From dfb368d8227c396c8731df596c230573f870e4cc Mon Sep 17 00:00:00 2001 From: sky_min Date: Sat, 15 Nov 2025 17:37:42 +0800 Subject: [PATCH] =?UTF-8?q?1.=E6=96=B0=E5=A2=9E=E4=B8=80=E9=94=AE=E7=99=BB?= =?UTF-8?q?=E5=BD=95=202.=E8=A7=86=E9=A2=91=E5=AF=B9=E8=AE=B2=E4=BC=98?= =?UTF-8?q?=E5=8C=96--=E4=BC=98=E5=8C=96=E5=B8=A7=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E7=AE=97=E6=B3=95=EF=BC=8C=E7=BC=93=E5=86=B2=E5=8C=BA=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/login/login/starLock_login_page.dart | 370 +++++++++--------- lib/login/login/starLock_login_state.dart | 8 +- .../lockDetail/lockDetail_logic.dart | 41 +- .../selectLockType/selectLockType_logic.dart | 16 +- .../message/messageList/messageList_page.dart | 83 +--- .../native/talk_view_native_decode_logic.dart | 129 +++--- lib/tools/jverify_one_click_login.dart | 176 ++++----- 7 files changed, 389 insertions(+), 434 deletions(-) diff --git a/lib/login/login/starLock_login_page.dart b/lib/login/login/starLock_login_page.dart index 19306279..22ac6540 100755 --- a/lib/login/login/starLock_login_page.dart +++ b/lib/login/login/starLock_login_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:star_lock/flavors.dart'; @@ -38,6 +39,10 @@ class _StarLockLoginPageState extends State { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { AppFirstEnterHandle().getAppFirstEnter(isAgreePrivacy); + // 获取手机号 + if (state.isChinaUser.value) { + // state.getPhoneNumber(); + } }); // StartChartManage().init(); } @@ -83,193 +88,202 @@ class _StarLockLoginPageState extends State { onTap: () { FocusScope.of(context).unfocus(); }, - child: ListView( - padding: EdgeInsets.only(top: 120.h, left: 40.w, right: 40.w), - children: [ - Container( - padding: EdgeInsets.all(10.w), - child: Center(child: Image.asset('images/icon_main_sky_1024.png', width: 110.w, height: 110.w))), - SizedBox(height: 50.w), - Obx(() => CommonItem( - leftTitel: '你所在的国家/地区'.tr, - rightTitle: '', - isHaveLine: true, - isPadding: false, - isHaveRightWidget: true, - isHaveDirection: true, - rightWidget: Text( - '${state.countryName} +${state.countryCode.value}', - textAlign: TextAlign.end, - style: TextStyle(fontSize: 22.sp, color: AppColors.darkGrayTextColor), - ), - action: () async { - final result = await Get.toNamed(Routers.selectCountryRegionPage); - if (result != null) { - result as Map; - state.countryCode.value = result['code']; - state.countryKey.value = result['countryName']; - logic.checkIpAction(); + child: state.isChinaUser.value ? _buildChinaUser() : _buildForeignUser() + ), + ); + } + + Widget _buildChinaUser() { + return ListView( + padding: EdgeInsets.only(top: 120.h, left: 40.w, right: 40.w), + children: [ + Container( + padding: EdgeInsets.all(10.w), + alignment: Alignment.center, + child: Column(children: [ + Image.asset('images/icon_main_sky_1024.png', width: 110.w, height: 110.w), + SizedBox(height: 50.w), + Text(state.emailOrPhone.value.isNotEmpty ? state.emailOrPhone.value : '获取手机号中...'), + SizedBox(height: 50.w), + SubmitBtn( + btnName: '一键登录', + fontSize: 28.sp, + borderRadius: 20.w, + padding: EdgeInsets.only(top: 25.w, bottom: 25.w), + onClick: () { + if (state.agree.value == false) { + logic.showToast('请先同意用户协议及隐私政策'.tr); + return; + } else { + logic.oneClickLoginAction(context); } - }, - )), - LoginInput( - focusNode: logic.state.emailOrPhoneFocusNode, - controller: state.emailOrPhoneController, - onchangeAction: (v) { - logic.checkNext(state.emailOrPhoneController); - }, - leftWidget: Padding( - padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w), - child: Image.asset( - 'images/icon_login_account.png', - width: 36.w, - height: 36.w, - ), - ), - hintText: '请输入手机号或者邮箱'.tr, - // keyboardType: TextInputType.number, - inputFormatters: [ - // FilteringTextInputFormatter.allow(RegExp('[0-9]')), - LengthLimitingTextInputFormatter(30), - FilteringTextInputFormatter.singleLineFormatter - ]), - SizedBox(height: 10.h), - LoginInput( - focusNode: logic.state.pwdFocusNode, - controller: state.pwdController, - onchangeAction: (v) { - logic.checkNext(state.pwdController); - }, - isPwd: true, - // isSuffixIcon: 2, - leftWidget: Padding( - padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w), - child: Image.asset( - 'images/icon_login_password.png', - width: 36.w, - height: 36.w, - ), - ), - hintText: '请输入密码'.tr, - inputFormatters: [ - LengthLimitingTextInputFormatter(20), - ]), - // SizedBox(height: 15.h), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Obx(() => GestureDetector( - onTap: () { - state.agree.value = !state.agree.value; - logic.changeAgreeState(); - }, - child: Container( - // color: Colors.red, - padding: EdgeInsets.only(left: 5.w, top: 20.w, right: 10.w, bottom: 20.h), - child: Image.asset( - state.agree.value ? 'images/icon_round_select.png' : 'images/icon_round_unSelect.png', - width: 35.w, - height: 35.w, - ), - ))), - // SizedBox( - // width: 5.w, - // ), - Flexible( - child: RichText( - text: TextSpan( - text: '我已阅读并同意'.tr, - style: TextStyle(color: const Color(0xff333333), fontSize: 20.sp), - children: [ - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: GestureDetector( - child: - Text('《${'用户协议'.tr}》', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)), - onTap: () { - Get.toNamed(Routers.webviewShowPage, arguments: { - 'url': XSConstantMacro.userAgreementURL, - 'title': '用户协议'.tr - }); - }, - )), - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: GestureDetector( - child: - Text('《${'隐私政策'.tr}》', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)), - onTap: () { - Get.toNamed(Routers.webviewShowPage, arguments: { - 'url': XSConstantMacro.privacyPolicyURL, - 'title': '隐私政策'.tr - }); - }, - )), - ], - )), - ) - ], + }), + SizedBox(height: 50.w), + _agreentWidget(), + ])) + ]); + } + + Widget _buildForeignUser() { + return ListView( + padding: EdgeInsets.only(top: 120.h, left: 40.w, right: 40.w), + children: [ + Container( + padding: EdgeInsets.all(10.w), + child: Center(child: Image.asset('images/icon_main_sky_1024.png', width: 110.w, height: 110.w))), + SizedBox(height: 50.w), + Obx(() => CommonItem( + leftTitel: '你所在的国家/地区'.tr, + rightTitle: '', + isHaveLine: true, + isPadding: false, + isHaveRightWidget: true, + isHaveDirection: true, + rightWidget: Text( + '${state.countryName} +${state.countryCode.value}', + textAlign: TextAlign.end, + style: TextStyle(fontSize: 22.sp, color: AppColors.darkGrayTextColor), + ), + action: () async { + final result = await Get.toNamed(Routers.selectCountryRegionPage); + if (result != null) { + result as Map; + state.countryCode.value = result['code']; + state.countryKey.value = result['countryName']; + logic.checkIpAction(); + } + }, + )), + LoginInput( + focusNode: logic.state.emailOrPhoneFocusNode, + controller: state.emailOrPhoneController, + onchangeAction: (v) { + logic.checkNext(state.emailOrPhoneController); + }, + leftWidget: Padding( + padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w), + child: Image.asset( + 'images/icon_login_account.png', + width: 36.w, + height: 36.w, + ), ), - SizedBox(height: 50.w), - Obx(() => SubmitBtn( - btnName: '登录'.tr, - fontSize: 28.sp, - borderRadius: 20.w, - padding: EdgeInsets.only(top: 25.w, bottom: 25.w), - isDisabled: state.canNext.value, - onClick: state.canNext.value - ? () { - if (state.agree.value == false) { - logic.showToast('请先同意用户协议及隐私政策'.tr); - return; - } else { - logic.login(); - } - } - : null)), - // SizedBox(height: 20.w), - // Obx(() => Visibility( - // visible: state.isCheckVerifyEnable.value, - // child: SubmitBtn( - // btnName: '一键登录', - // fontSize: 28.sp, - // borderRadius: 20.w, - // padding: EdgeInsets.only(top: 25.w, bottom: 25.w), - // // isDisabled: state.canNext.value, - // onClick: () { - // if (state.agree.value == false) { - // logic.showToast('请先同意用户协议及隐私政策'.tr); - // return; - // } else { - // logic.oneClickLoginAction(); - // } - // }), - // )), - SizedBox(height: 50.w), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - GestureDetector( - child: SizedBox( - // width: 150.w, - height: 50.h, - // color: Colors.red, - child: Center( - child: Text('${'忘记密码'.tr}?', style: TextStyle(fontSize: 22.sp, color: AppColors.mainColor)), - ), - ), - onTap: () { - Navigator.pushNamed(context, Routers.starLockForgetPasswordPage); - }, + hintText: '请输入邮箱'.tr, + inputFormatters: [ + LengthLimitingTextInputFormatter(30), + FilteringTextInputFormatter.singleLineFormatter + ]), + SizedBox(height: 10.h), + LoginInput( + focusNode: logic.state.pwdFocusNode, + controller: state.pwdController, + onchangeAction: (v) { + logic.checkNext(state.pwdController); + }, + isPwd: true, + leftWidget: Padding( + padding: EdgeInsets.only(top: 30.w, bottom: 20.w, right: 5.w, left: 5.w), + child: Image.asset( + 'images/icon_login_password.png', + width: 36.w, + height: 36.w, + ), + ), + hintText: '请输入密码'.tr, + inputFormatters: [ + LengthLimitingTextInputFormatter(20), + ]), + SizedBox(height: 50.w), + Obx(() => SubmitBtn( + btnName: '登录'.tr, + fontSize: 28.sp, + borderRadius: 20.w, + padding: EdgeInsets.only(top: 25.w, bottom: 25.w), + isDisabled: state.canNext.value, + onClick: state.canNext.value + ? () { + if (state.agree.value == false) { + logic.showToast('请先同意用户协议及隐私政策'.tr); + return; + } else { + logic.login(); + } + } : null)), + SizedBox(height: 20.w), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + child: SizedBox( + // width: 150.w, + height: 50.h, + // color: Colors.red, + child: Center( + child: Text('${'忘记密码'.tr}?', style: TextStyle(fontSize: 22.sp, color: AppColors.mainColor)), ), - ], + ), + onTap: () { + Navigator.pushNamed(context, Routers.starLockForgetPasswordPage); + }, ), ], ), - ), + ], ); } + Widget _agreentWidget() { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Obx(() => GestureDetector( + onTap: () { + state.agree.value = !state.agree.value; + logic.changeAgreeState(); + }, + child: Container( + // color: Colors.red, + padding: EdgeInsets.only(left: 5.w, top: 20.w, right: 10.w, bottom: 20.h), + child: Image.asset( + state.agree.value ? 'images/icon_round_select.png' : 'images/icon_round_unSelect.png', + width: 35.w, + height: 35.w, + ), + ))), + RichText( + text: TextSpan( + text: '我已阅读并同意'.tr, + style: TextStyle(color: const Color(0xff333333), fontSize: 20.sp), + children: [ + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: GestureDetector( + child: + Text('《${'用户协议'.tr}》', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)), + onTap: () { + Get.toNamed(Routers.webviewShowPage, arguments: { + 'url': XSConstantMacro.userAgreementURL, + 'title': '用户协议'.tr + }); + }, + )), + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: GestureDetector( + child: + Text('《${'隐私政策'.tr}》', style: TextStyle(color: AppColors.mainColor, fontSize: 20.sp)), + onTap: () { + Get.toNamed(Routers.webviewShowPage, arguments: { + 'url': XSConstantMacro.privacyPolicyURL, + 'title': '隐私政策'.tr + }); + }, + )), + ], + )), + ]); + } + Widget loginInput( {TextEditingController? controller, List? inputFormatters, diff --git a/lib/login/login/starLock_login_state.dart b/lib/login/login/starLock_login_state.dart index b623b61d..2e7aac08 100755 --- a/lib/login/login/starLock_login_state.dart +++ b/lib/login/login/starLock_login_state.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; - +import '../../app_settings/app_settings.dart'; +import '../../tools/jverify_one_click_login.dart'; import '../../translations/current_locale_tool.dart'; class StarLockLoginState { @@ -14,6 +15,11 @@ class StarLockLoginState { RxString countryCode = '86'.obs; RxString countryKey = '中国'.tr.obs; + // 是否为中国用户 + final RxBool isChinaUser = false.obs; + // 是否显示一键登录 + final RxBool showOneClickLogin = false.obs; + /// 获取翻译后的国家名称 String get countryName => countryKey.value.tr; diff --git a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart index 9ceff7d1..7d62d6bc 100755 --- a/lib/main/lockDetail/lockDetail/lockDetail_logic.dart +++ b/lib/main/lockDetail/lockDetail/lockDetail_logic.dart @@ -689,18 +689,35 @@ class LockDetailLogic extends BaseGetXController { // 远程开锁 Future remoteOpenLock() async { - final catEyeConfig = state.keyInfos.value.lockSetting?.catEyeConfig ?? []; - // 支持猫眼功能时,才需要判断是否是省电模式 - if (state.keyInfos.value.lockFeature?.isSupportCatEye == 1 && catEyeConfig[0].catEyeMode == 0) { - showToast('猫眼设置为省电模式时无法进行远程开锁,请在猫眼设置中切换为其他模式'.tr); - return; + final LockListInfoItemEntity currentKeyInfo = CommonDataManage().currentKeyInfo; + + var lockId = currentKeyInfo.lockId ?? 0; + var remoteUnlock = currentKeyInfo.lockSetting?.remoteUnlock ?? 0; + + final lockPeerId = StartChartManage().lockPeerId; + final LockListInfoGroupEntity? lockListInfoGroupEntity = await Storage.getLockMainListData(); + if (lockListInfoGroupEntity != null) { + lockListInfoGroupEntity!.groupList?.forEach((element) { + final lockList = element.lockList; + if (lockList != null && lockList.length != 0) { + for (var lockInfo in lockList) { + final peerId = lockInfo.network?.peerId; + if (peerId != null && peerId != '') { + if (peerId == lockPeerId) { + lockId = lockInfo.lockId ?? 0; + remoteUnlock = lockInfo.lockSetting?.remoteUnlock ?? 0; + } + } + } + } + }); } - final LoginEntity entity = await ApiRepository.to.remoteOpenLock( - lockId: state.keyInfos.value.lockId.toString(), - timeOut: 60, - ); - if (entity.errorCode!.codeIsSuccessful) { - showToast('已开锁'.tr); + if (remoteUnlock == 1) { + final LoginEntity entity = await ApiRepository.to.remoteOpenLock(lockId: lockId.toString(), timeOut: 60); + if (entity.errorCode!.codeIsSuccessful) { + showToast('已开锁'.tr); + StartChartManage().lockListPeerId = []; + } } } @@ -849,8 +866,6 @@ class LockDetailLogic extends BaseGetXController { showToast('设备未配网'.tr); return; } - // 启动监控时禁用铃声 - AudioPlayerManager().disableRingtone(); // 重置丢包率监控 // PacketLossStatistics().reset(); // 发送监控id diff --git a/lib/mine/addLock/selectLockType/selectLockType_logic.dart b/lib/mine/addLock/selectLockType/selectLockType_logic.dart index 5d6d3565..29283222 100755 --- a/lib/mine/addLock/selectLockType/selectLockType_logic.dart +++ b/lib/mine/addLock/selectLockType/selectLockType_logic.dart @@ -41,20 +41,8 @@ class SelectLockTypeLogic extends BaseGetXController { if (!Platform.isIOS) { final bool locationRequest = await PermissionDialog.request(Permission.location); final bool bluetoothRequest = await PermissionDialog.requestBluetooth(); - // 添加存储权限请求(相册权限) - final bool storageRequest = await PermissionDialog.request(Permission.storage); - - bool isHarmonyOS = await checkIfHarmonyOS(); - // 鸿蒙系统 - if(isHarmonyOS){ - print('鸿蒙手机提示----'); - if (!bluetoothRequest || !locationRequest || !storageRequest) { - return; - } - } else { - if (!bluetoothRequest || !locationRequest) { - return; - } + if (!bluetoothRequest || !locationRequest) { + return; } } diff --git a/lib/mine/message/messageList/messageList_page.dart b/lib/mine/message/messageList/messageList_page.dart index 5b9be83c..92e097c2 100755 --- a/lib/mine/message/messageList/messageList_page.dart +++ b/lib/mine/message/messageList/messageList_page.dart @@ -193,34 +193,10 @@ class _MessageListPageState extends State style: TextStyle( fontWeight: FontWeight.w600, fontSize: 30.sp)), - // 点击多选可以进行删除 - // GestureDetector( - // onTap: () { - // // 没有多选删除的 api接口,无法使用 - // // if (_showCheckboxes.value) { - // // deleteSelectedMessages(); - // // } else { - // // setState(() { - // // _showCheckboxes.value = - // // !_showCheckboxes.value; - // // }); - // // } - // }, - // child: _showCheckboxes.value - // ? Text('删除', - // style: TextStyle( - // fontSize: 24.sp, - // color: Colors.red)) - // : Image.asset( - // 'images/mine/icon_message_checbox.png', - // width: 30.w, - // height: 30.h), - // ) ]), ) ]))), Container( - child: Container( padding: EdgeInsets.only( top: showNotificationBanner ? 80 : 50), child: ListView.builder( @@ -270,7 +246,6 @@ class _MessageListPageState extends State }, ), ), - ) ], ); })), @@ -342,7 +317,7 @@ class _MessageListPageState extends State if (!isLastInGroupSimple) Container( width: 0.5, - height: 190.h, + height: 120.h, color: AppColors.placeholderTextColor, ) ], @@ -370,7 +345,7 @@ class _MessageListPageState extends State ], ), child: Container( width: 1.sw, - margin: EdgeInsets.all(20.h), + margin: EdgeInsets.all(10.h), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10.w), @@ -381,42 +356,8 @@ class _MessageListPageState extends State child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - // SizedBox(height: 4.h), - // Row( - // children: [ - // Flexible( - // child: Text( - // // 调用请求标题 - // '远程开门请求', - // maxLines: 1, - // overflow: TextOverflow.ellipsis, - // style: TextStyle( - // fontSize: 22.sp, - // color: messageItemEntity.readAt! == 0 - // ? AppColors.blackColor - // : AppColors.placeholderTextColor), - // ), - // ), - // ], - // ), - // SizedBox(height: 4.h), Wrap( children: [ - // if (messageItemEntity.readAt! == 0) - // Container( - // width: 10.w, - // height: 10.w, - // decoration: BoxDecoration( - // color: Colors.red, - // borderRadius: BorderRadius.circular(5.w), - // ), - // ) - // else - // Container(), - // if (messageItemEntity.readAt! == 0) - // SizedBox(width: 5.w) - // else - // Container(), Container( margin: EdgeInsets.only(top: 4.h), child: Text( @@ -437,7 +378,7 @@ class _MessageListPageState extends State ? AppColors.blackColor : AppColors.placeholderTextColor, ), - Container(transform: Matrix4.translationValues(0, -18, 0), + Container(transform: Matrix4.translationValues(0, -22, 0), child: Text(' ${messageItemEntity.data!}', maxLines: 2, overflow: TextOverflow.ellipsis, @@ -453,24 +394,6 @@ class _MessageListPageState extends State ),alignment: Alignment.centerRight,) ], ), - // SizedBox(height: 5.h), - // Row( - // mainAxisAlignment: MainAxisAlignment.start, - // children: [ - // // Image.asset('images/mine/icon_mine_gatewaySignal_strong.png', width: 40.w, height: 40.w,), - // // SizedBox(width: 10.w,), - // Text( - // DateTool().dateToHnString(messageItemEntity - // .createdAt! - // .toString()), - // style: TextStyle( - // fontSize: 18.sp, - // color: messageItemEntity.readAt! == 0 - // ? AppColors.blackColor - // : AppColors.placeholderTextColor)), - // ], - // ), - // SizedBox(width: 20.h), ]))))), // 显示选中状态的复选框 if (_showCheckboxes.value) diff --git a/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart b/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart index f4376135..95fba8b0 100644 --- a/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart +++ b/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart @@ -41,6 +41,33 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { final LockDetailState lockDetailState = Get.put(LockDetailLogic()).state; + // 添加成员变量缓存帧索引 + final Map>> _frameIndexCache = {}; + bool _frameIndexDirty = true; + // 更新帧缓冲区时标记索引为脏数据 + void _invalidateFrameIndex() { + _frameIndexDirty = true; + } + // 构建帧索引 + List> _buildFrameIndex(TalkDataH264Frame_FrameTypeE frameType) { + if (!_frameIndexDirty && _frameIndexCache.containsKey(frameType)) { + return _frameIndexCache[frameType]!; + } + + final List> index = []; + for (int i = 0; i < state.h264FrameBuffer.length; i++) { + final frame = state.h264FrameBuffer[i]; + if (frame['frameType'] == frameType) { + index.add(MapEntry(frame['frameSeq'] as int, i)); + } + } + index.sort((a, b) => a.key.compareTo(b.key)); + + _frameIndexCache[frameType] = index; + _frameIndexDirty = false; + return index; + } + // 添加网络质量评估变量 int _networkQualityScore = 5; // 1-5分,5为最佳 int _frameDropCount = 0; @@ -296,7 +323,13 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { VideoDecodePlugin.setOnFrameRenderedListener((textureId) { AppLog.log('已经开始渲染======='); // 只有真正渲染出首帧时才关闭loading - Future.microtask(() => state.isLoading.value = false); + Future.microtask(() { + state.isLoading.value = false; + // 添加停止动画的代码 + if (state.animationController.isAnimating) { + state.animationController.stop(); + } + }); }); } else { AppLog.log('视频解码器初始化失败或超时, 耗时: ${duration}ms'); @@ -432,6 +465,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { // 将帧添加到缓冲区 state.h264FrameBuffer.add(frameMap); + _invalidateFrameIndex(); } /// 启动帧处理定时器 @@ -494,11 +528,43 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { } else { // 新帧是P帧或B帧,移除最旧的帧 state.h264FrameBuffer.removeAt(0); + _invalidateFrameIndex(); } } + int _findEarliestIFrame() { + final iFrameIndexes = _buildFrameIndex(TalkDataH264Frame_FrameTypeE.I); + return iFrameIndexes.isNotEmpty ? iFrameIndexes.first.value : -1; + } + + int _findRelatedPFrame(int refIFrameSeq) { + final pFrameIndexes = _buildFrameIndex(TalkDataH264Frame_FrameTypeE.P); + for (final entry in pFrameIndexes) { + final frame = state.h264FrameBuffer[entry.value]; + if (frame['frameSeqI'] == refIFrameSeq) { + return entry.value; + } + } + return -1; + } + int _findBestFrameIndex() { + // 优先处理与最近解码的I帧相关的P帧 + if (lastDecodedIFrameSeq != null) { + final pFrameIndex = _findRelatedPFrame(lastDecodedIFrameSeq!); + if (pFrameIndex >= 0) return pFrameIndex; + } + + // 查找最早的I帧 + final iFrameIndex = _findEarliestIFrame(); + if (iFrameIndex >= 0) return iFrameIndex; + + // 如果没有I帧,处理最早的帧 + return state.h264FrameBuffer.isNotEmpty ? 0 : -1; + } + /// 从缓冲区处理下一帧 void _processNextFrameFromBuffer() async { + final stopwatch = Stopwatch()..start(); _monitorFrameProcessingPerformance(); final startTime = DateTime.now().microsecondsSinceEpoch; @@ -543,63 +609,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { } } - // 查找最适合处理的帧 -- 优先处理I帧以加速首帧显示 - int frameIndex = -1; - // 首先查找最早的I帧 - final iFrames = state.h264FrameBuffer - .where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I) - .toList() - ..sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int)); - - if (iFrames.isNotEmpty) { - final minIFrame = iFrames.first; - frameIndex = state.h264FrameBuffer.indexWhere( - (f) => - f['frameType'] == TalkDataH264Frame_FrameTypeE.I && - f['frameSeq'] == minIFrame['frameSeq'], - ); - } else { - // 如果没有I帧,处理最早的帧 - frameIndex = 0; - } - - // 优先处理与最近解码的I帧相关的P帧 - if (lastDecodedIFrameSeq != null) { - // 查找与上一个I帧关联的P帧(按顺序) - final validPFrames = state.h264FrameBuffer - .where((f) => - f['frameType'] == TalkDataH264Frame_FrameTypeE.P && - f['frameSeqI'] == lastDecodedIFrameSeq) - .toList() - ..sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int)); - - if (validPFrames.isNotEmpty) { - final minPFrame = validPFrames.first; - frameIndex = state.h264FrameBuffer.indexWhere( - (f) => - f['frameType'] == TalkDataH264Frame_FrameTypeE.P && - f['frameSeq'] == minPFrame['frameSeq'] && - f['frameSeqI'] == lastDecodedIFrameSeq, - ); - } - } - - // 如果没有找到相关的P帧,查找最早的I帧 - if (frameIndex == -1) { - final iFrames = state.h264FrameBuffer - .where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I) - .toList() - ..sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int)); - - if (iFrames.isNotEmpty) { - final minIFrame = iFrames.first; - frameIndex = state.h264FrameBuffer.indexWhere( - (f) => - f['frameType'] == TalkDataH264Frame_FrameTypeE.I && - f['frameSeq'] == minIFrame['frameSeq'], - ); - } - } + //减少重复计算和排序操作 + final frameIndex = _findBestFrameIndex(); // 处理选中的帧 if (frameIndex >= 0) { @@ -657,6 +668,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { AppLog.log('帧处理耗时过长: ${durationMs.toStringAsFixed(2)} ms, 缓冲区长度: ${state.h264FrameBuffer.length}'); } } + stopwatch.stop(); + print('执行耗时: ${stopwatch.elapsedMilliseconds} 毫秒'); } diff --git a/lib/tools/jverify_one_click_login.dart b/lib/tools/jverify_one_click_login.dart index 324d1b62..5a0ac4bc 100644 --- a/lib/tools/jverify_one_click_login.dart +++ b/lib/tools/jverify_one_click_login.dart @@ -10,21 +10,21 @@ import '../app_settings/app_settings.dart'; import '../common/XSConstantMacro/XSConstantMacro.dart'; import '../flavors.dart'; + class JverifyOneClickLoginManage { - factory JverifyOneClickLoginManage() => shareManager()!; + factory JverifyOneClickLoginManage() => _getInstance()!; - JverifyOneClickLoginManage._init() { - _initSDK(); + JverifyOneClickLoginManage._init() {} + + static JverifyOneClickLoginManage get instance => _getInstance(); + static JverifyOneClickLoginManage? _instance; + + static JverifyOneClickLoginManage _getInstance() { + _instance ??= JverifyOneClickLoginManage._init(); + return _instance!; } - static JverifyOneClickLoginManage? _manager; - - static JverifyOneClickLoginManage? shareManager() { - _manager ??= JverifyOneClickLoginManage._init(); - return _manager; - } - - JverifyOneClickLoginManage? get manager => shareManager(); + JverifyOneClickLoginManage? get manager => _getInstance(); Jverify jverify = Jverify(); /// 统一 key @@ -39,106 +39,102 @@ class JverifyOneClickLoginManage { /// 运营商信息 String f_opr_key = 'operator'; - Future _initSDK() async { + Future initSDK({Function? onSuccess, Function? onFailure}) async { try { - await initPlatformState(); + // 初始化 SDK 之前添加监听 + jverify.addSDKSetupCallBackListener((JVSDKSetupEvent event) { + print('receive sdk setup call back event :${event.toMap()}'); + if (event.code == 8000) { + onSuccess?.call(); + } else { + onFailure?.call(); + } + }); - isInitSuccess(); + jverify.setDebugMode(true); // 打开调试模式 + jverify.setCollectionAuth(true); + String appKey; + if (F.isSKY) { + appKey = '7ff37d174c1a568a89e98dad'; + AppLog.log('appKey:7ff37d174c1a568a89e98dad'); + } else { + appKey = '251fc8074820d122b6de58d2'; + AppLog.log('appKey:251fc8074820d122b6de58d2'); + } + jverify.setup( + appKey: appKey, //"你自己应用的 AppKey", + channel: 'devloper'); - getToken(); + /// 授权页面点击时间监听 + jverify.addAuthPageEventListener((JVAuthPageEvent event) { + print('receive auth page event :${event.toMap()}'); + }); - preLogin(); + // isInitSuccess(); + + // getToken(); + + // preLogin(); } catch (e) { AppLog.log('SDK 初始化错误: $e'); } } - Future initPlatformState() async { - // 初始化 SDK 之前添加监听 - jverify.addSDKSetupCallBackListener((JVSDKSetupEvent event) { - print('receive sdk setup call back event :${event.toMap()}'); - }); - - jverify.setDebugMode(true); // 打开调试模式 - jverify.setCollectionAuth(true); - String appKey; - if (F.isSKY) { - appKey = '7ff37d174c1a568a89e98dad'; - AppLog.log('appKey:7ff37d174c1a568a89e98dad'); - } else { - appKey = '251fc8074820d122b6de58d2'; - AppLog.log('appKey:251fc8074820d122b6de58d2'); - } - jverify.setup( - appKey: appKey, //"你自己应用的 AppKey", - channel: 'devloper'); - - /// 授权页面点击时间监听 - jverify.addAuthPageEventListener((JVAuthPageEvent event) { - print('receive auth page event :${event.toMap()}'); - }); - } - /// sdk 初始化是否完成 - void isInitSuccess() { - jverify.isInitSuccess().then((map) { - final bool result = map[f_result_key]; - AppLog.log('sdk 初始化结果:$map'); - if (result) { - AppLog.log('sdk 初始化成功'); - } else { - AppLog.log('sdk 初始化失败'); - } - }); + Future isInitSuccess() async { + final Map map = await jverify.isInitSuccess(); + final bool result = map[f_result_key]; + AppLog.log('sdk 初始化结果:$map'); + if (result) { + AppLog.log('sdk 初始化成功'); + } else { + AppLog.log('sdk 初始化失败'); + } + return Future.value(result); } /// 判断当前网络环境是否可以发起认证 Future checkVerifyEnable() async { + final isInitSuccess = await this.isInitSuccess(); + if (!isInitSuccess) { + return false; + } final Map map = await jverify.checkVerifyEnable(); - AppLog.log('一家登录 sdk 初始化结果:$map'); + print('一家登录 sdk 初始化结果:$map'); final bool result = map[f_result_key]; return result; - // state.jverify.checkVerifyEnable().then((map) { - // final bool result = map[f_result_key]; - // if (result) { - // AppLog.log('当前网络环境【支持认证】!'); - // } else { - // AppLog.log('当前网络环境【不支持认证】!'); - // } - // return result; - // }); } - void getToken() { - jverify.checkVerifyEnable().then((map) { - final bool result = map[f_result_key]; - if (result) { - jverify.getToken().then((map) { - final int code = map[f_code_key]; - final String token = map[f_msg_key]; - final String operator = map[f_opr_key]; - AppLog.log('getToken code:$code token:$token operator:$operator'); - }); - } else { - AppLog.log('[2016],msg = 当前网络环境不支持认证'); - } - }); - } + // void getToken() { + // jverify.checkVerifyEnable().then((map) { + // final bool result = map[f_result_key]; + // if (result) { + // jverify.getToken().then((map) { + // final int code = map[f_code_key]; + // final String token = map[f_msg_key]; + // final String operator = map[f_opr_key]; + // AppLog.log('getToken code:$code token:$token operator:$operator'); + // }); + // } else { + // AppLog.log('[2016],msg = 当前网络环境不支持认证'); + // } + // }); + // } /// 登录预取号 - void preLogin() { - jverify.checkVerifyEnable().then((map) { - final bool result = map[f_result_key]; - if (result) { - jverify.preLogin().then((map) { - AppLog.log('预取号接口回调:${map.toString()}'); - final int code = map[f_code_key]; - final String message = map[f_msg_key]; - }); - } else { - AppLog.log('[2016],msg = 当前网络环境不支持认证'); - } - }); + Future preLogin() async { + final networkSupportVerify = await this.checkVerifyEnable(); + if (!networkSupportVerify) { + return false; + } + final Map map = await jverify.preLogin(); + final int code = map[f_code_key]; + final String message = map[f_msg_key]; + if (code > 0) { + return true; + } + AppLog.log('[2016],msg = 当前网络环境不支持认证'); + return false; } /// SDK 请求授权一键登录