From a7336b79cceb8bf91b60bb113d180864f37230bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AD=8F=E5=B0=91=E9=98=B3?= <786612630@qq.com> Date: Mon, 2 Sep 2024 18:09:57 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=B7=BB=E5=8A=A0=E5=BC=80=E5=AE=8C?= =?UTF-8?q?=E9=94=81=E4=B9=8B=E5=90=8E=E6=95=B0=E6=8D=AE=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=202=E3=80=81=E6=89=93=E5=8C=85apk=E4=B8=8A=E4=BC=A0=E5=88=B0pr?= =?UTF-8?q?e=E4=B8=8B=E8=BD=BD=E9=A1=B5=203=E3=80=81=E5=AE=8C=E6=88=90App?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E6=95=B0=E6=8D=AE=E8=AF=B7=E6=B1=82=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 12292 -> 14340 bytes ios/.DS_Store | Bin 8196 -> 8196 bytes ios/Podfile.lock | 6 - lib/app.dart | 6 - lib/login/login/starLock_login_page.dart | 11 +- lib/login/login/starLock_login_xhj_page.dart | 7 +- lib/main.dart | 11 - .../lockDetail/lockDetail_logic.dart | 236 +++++++++--------- .../lockMian/lockList/lockList_logic.dart | 2 +- .../lockMian/lockMain/lockMain_logic.dart | 65 +++-- lib/main/lockMian/lockMain/lockMain_page.dart | 29 ++- .../lockMain/xhj/lockMain_xhj_logic.dart | 12 +- lib/main_pre.dart | 1 - lib/mine/about/about_page.dart | 22 +- lib/mine/mall/lockMall_logic.dart | 8 +- lib/mine/mine/starLockMine_page.dart | 5 +- lib/mine/mineSet/mineSet/mineSet_logic.dart | 20 +- lib/mine/mineSet/mineSet/mineSet_page.dart | 7 +- .../advancedFeaturesWeb_logic.dart | 10 +- lib/network/request_interceptor_log.dart | 2 +- .../starLockApplication.dart | 2 +- lib/talk/call/audioPlayerTask.dart | 40 +-- lib/tools/appFirstEnterHandle.dart | 14 +- lib/tools/{ => wechat}/customer_tool.dart | 0 lib/tools/{ => wechat}/pay/wx_pay_tool.dart | 0 lib/tools/wechat/wechatManageTool.dart | 24 ++ lib/translations/translation_message.dart | 39 +-- pubspec.yaml | 6 +- 28 files changed, 296 insertions(+), 289 deletions(-) rename lib/tools/{ => wechat}/customer_tool.dart (100%) rename lib/tools/{ => wechat}/pay/wx_pay_tool.dart (100%) create mode 100644 lib/tools/wechat/wechatManageTool.dart diff --git a/.DS_Store b/.DS_Store index f0515be34db252cab1d7cf71da727b42cefb2272..e1898a6853e826f991dcb95c5a1570e7fcd7e794 100755 GIT binary patch delta 247 zcmZokXem%&U|?W$DortDU@!nOIe-{M3-ADmHUSO~QmdV_VT!NVl`3MQ1QpU+@3UZq-N?5T^Y~b9?&cVXL$TwMl@$6=-7GQx4or#= 1.8.0) - app_settings (5.1.1): - Flutter - - audio_service (0.0.1): - - Flutter - audio_session (0.0.1): - Flutter - audioplayers_darwin (0.0.1): @@ -166,7 +164,6 @@ DEPENDENCIES: - amap_flutter_location (from `.symlinks/plugins/amap_flutter_location/ios`) - amap_flutter_map (from `.symlinks/plugins/amap_flutter_map/ios`) - app_settings (from `.symlinks/plugins/app_settings/ios`) - - audio_service (from `.symlinks/plugins/audio_service/ios`) - audio_session (from `.symlinks/plugins/audio_session/ios`) - audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`) - auto_orientation (from `.symlinks/plugins/auto_orientation/ios`) @@ -237,8 +234,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/amap_flutter_map/ios" app_settings: :path: ".symlinks/plugins/app_settings/ios" - audio_service: - :path: ".symlinks/plugins/audio_service/ios" audio_session: :path: ".symlinks/plugins/audio_session/ios" audioplayers_darwin: @@ -318,7 +313,6 @@ SPEC CHECKSUMS: AMapFoundation: 9885c48fc3a78fdfb84a0299a2293e56ea3c9fec AMapLocation: 5248aec2455ebb5d104b367813c946430a2ee033 app_settings: 017320c6a680cdc94c799949d95b84cb69389ebc - audio_service: f509d65da41b9521a61f1c404dd58651f265a567 audio_session: 088d2483ebd1dc43f51d253d4a1c517d9a2e7207 audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40 auto_orientation: 102ed811a5938d52c86520ddd7ecd3a126b5d39d diff --git a/lib/app.dart b/lib/app.dart index ae016819..247d211b 100755 --- a/lib/app.dart +++ b/lib/app.dart @@ -3,18 +3,12 @@ import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; -import 'package:permission_handler/permission_handler.dart'; -import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/blue/blue_manage.dart'; import 'package:star_lock/flavors.dart'; -import 'package:star_lock/login/login/app_get_version.dart'; import 'package:star_lock/main/lockMian/lockMain/lockMain_logic.dart'; -import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/appFirstEnterHandle.dart'; import 'package:star_lock/tools/app_manager.dart'; import 'package:star_lock/tools/bindings/app_binding.dart'; -import 'package:star_lock/tools/customer_tool.dart'; -import 'package:star_lock/tools/pay/wx_pay_tool.dart'; import 'package:star_lock/tools/storage.dart'; import 'package:star_lock/translations/app_dept.dart'; diff --git a/lib/login/login/starLock_login_page.dart b/lib/login/login/starLock_login_page.dart index f820cf49..d381196c 100755 --- a/lib/login/login/starLock_login_page.dart +++ b/lib/login/login/starLock_login_page.dart @@ -6,7 +6,7 @@ import 'package:get/get.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/login/login/starLock_login_state.dart'; import 'package:star_lock/tools/appFirstEnterHandle.dart'; -import 'package:star_lock/tools/customer_tool.dart'; +import 'package:star_lock/tools/wechat/customer_tool.dart'; import 'package:star_lock/tools/storage.dart'; import '../../appRouters.dart'; @@ -16,6 +16,7 @@ import '../../tools/commonItem.dart'; import '../../tools/submitBtn.dart'; import '../../tools/tf_loginInput.dart'; import '../../tools/titleAppBar.dart'; +import '../../tools/wechat/wechatManageTool.dart'; import 'starLock_login_logic.dart'; class StarLockLoginPage extends StatefulWidget { @@ -47,9 +48,11 @@ class _StarLockLoginPageState extends State { haveBack: false, backgroundColor: AppColors.mainColor, actionsList: [ - const IconButton( - onPressed: CustomerTool.openCustomerService, - icon: Icon( + IconButton( + onPressed: (){ + WechatManageTool.getAppInfo(CustomerTool.openCustomerService); + }, + icon: const Icon( Icons.support_agent, color: Colors.white, )), diff --git a/lib/login/login/starLock_login_xhj_page.dart b/lib/login/login/starLock_login_xhj_page.dart index bf62388f..7e05b386 100755 --- a/lib/login/login/starLock_login_xhj_page.dart +++ b/lib/login/login/starLock_login_xhj_page.dart @@ -6,7 +6,7 @@ import 'package:get/get.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/login/login/starLock_login_state.dart'; import 'package:star_lock/tools/appFirstEnterHandle.dart'; -import 'package:star_lock/tools/customer_tool.dart'; +import 'package:star_lock/tools/wechat/customer_tool.dart'; import 'package:star_lock/tools/storage.dart'; import '../../appRouters.dart'; @@ -14,6 +14,7 @@ import '../../app_settings/app_colors.dart'; import '../../common/XSConstantMacro/XSConstantMacro.dart'; import '../../tools/submitBtn.dart'; import '../../tools/tf_loginInput.dart'; +import '../../tools/wechat/wechatManageTool.dart'; import 'starLock_login_logic.dart'; class StarLockLoginXHJPage extends StatefulWidget { @@ -64,7 +65,9 @@ class _StarLockLoginPageState extends State { ), ), IconButton( - onPressed: CustomerTool.openCustomerService, + onPressed: (){ + WechatManageTool.getAppInfo(CustomerTool.openCustomerService); + }, icon: Icon( Icons.support_agent, color: AppColors.mainColor, diff --git a/lib/main.dart b/lib/main.dart index 7c888378..a9d4110c 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,14 +7,11 @@ import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:path/path.dart' as path; import 'package:star_lock/flavors.dart'; -import 'package:star_lock/login/login/app_get_version.dart'; import 'package:star_lock/mine/about/debug/debug_tool.dart'; import 'package:star_lock/network/api_provider.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/bugly/bugly_tool.dart'; -import 'package:star_lock/tools/customer_tool.dart'; import 'package:star_lock/tools/device_info_service.dart'; -import 'package:star_lock/tools/pay/wx_pay_tool.dart'; import 'package:star_lock/tools/platform_info_services.dart'; import 'package:star_lock/tools/push/xs_jPhush.dart'; import 'package:star_lock/tools/storage.dart'; @@ -36,14 +33,6 @@ FutureOr main() async { final bool isLogin = await getLoginStatus(); if (isLogin) { await privacySDKInitialization(); - Future.delayed(const Duration(milliseconds: 500), () async { - // AppLog.log('main函数调用了获取App信息接口'); - final GetAppInfo entity = await ApiRepository.to.getAppInfo(); - CustomerTool.init(entity.data?.wechatServiceUrl ?? ''); - if (entity.data?.appSiteUrl != null) { - WxPayTool.setAssociationUrl(entity.data!.appSiteUrl!); - } - }); } WidgetsBinding.instance.addPostFrameCallback((_) async { diff --git a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index dd0bf91e..c8dfd0cb 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -18,6 +18,7 @@ import 'package:star_lock/widget/permission/permission_dialog.dart'; import '../../../app_settings/app_settings.dart'; import '../../../blue/blue_manage.dart'; import '../../../blue/io_protocol/io_openLock.dart'; +import '../../../blue/io_protocol/io_referEventRecordTime.dart'; import '../../../blue/io_reply.dart'; import '../../../blue/io_tool/io_tool.dart'; import '../../../blue/io_tool/manager_event_bus.dart'; @@ -28,6 +29,7 @@ import '../../../tools/commonDataManage.dart'; import '../../../tools/eventBusEventManage.dart'; import '../../../tools/storage.dart'; import '../lockOperatingRecord/keyOperationRecord_entity.dart'; +import '../lockOperatingRecord/lockOperatingRecordGetLastRecordTime_entity.dart'; import '../lockSet/basicInformation/uploadElectricQuantity/uploadElectricQuantity_entity.dart'; import 'lockDetail_state.dart'; import 'lockNetToken_entity.dart'; @@ -41,18 +43,17 @@ class LockDetailLogic extends BaseGetXController { // 监听设备返回的数据 void initReplySubscription() { - state.replySubscription = - EventBusManager().eventBus!.on().listen((Reply reply) async { + state.replySubscription = EventBusManager().eventBus!.on().listen((Reply reply) async { // 开门 if (reply is OpenDoorReply && state.ifCurrentScreen.value == true) { _replyOpenLock(reply); } // 开完锁之后上传记录 - // if (reply is SenderReferEventRecordTimeReply && - // state.ifCurrentScreen.value == true) { - // _replyReferEventRecordTime(reply); - // } + if (reply is SenderReferEventRecordTimeReply && + state.ifCurrentScreen.value == true) { + _replyReferEventRecordTime(reply); + } }); } @@ -95,7 +96,7 @@ class LockDetailLogic extends BaseGetXController { state.animationController!.stop(); //锁数据更新 - // getLockRecordLastUploadDataTime(); + getLockRecordLastUploadDataTime(); break; case 0x06: //无权限 @@ -178,7 +179,6 @@ class LockDetailLogic extends BaseGetXController { } } - Future loadData({ required LockListInfoItemEntity lockListInfoItemEntity,required bool isOnlyOneData}) async { state.keyInfos.value = lockListInfoItemEntity; CommonDataManage().currentLockUserNo = state.keyInfos.value.lockUserNo!; @@ -254,71 +254,70 @@ class LockDetailLogic extends BaseGetXController { } // 根据时间查解析数据 - // Future _replyReferEventRecordTime(Reply reply) async { - // final int status = reply.data[2]; - // switch (status) { - // case 0x00: - // //成功 - // final int dataLength = (reply.data[5] << 8) + reply.data[6]; - // AppLog.log('dataLength:$dataLength'); - // if (dataLength > 0) { - // reply.data.removeRange(0, 7); - // // 把得到的数据按17个字节分割成数组 然后塞进一个新的数组里面 - // if (reply.data.length < 17) { - // return; - // } - // final List> getList = splitList(reply.data, 17); - // AppLog.log('getList:$getList'); - // final List uploadList = []; - // for (int i = 0; i < getList.length; i++) { - // final List indexList = getList[i]; - // AppLog.log('indexList:$indexList'); - // final Map indexMap = {}; - // indexMap['type'] = indexList[0].toString(); - // int operateDate = 0; - // // if (indexList[0] == 2) { - // final List passwordData = indexList.sublist(7, 17); - // final String password = utf8String(passwordData); - // AppLog.log('passwordData:$passwordData password:$password'); - // indexMap['user'] = password.toString(); - // // } else { - // // final int userNo = (indexList[1] * 256) + indexList[2]; - // // indexMap['user'] = userNo.toString(); - // // } - // - // indexMap['success'] = '1'; - // - // final int time = (0xff & indexList[3]) << 24 | - // (0xff & indexList[4]) << 16 | - // (0xff & indexList[5]) << 8 | - // (0xFF & indexList[6]); - // operateDate = time * 1000; - // indexMap['date'] = '$operateDate'; - // uploadList.add(indexMap); - // - // if (i == getList.length - 1) { - // //设置最后的时间戳 - // state.operateDate = operateDate; - // } - // } - // lockRecordUploadData(uploadList); - // - // if (dataLength == state.logCountPage) { - // senderReferEventRecordTime(); - // } else { - // await blueManageDisconnect(); - // } - // } - // break; - // case 0x06: - // //无权限 - // blueManageDisconnect(); - // break; - // default: - // blueManageDisconnect(); - // break; - // } - // } + Future _replyReferEventRecordTime(Reply reply) async { + final int status = reply.data[2]; + switch (status) { + case 0x00: + //成功 + final int dataLength = (reply.data[5] << 8) + reply.data[6]; + AppLog.log('dataLength:$dataLength'); + if (dataLength > 0) { + reply.data.removeRange(0, 7); + // 把得到的数据按17个字节分割成数组 然后塞进一个新的数组里面 + if (reply.data.length < 17) { + return; + } + final List> getList = splitList(reply.data, 17); + AppLog.log('getList:$getList'); + final List uploadList = []; + for (int i = 0; i < getList.length; i++) { + final List indexList = getList[i]; + // AppLog.log("indexList:$indexList"); + final Map indexMap = {}; + indexMap['type'] = indexList[0].toString(); + + final int userNo = (indexList[1] * 256) + indexList[2]; + indexMap['user'] = userNo.toString(); + // AppLog.log('userNouserNouserNouserNo:$userNo'); + + final List passwordData = indexList.sublist(7, 17); + final String password = utf8String(passwordData); + indexMap['password'] = password.toString(); + // AppLog.log('passwordpasswordpassword:$password'); + + indexMap['success'] = '1'; + + final int time = (0xff & indexList[3]) << 24 | + (0xff & indexList[4]) << 16 | + (0xff & indexList[5]) << 8 | + (0xFF & indexList[6]); + indexMap['date'] = '${time * 1000}'; + uploadList.add(indexMap); + + final int operateDate = time * 1000; + if (i == getList.length - 1) { + //设置最后的时间戳 + state.operateDate = operateDate; + } + } + lockRecordUploadData(uploadList); + + if (dataLength == state.logCountPage) { + senderReferEventRecordTime(); + } else { + await blueManageDisconnect(); + } + } + break; + case 0x06: + //无权限 + blueManageDisconnect(); + break; + default: + blueManageDisconnect(); + break; + } + } // 点击开门事件 Future openDoorAction() async { @@ -374,42 +373,43 @@ class LockDetailLogic extends BaseGetXController { } // 查询事件记录(时间查询) - // void senderReferEventRecordTime() { - // showBlueConnetctToastTimer( - // isShowBlueConnetctToast: false, - // action: () { - // blueManageDisconnect(); - // }); - // BlueManage().blueSendData(BlueManage().connectDeviceName, - // (BluetoothConnectionState connectionState) async { - // if (connectionState == BluetoothConnectionState.connected) { - // final List? privateKey = - // await Storage.getStringList(saveBluePrivateKey); - // final List getPrivateKeyList = - // changeStringListToIntList(privateKey!); - // - // final List? token = await Storage.getStringList(saveBlueToken); - // final List getTokenList = changeStringListToIntList(token!); - // - // final List? publicKey = - // await Storage.getStringList(saveBluePublicKey); - // final List getPublicKeyList = - // changeStringListToIntList(publicKey!); - // - // IoSenderManage.senderReferEventRecordTimeCommand( - // keyID: BlueManage().connectDeviceName, - // userID: await Storage.getUid(), - // logsCount: state.logCountPage, - // // time:DateTime.now().millisecondsSinceEpoch~/1000, - // time: state.operateDate, - // token: getTokenList, - // needAuthor: 1, - // publicKey: getPublicKeyList, - // privateKey: getPrivateKeyList, - // ); - // } - // }); - // } + void senderReferEventRecordTime() { + showBlueConnetctToastTimer( + isShowBlueConnetctToast: false, + action: () { + blueManageDisconnect(); + }); + BlueManage().blueSendData(BlueManage().connectDeviceName, + (BluetoothConnectionState connectionState) async { + if (connectionState == BluetoothConnectionState.connected) { + final List? privateKey = + await Storage.getStringList(saveBluePrivateKey); + final List getPrivateKeyList = + changeStringListToIntList(privateKey!); + + final List? token = await Storage.getStringList(saveBlueToken); + final List getTokenList = changeStringListToIntList(token!); + + final List? publicKey = + await Storage.getStringList(saveBluePublicKey); + final List getPublicKeyList = + changeStringListToIntList(publicKey!); + + IoSenderManage.senderReferEventRecordTimeCommand( + keyID: BlueManage().connectDeviceName, + userID: await Storage.getUid(), + logsCount: state.logCountPage, + // time:DateTime.now().millisecondsSinceEpoch~/1000, + time: state.operateDate, + currentDate: getUTCNetTime(), + token: getTokenList, + needAuthor: 1, + publicKey: getPublicKeyList, + privateKey: getPrivateKeyList, + ); + } + }); + } // 从服务器获取锁的时间 开锁时传入 Future getServerDatetime() async { @@ -467,15 +467,15 @@ class LockDetailLogic extends BaseGetXController { } // 查询锁记录最后时间 - // Future getLockRecordLastUploadDataTime() async { - // final LockOperatingRecordGetLastRecordTimeEntity entity = - // await ApiRepository.to.getLockRecordLastUploadDataTime( - // lockId: state.keyInfos.value.lockId.toString()); - // if (entity.errorCode!.codeIsSuccessful) { - // state.operateDate = entity.data!.operateDate! ~/ 1000; - // senderReferEventRecordTime(); - // } - // } + Future getLockRecordLastUploadDataTime() async { + final LockOperatingRecordGetLastRecordTimeEntity entity = + await ApiRepository.to.getLockRecordLastUploadDataTime( + lockId: state.keyInfos.value.lockId.toString()); + if (entity.errorCode!.codeIsSuccessful) { + state.operateDate = entity.data!.operateDate! ~/ 1000; + senderReferEventRecordTime(); + } + } // 操作记录上传 Future lockRecordUploadData(List list) async { diff --git a/lib/main/lockMian/lockList/lockList_logic.dart b/lib/main/lockMian/lockList/lockList_logic.dart index f8e324c9..fd99aade 100755 --- a/lib/main/lockMian/lockList/lockList_logic.dart +++ b/lib/main/lockMian/lockList/lockList_logic.dart @@ -323,7 +323,7 @@ class LockListLogic extends BaseGetXController { @override void onInit() { super.onInit(); - AppLog.log('onInit调用了 setLockListInfoGroupEntity'); + // AppLog.log('onInit调用了 setLockListInfoGroupEntity'); setLockListInfoGroupEntity(entity!); } diff --git a/lib/main/lockMian/lockMain/lockMain_logic.dart b/lib/main/lockMian/lockMain/lockMain_logic.dart index fd1305c4..5aabde5a 100755 --- a/lib/main/lockMian/lockMain/lockMain_logic.dart +++ b/lib/main/lockMian/lockMain/lockMain_logic.dart @@ -41,7 +41,7 @@ class LockMainLogic extends BaseGetXController { if (entity.errorCode!.codeIsSuccessful) { // AppLog.log('请求列表调用 loadMainDataLogic'); await loadMainDataLogic(entity.data!); - updateZoneOffsetsAndLanguages(); + // updateZoneOffsetsAndLanguages(); } return entity; } @@ -94,24 +94,24 @@ class LockMainLogic extends BaseGetXController { } /// 获取联网类型 - Future getConnectType() async { - final ConnectivityResult connectResult = - await Connectivity().checkConnectivity(); - if (connectResult == ConnectivityResult.mobile) { - // _netType = "4G"; - state.networkConnectionStatus.value = 1; - AppLog.log('网络连接: 4G 4G 4G 4G 4G'); - } else if (connectResult == ConnectivityResult.wifi) { - // _netType = "wifi"; - state.networkConnectionStatus.value = 1; - AppLog.log('网络连接: wifi wifi wifi wifi wifi'); - } else { - // _netType = "未连接"; - state.networkConnectionStatus.value = 0; - AppLog.log('网络连接: 未连接 未连接 未连接 未连接 未连接'); - // showToast("网络访问失败,请检查网络是否正常"); - } - } + // Future _getConnectType() async { + // final ConnectivityResult connectResult = + // await Connectivity().checkConnectivity(); + // if (connectResult == ConnectivityResult.mobile) { + // // _netType = "4G"; + // state.networkConnectionStatus.value = 1; + // AppLog.log('网络连接: 4G 4G 4G 4G 4G'); + // } else if (connectResult == ConnectivityResult.wifi) { + // // _netType = "wifi"; + // state.networkConnectionStatus.value = 1; + // AppLog.log('网络连接: wifi wifi wifi wifi wifi'); + // } else { + // // _netType = "未连接"; + // state.networkConnectionStatus.value = 0; + // AppLog.log('网络连接: 未连接 未连接 未连接 未连接 未连接'); + // // showToast("网络访问失败,请检查网络是否正常"); + // } + // } /// 判断网络是否连接 Future isConnected() async { @@ -121,19 +121,18 @@ class LockMainLogic extends BaseGetXController { } /// 设置网络切换监听 - Future connectListener() async { - Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { - AppLog.log('设置网络切换监听:$result'); - if (state.networkConnectionStatus.value == 0 && - result != ConnectivityResult.none) { - // 从无网络到有网络 - state.networkConnectionStatus.value = 1; - getStarLockInfo(isUnShowLoading: true); - } else if (result == ConnectivityResult.none) { - state.networkConnectionStatus.value = 0; - } - }); - } + // Future connectListener() async { + // Connectivity().onConnectivityChanged.listen((ConnectivityResult result) { + // AppLog.log('设置网络切换监听:$result'); + // if (state.networkConnectionStatus.value == 0 && result != ConnectivityResult.none) { + // // 从无网络到有网络 + // state.networkConnectionStatus.value = 1; + // getStarLockInfo(isUnShowLoading: true); + // } else if (result == ConnectivityResult.none) { + // state.networkConnectionStatus.value = 0; + // } + // }); + // } /// 判断是否有网络 Future judgeTheNetwork() async { @@ -300,7 +299,7 @@ class LockMainLogic extends BaseGetXController { super.onInit(); checkWhetherPushIsEnabled(); _initSubscription(); - connectListener(); + // connectListener(); // AppLog.log('onInit() updateZoneOffsetsAndLanguages'); // updateZoneOffsetsAndLanguages(); diff --git a/lib/main/lockMian/lockMain/lockMain_page.dart b/lib/main/lockMian/lockMain/lockMain_page.dart index 6bf9e5ed..3bf66ccf 100755 --- a/lib/main/lockMian/lockMain/lockMain_page.dart +++ b/lib/main/lockMian/lockMain/lockMain_page.dart @@ -34,8 +34,7 @@ class StarLockMainPage extends StatefulWidget { State createState() => _StarLockMainPageState(); } -class _StarLockMainPageState extends State - with BaseWidget, AutomaticKeepAliveClientMixin { +class _StarLockMainPageState extends State with BaseWidget, AutomaticKeepAliveClientMixin, WidgetsBindingObserver { final LockMainLogic logic = Get.put(LockMainLogic()); final LockMainState state = Get.find().state; @@ -243,6 +242,32 @@ class _StarLockMainPageState extends State }); } + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + // AppLog.log('App--->state:$state'); + switch (state) { + case AppLifecycleState.inactive: + // AppLog.log('App--->进入非活动状态'); + break; + case AppLifecycleState.paused: + // AppLog.log('App--->进入后台'); + BlueManage().disconnect(); + break; + case AppLifecycleState.resumed: + // AppLog.log('App--->进入前台'); + logic.pageNo = 1; + getHttpData(); + break; + case AppLifecycleState.detached: + // AppLog.log('App--->挂起'); + break; + case AppLifecycleState.hidden: + // AppLog.log('App--->隐藏'); + break; + } + } + @override void dispose() { super.dispose(); diff --git a/lib/main/lockMian/lockMain/xhj/lockMain_xhj_logic.dart b/lib/main/lockMian/lockMain/xhj/lockMain_xhj_logic.dart index ace7e2d9..45473267 100755 --- a/lib/main/lockMian/lockMain/xhj/lockMain_xhj_logic.dart +++ b/lib/main/lockMian/lockMain/xhj/lockMain_xhj_logic.dart @@ -27,9 +27,15 @@ class LockMainXHJLogic extends BaseGetXController { if (entity.errorCode!.codeIsSuccessful) { final String languageCodeAndCountryCode = entity.data!.lang ?? 'zh-CN'; - final List parts = languageCodeAndCountryCode.split('-'); - final Locale locale = Locale(parts[0], parts[1]); - Get.updateLocale(locale); + if(languageCodeAndCountryCode.contains('-')){ + final List parts = languageCodeAndCountryCode.split('-'); + final Locale locale = Locale(parts[0], parts[1]); + Get.updateLocale(locale); + }else if(languageCodeAndCountryCode.contains('_')){ + final List parts = languageCodeAndCountryCode.split('_'); + final Locale locale = Locale(parts[0], parts[1]); + Get.updateLocale(locale); + } Storage.setBool(saveIsVip, entity.data!.isVip == 1); if (entity.data!.deviceId != null) { diff --git a/lib/main_pre.dart b/lib/main_pre.dart index 2039ea8a..27329ef8 100755 --- a/lib/main_pre.dart +++ b/lib/main_pre.dart @@ -1,4 +1,3 @@ -import 'app_settings/app_settings.dart'; import 'flavors.dart'; import 'main.dart' as runner; diff --git a/lib/mine/about/about_page.dart b/lib/mine/about/about_page.dart index dad382d2..98d1318c 100755 --- a/lib/mine/about/about_page.dart +++ b/lib/mine/about/about_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -97,7 +98,7 @@ class _AboutPageState extends State { endIndent: 20.w, ), CommonItem( - leftTitel: '隐私政策'.tr, + leftTitel: '用户协议'.tr, rightTitle: '', isHaveLine: false, isHaveDirection: true, @@ -210,14 +211,17 @@ class _AboutPageState extends State { ), ), ), - ClipRRect( - borderRadius: BorderRadius.circular(20.r), - child: Image.asset( - F.sw( - skyCall: () => 'images/icon_main_sky_1024.png', - xhjCall: () => 'images/icon_main_xhj_1024.png'), - width: 160.w, - height: 160.w), + GestureDetector( + onTap: logic.handleTap, + child: ClipRRect( + borderRadius: BorderRadius.circular(20.r), + child: Image.asset( + F.sw( + skyCall: () => 'images/icon_main_sky_1024.png', + xhjCall: () => 'images/icon_main_xhj_1024.png'), + width: 160.w, + height: 160.w), + ), ), SizedBox(height: 20.h), Text( diff --git a/lib/mine/mall/lockMall_logic.dart b/lib/mine/mall/lockMall_logic.dart index a9f03310..c9c6e204 100755 --- a/lib/mine/mall/lockMall_logic.dart +++ b/lib/mine/mall/lockMall_logic.dart @@ -9,10 +9,11 @@ import 'package:star_lock/mine/mall/lockMall_entity.dart'; import 'package:star_lock/mine/mall/lockMall_state.dart'; import 'package:star_lock/mine/mall/webview/webview_logic.dart'; import 'package:star_lock/network/api_repository.dart'; -import 'package:star_lock/tools/pay/wx_pay_tool.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../../tools/baseGetXController.dart'; +import '../../tools/wechat/pay/wx_pay_tool.dart'; +import '../../tools/wechat/wechatManageTool.dart'; class LockMallLogic extends BaseGetXController { late LockMallState state; @@ -73,7 +74,10 @@ class LockMallLogic extends BaseGetXController { switch (action) { case 'WechatPayParams': //微信支付 - wxPay(data, callFun); + WechatManageTool.getAppInfo(() { + wxPay(data, callFun); + }); + // wxPay(data, callFun); break; } } diff --git a/lib/mine/mine/starLockMine_page.dart b/lib/mine/mine/starLockMine_page.dart index f7c3873d..e1e98bf1 100755 --- a/lib/mine/mine/starLockMine_page.dart +++ b/lib/mine/mine/starLockMine_page.dart @@ -5,13 +5,14 @@ import 'package:get/get.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/mine/mine/starLockMine_state.dart'; -import 'package:star_lock/tools/customer_tool.dart'; +import 'package:star_lock/tools/wechat/customer_tool.dart'; import '../../appRouters.dart'; import '../../app_settings/app_colors.dart'; import '../../baseWidget.dart'; import '../../tools/customNetworkImage.dart'; import '../../tools/submitBtn.dart'; +import '../../tools/wechat/wechatManageTool.dart'; import 'starLockMine_logic.dart'; class StarLockMinePage extends StatefulWidget { @@ -207,7 +208,7 @@ class StarLockMinePageState extends State with BaseWidget { mineItem('images/mine/icon_mine_main_shoppingcart.png', '客服'.tr, () { Get.back(); - CustomerTool.openCustomerService(); + WechatManageTool.getAppInfo(CustomerTool.openCustomerService); }), mineItem('images/mine/icon_mine_main_about.png', '关于'.tr, () { Get.back(); diff --git a/lib/mine/mineSet/mineSet/mineSet_logic.dart b/lib/mine/mineSet/mineSet/mineSet_logic.dart index 0d4a5fff..29eacf09 100755 --- a/lib/mine/mineSet/mineSet/mineSet_logic.dart +++ b/lib/mine/mineSet/mineSet/mineSet_logic.dart @@ -102,8 +102,8 @@ class MineSetLogic extends BaseGetXController { //退出登录请求 Future userLogoutRequest() async { - var getPushDeviceID = ''; - await Storage.getString(pushDeviceID).then((value) { + String getPushDeviceID = ''; + await Storage.getString(pushDeviceID).then((String? value) { if (value != null && value.isNotEmpty) { getPushDeviceID = value; } @@ -118,7 +118,7 @@ class MineSetLogic extends BaseGetXController { BlueManage().disconnect(); XSJPushProvider().initLocalNotification(isCancelLocalPush: true); - Get.offNamedUntil(Routers.starLockLoginPage, (route) => false); + Get.offNamedUntil(Routers.starLockLoginPage, (Route route) => false); } } @@ -129,7 +129,7 @@ class MineSetLogic extends BaseGetXController { //更新触摸开锁 Future updateTouchUnlockRequest() async { - ExpireLockListEntity entity = await ApiRepository.to + final ExpireLockListEntity entity = await ApiRepository.to .setTouchUnlockFlag(state.isTouchUnlock.value == true ? '1' : '2'); if (entity.errorCode!.codeIsSuccessful) { showToast('设置成功'.tr); @@ -141,16 +141,18 @@ class MineSetLogic extends BaseGetXController { StreamSubscription? _getNumberEvent; void _initLoadDataAction() { // 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus - _getNumberEvent = eventBus.on().listen((event) { + _getNumberEvent = eventBus.on().listen((ChangeLanguageBlockLastLanguageEvent event) { state.currentLanguage.value = _getCurrentLanguage(); }); } String _getCurrentLanguage() { - String currentLanguage = ExtensionLanguageType.fromLocale(appDept.deptSupportedLocales.where((Locale element) => - element.languageCode == StoreService.to.getLanguageCode()).first).lanTitle; - // AppLog.log('currentLanguagecurrentLanguage:$currentLanguage StoreService.to.getLanguageCode():${StoreService.to.getLanguageCode()}'); - return currentLanguage ??''; + String? languageCode = StoreService.to.getLanguageCode(); + if(languageCode!.isEmpty){ + languageCode = Get.deviceLocale!.languageCode; + } + final String currentLanguage = ExtensionLanguageType.fromLocale(appDept.deptSupportedLocales.where((Locale element) => element.languageCode == languageCode).first).lanTitle; + return currentLanguage; } @override diff --git a/lib/mine/mineSet/mineSet/mineSet_page.dart b/lib/mine/mineSet/mineSet/mineSet_page.dart index adce2eec..afbc1383 100755 --- a/lib/mine/mineSet/mineSet/mineSet_page.dart +++ b/lib/mine/mineSet/mineSet/mineSet_page.dart @@ -10,13 +10,14 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/mine/mineSet/mineSet/mineSet_logic.dart'; import 'package:star_lock/mine/mineSet/mineSet/mineSet_state.dart'; -import 'package:star_lock/tools/customer_tool.dart'; +import 'package:star_lock/tools/wechat/customer_tool.dart'; import '../../../appRouters.dart'; import '../../../app_settings/app_colors.dart'; import '../../../tools/commonItem.dart'; import '../../../tools/showTipView.dart'; import '../../../tools/submitBtn.dart'; import '../../../tools/titleAppBar.dart'; +import '../../../tools/wechat/wechatManageTool.dart'; import '../../../translations/trans_lib.dart'; class MineSetPage extends StatefulWidget { @@ -366,7 +367,9 @@ class _MineSetPageState extends State leftTitel: '客服'.tr, isHaveLine: widget.showAbout, isHaveDirection: true, - action: CustomerTool.openCustomerService, + action: (){ + WechatManageTool.getAppInfo(CustomerTool.openCustomerService); + }, ), if (widget.showAbout) CommonItem( diff --git a/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_logic.dart b/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_logic.dart index ea084092..ab7d83f8 100755 --- a/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_logic.dart +++ b/lib/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_logic.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'package:flutter/services.dart'; import 'package:fluwx/fluwx.dart'; import 'package:get/get.dart'; -import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/mine/mall/webview/webview_logic.dart'; @@ -11,9 +10,11 @@ import 'package:star_lock/mine/valueAddedServices/advancedFeaturesWeb/advancedFe import 'package:star_lock/mine/valueAddedServices/advancedFeaturesWeb/advancedFeaturesWeb_state.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/baseGetXController.dart'; -import 'package:star_lock/tools/pay/wx_pay_tool.dart'; import 'package:webview_flutter/webview_flutter.dart'; +import '../../../tools/wechat/pay/wx_pay_tool.dart'; +import '../../../tools/wechat/wechatManageTool.dart'; + class AdvancedFeaturesWebLogic extends BaseGetXController { late AdvancedFeaturesWebState state = AdvancedFeaturesWebState(); @@ -86,7 +87,10 @@ class AdvancedFeaturesWebLogic extends BaseGetXController { switch (action) { case 'WechatPayParams': //微信支付 - wxPay(data, callFun); + WechatManageTool.getAppInfo(() { + wxPay(data, callFun); + }); + // wxPay(data, callFun); break; } } diff --git a/lib/network/request_interceptor_log.dart b/lib/network/request_interceptor_log.dart index c8f9436f..bae49843 100755 --- a/lib/network/request_interceptor_log.dart +++ b/lib/network/request_interceptor_log.dart @@ -5,6 +5,6 @@ import 'package:star_lock/app_settings/app_settings.dart'; FutureOr requestLogInterceptor(Request request) async { // AppLog.log('GET HTTP REQUEST \n${request.url} \n${request.headers} ${request.toString()} '); - AppLog.log('请求头:${request.headers.toString()}'); + // AppLog.log('请求头:${request.headers.toString()}'); return request; } diff --git a/lib/starLockApplication/starLockApplication.dart b/lib/starLockApplication/starLockApplication.dart index adc72d5d..12d1fb10 100755 --- a/lib/starLockApplication/starLockApplication.dart +++ b/lib/starLockApplication/starLockApplication.dart @@ -8,7 +8,7 @@ import 'package:star_lock/main/lockMian/lockMain/xhj/lockMain_xhj_page.dart'; import 'package:star_lock/mine/about/debug/debug_tool.dart'; import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/tools/appFirstEnterHandle.dart'; -import 'package:star_lock/tools/customer_tool.dart'; +import 'package:star_lock/tools/wechat/customer_tool.dart'; import 'package:star_lock/tools/storage.dart'; import '../main/lockMian/lockMain/lockMain_page.dart'; diff --git a/lib/talk/call/audioPlayerTask.dart b/lib/talk/call/audioPlayerTask.dart index bc7a3a7e..475e17ac 100755 --- a/lib/talk/call/audioPlayerTask.dart +++ b/lib/talk/call/audioPlayerTask.dart @@ -1,22 +1,22 @@ // Audio player task implementation -import 'package:audio_service/audio_service.dart'; +// import 'package:audio_service/audio_service.dart'; -class AudioPlayerTask extends BackgroundAudioTask { - @override - Future onStart(Map? params) async { - // Load and play audio here - // Example: - // AudioPlayer audioPlayer = AudioPlayer(); - // await audioPlayer.play('path_to_audio.mp3'); - } - - @override - Future onStop() async { - // Stop audio playback and clean up resources - } - - @override - Future onPause() async { - // Pause audio playback - } -} +// class AudioPlayerTask extends BackgroundAudioTask { +// @override +// Future onStart(Map? params) async { +// // Load and play audio here +// // Example: +// // AudioPlayer audioPlayer = AudioPlayer(); +// // await audioPlayer.play('path_to_audio.mp3'); +// } +// +// @override +// Future onStop() async { +// // Stop audio playback and clean up resources +// } +// +// @override +// Future onPause() async { +// // Pause audio playback +// } +// } diff --git a/lib/tools/appFirstEnterHandle.dart b/lib/tools/appFirstEnterHandle.dart index 909baf93..e6d63573 100755 --- a/lib/tools/appFirstEnterHandle.dart +++ b/lib/tools/appFirstEnterHandle.dart @@ -6,20 +6,16 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:star_lock/appRouters.dart'; import 'package:star_lock/app_settings/app_colors.dart'; -import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/login/login/app_get_version.dart'; import 'package:star_lock/login/login/starLock_login_logic.dart'; import 'package:star_lock/main.dart'; import 'package:star_lock/network/api_repository.dart'; -import 'package:star_lock/tools/customer_tool.dart'; -import 'package:star_lock/tools/pay/wx_pay_tool.dart'; import 'package:star_lock/tools/storage.dart'; +import 'package:star_lock/tools/wechat/customer_tool.dart'; import '../versionUndate/versionUndateTool.dart'; -import 'bugly/bugly_tool.dart'; -import 'push/xs_jPhush.dart'; class AppFirstEnterHandle { Future getAppFirstEnter(String flagStr) async { @@ -29,7 +25,6 @@ class AppFirstEnterHandle { if (getFlag != isAgreePrivacy) { await showPrivacyAgreementAlert(); } - getAppInfo(); await privacySDKInitialization(); if (Get.isRegistered()) { Get.find().flushedDeviceInfo(); @@ -69,13 +64,6 @@ class AppFirstEnterHandle { ); } - Future getAppInfo() async { - // AppLog.log('AppFirstEnterHandle调用了获取App信息接口'); - final GetAppInfo entity = await ApiRepository.to.getAppInfo(); - CustomerTool.init(entity.data?.wechatServiceUrl ?? ''); - WxPayTool.setAssociationUrl(entity.data!.appSiteUrl!); - } - //默认布局 Widget _defaultPrivacyAgreementAlert(BuildContext context) { return CupertinoAlertDialog( diff --git a/lib/tools/customer_tool.dart b/lib/tools/wechat/customer_tool.dart similarity index 100% rename from lib/tools/customer_tool.dart rename to lib/tools/wechat/customer_tool.dart diff --git a/lib/tools/pay/wx_pay_tool.dart b/lib/tools/wechat/pay/wx_pay_tool.dart similarity index 100% rename from lib/tools/pay/wx_pay_tool.dart rename to lib/tools/wechat/pay/wx_pay_tool.dart diff --git a/lib/tools/wechat/wechatManageTool.dart b/lib/tools/wechat/wechatManageTool.dart new file mode 100644 index 00000000..9f77c6dc --- /dev/null +++ b/lib/tools/wechat/wechatManageTool.dart @@ -0,0 +1,24 @@ + + +import '../../login/login/app_get_version.dart'; +import '../../network/api_repository.dart'; +import 'customer_tool.dart'; +import 'pay/wx_pay_tool.dart'; + +class WechatManageTool { + static void init(String wechatServiceUrl) { + // CustomerTool.init(wechatServiceUrl); + } + + static Future getAppInfo(void Function() action) async { + // AppLog.log('AppFirstEnterHandle调用了获取App信息接口'); + final GetAppInfo entity = await ApiRepository.to.getAppInfo(); + if(entity.errorCode == 0) { + CustomerTool.init(entity.data?.wechatServiceUrl ?? ''); + WxPayTool.setAssociationUrl(entity.data!.appSiteUrl!); + action(); + } + + } + +} \ No newline at end of file diff --git a/lib/translations/translation_message.dart b/lib/translations/translation_message.dart index a15d7d66..42a47822 100755 --- a/lib/translations/translation_message.dart +++ b/lib/translations/translation_message.dart @@ -2,47 +2,10 @@ part of lib_trans; class TranslationMessage extends Translations { - // LAN_ZH_CN="zh" # 简体中文 - // LAN_EN_US="en" # 英文 - // LAN_ZH_TW="tw" # 繁体中文 - // LAN_Fr_FR="fr" # 法语 - // LAN_RU_RU="ru" # 俄语 - // LAN_DE_DE="de" # 德语 - // LAN_ZH_JA="ja" # 日语 - // LAN_ZH_KO="ko" # 韩语 - // LAN_ZH_IT="it" # 意大利语 - // #LAN_ZH_TW="uk" # 乌克兰语 - // LAN_ZH_PT="pt" # 葡萄牙语 - // LAN_ZH_ES="es" # 西班牙语 - // LAN_ZH_AR="ar" # 阿拉伯语 - // LAN_ZH_vi="vi" # 越南语 - // LAN_ZH_MS="ms" # 马莱语 - // LAN_ZH_NL="nl" # 荷兰语 - // LAN_ZH_RO="ro" # 罗马尼亚语 - // LAN_ZH_LT="lt" # 立陶宛语 - // LAN_ZH_SV="sv" # 瑞典语 - // LAN_ZH_ET="et" # 爱沙尼亚语 - // LAN_ZH_PL="pl" # 波兰语 - // LAN_ZH_SK="sk" # 斯洛伐克语 - // LAN_ZH_CS="cs" # 捷克语 - // LAN_ZH_EL="el" # 希腊语 - // LAN_ZH_HE="he" # 希伯来语 - // #LAN_ZH_TW="sr" # 塞尔维亚文 - // LAN_ZH_TR="tr" # 土耳其语 - // LAN_ZH_HU="hu" # 匈牙利语 - // LAN_ZH_BG="bg" # 保加利亚语 - // LAN_ZH_KK="kk" # 哈萨克斯坦语 === 哈萨克语 - // LAN_ZH_BN="bn" # 孟加拉语 - // LAN_ZH_HBS="hr" # 克罗地亚语 - // LAN_ZH_TH="th" # 泰语 - // LAN_ZH_ID="id" # 印度尼西亚语 - // LAN_ZH_FI="fi" # 芬兰语 - // LAN_ZH_DA="da" # 丹麦语 - @override Map> get keys => { - 'en_US' : TranslationLoader.enDic, 'zh_CN': TranslationLoader.zhDic, + 'en_US' : TranslationLoader.enDic, 'zh_TW': TranslationLoader.twDic, 'fr_FR': TranslationLoader.frDic, 'ru_RU': TranslationLoader.ruDic, diff --git a/pubspec.yaml b/pubspec.yaml index a2608739..3dd564bb 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -87,8 +87,10 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # 1.0.75+2024081001:锁定版本,上架商城 # 1.0.76+2024081201:锁定版本,上架商城--最新版本 # 1.0.78+2024082701:测试国际化功能 +# 1.0.79+2024083001:测试所有国家国际化功能 +# 1.0.79+2024083001:测试开完锁数据上传功能 -version: 1.0.78+2024082701 +version: 1.0.79+2024090201 environment: sdk: '>=2.12.0 <3.0.0' @@ -220,7 +222,7 @@ dependencies: timelines: ^0.1.0 #侧滑删除 flutter_slidable: ^3.0.1 - audio_service: ^0.18.12 +# audio_service: ^0.18.12 app_settings: ^5.1.1 flutter_local_notifications: ^17.0.0 fluwx: ^4.5.5