diff --git a/lan/lan_keys.json b/lan/lan_keys.json index f695a426..aff5bacc 100755 --- a/lan/lan_keys.json +++ b/lan/lan_keys.json @@ -1168,6 +1168,7 @@ "第三方平台设置": "第三方平台设置", "涂鸦智能": "Tuya Smart", "锁语音包设置": "锁语音包设置", + "语音包设置": "语音包设置", "(中国台湾)": "(中国台湾)", "男声": "男声", "女声": "女声" diff --git a/lan/lan_zh.json b/lan/lan_zh.json index 424a13ec..c1b24478 100755 --- a/lan/lan_zh.json +++ b/lan/lan_zh.json @@ -1170,6 +1170,7 @@ "第三方平台设置": "第三方平台设置", "涂鸦智能": "涂鸦智能", "锁语音包设置": "锁语音包设置", + "语音包设置": "语音包设置", "(中国台湾)": "(中国台湾)", "男声": "男声", "女声": "女声" diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart index 781df709..4422954f 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_logic.dart @@ -34,6 +34,12 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { final SpeechLanguageSettingsState state = SpeechLanguageSettingsState(); StreamSubscription? _replySubscription; +// 超时定时器(用于检测是否未收到回复) + Timer? _sendTimeoutTimer; + +// 超时标志位(可选,防止重复处理) + bool _isTimeout = false; + @override void onInit() async { super.onInit(); @@ -45,10 +51,9 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { } else if (reply is VoicePackageConfigureProcessReply) { _handlerVoicePackageConfigureProcess(reply); } else if (reply is VoicePackageConfigureConfirmationReply) { - _handlerVoicePackageConfigureConfirmation(reply); + handleVoiceConfigureThrottled(reply); } }); - await initList(); } @@ -110,14 +115,22 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.lang; final timbre = state .lockSetInfoData.value.lockSettingInfo?.currentVoiceTimbre?.timbre; - state.languages.value.forEach((element) { - final timbres = element.timbres; - timbres.forEach((item) { - if (lang == element.lang && item.timbre == timbre) { - state.selectSoundTypeIndex.value = item.isFemale; + // 传统 for 循环,直接通过索引访问 + for (int i = 0; i < state.languages.length; i++) { + final language = state.languages[i]; // 当前元素 + if (language.lang == lang) { + print('匹配到下标:$i,元素:$language'); + final timbres = language.timbres; + for (int j = 0; j < timbres.length; j++) { + final item = timbres[j]; + if (lang == language.lang && item.timbre == timbre) { + state.selectSoundTypeIndex.value = item.isFemale; + state.selectPassthroughListIndex.value = i; + break; + } } - }); - }); + } + } } } catch (e) { debugPrint('获取语音包出现错误:$e'); @@ -266,7 +279,39 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { _sendNextPackage(); } + void _handleSendTimeout() { + _isTimeout = true; // 标记超时状态 + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + + // 重置状态,避免后续错误操作 + state.voiceSubcontractingIndex = 0; + state.voiceSubcontractingCount = 0; + state.data = null; + state.progress.value = 0.0; + _isTimeout = false; // 标记超时状态 + } + void _sendNextPackage() async { + // 若已超时,直接返回 + if (_isTimeout) return; + + // 取消上一次未完成的定时器(避免重复触发) + _sendTimeoutTimer?.cancel(); + + // 检查是否已完成所有分包发送 + if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) { + print('所有分包已发送完成'); + state.progress.value = 1.0; + return; + } + + // 启动 3 秒超时定时器 + _sendTimeoutTimer = Timer(Duration(seconds: 3), () { + _handleSendTimeout(); // 触发超时处理 + }); + if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) { print('所有分包已发送完成'); state.progress.value = 1.0; // 发送完成 @@ -313,6 +358,9 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { void _handlerVoicePackageConfigureProcess( VoicePackageConfigureProcessReply reply) { + // 取消超时定时器(已收到回复,无需继续等待) + _sendTimeoutTimer?.cancel(); + _isTimeout = false; // 重置超时标志 final int status = reply.data[2]; switch (status) { case 0x00: @@ -358,7 +406,30 @@ class SpeechLanguageSettingsLogic extends BaseGetXController { super.onClose(); } - void _handlerVoicePackageConfigureConfirmation( + bool _isThrottled = false; + + void handleVoiceConfigureThrottled( + VoicePackageConfigureConfirmationReply reply, + ) { + if (_isThrottled) return; + + _isThrottled = true; + + // 执行你的逻辑 + _executeLogic(reply); + + // 设置节流时间(比如 1 秒) + Future.delayed(Duration(seconds: 1), () { + _isThrottled = false; + }); + } + + Future _executeLogic( + VoicePackageConfigureConfirmationReply reply) async { + await _handlerVoicePackageConfigureConfirmation(reply); + } + + _handlerVoicePackageConfigureConfirmation( VoicePackageConfigureConfirmationReply reply, ) async { final int status = reply.data[2]; diff --git a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart index 94e602cd..ef590be8 100644 --- a/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart +++ b/lib/main/lockDetail/lockSet/speechLanguageSettings/speech_language_settings_page.dart @@ -48,7 +48,86 @@ class _SpeechLanguageSettingsPageState ), ], ), - body: _buildBody(), + body: Obx( + () => ListView( + padding: EdgeInsets.zero, + children: [ + // 语音类型选择区 + Container( + color: Colors.white, + child: Column( + children: List.generate( + state.soundTypeList.length, + (index) { + final isLastItem = index == state.soundTypeList.length - 1; + final soundType = state.soundTypeList.value[index]; + return CommonItem( + leftTitel: soundType, + rightTitle: '', + isHaveLine: !isLastItem, + isHaveDirection: false, + isHaveRightWidget: true, + rightWidget: Radio( + value: soundType, + groupValue: state.soundTypeList + .value[state.selectSoundTypeIndex.value], + activeColor: AppColors.mainColor, + onChanged: (value) { + if (value != null) { + final newIndex = state.soundTypeList.value + .indexWhere((p) => p == value); + if (newIndex != -1) { + state.selectSoundTypeIndex.value = newIndex; + } + } + }, + ), + action: () { + state.selectSoundTypeIndex.value = index; + }, + ); + }, + ), + ), + ), + SizedBox( + height: 8.h, + ), + // 语言包列表区 + Container( + color: Colors.transparent, + child: Column( + children: List.generate( + state.languages.length, + (index) { + final item = state.languages[index]; + return CommonItem( + leftTitel: item.langText, + rightTitle: '', + isHaveLine: true, + isHaveDirection: false, + isHaveRightWidget: true, + rightWidget: + state.selectPassthroughListIndex.value == index + ? Image( + image: const AssetImage( + 'images/icon_item_checked.png'), + width: 30.w, + height: 30.w, + fit: BoxFit.contain, + ) + : Container(), + action: () { + state.selectPassthroughListIndex.value = index; + }, + ); + }, + ), + ), + ), + ], + ), + ), ); } @@ -57,10 +136,7 @@ class _SpeechLanguageSettingsPageState () => SingleChildScrollView( child: Column( children: [ - Container( - width: 1.sw, - decoration: BoxDecoration(color: Colors.white), - child: ListView.builder( + ListView.builder( itemCount: state.soundTypeList.length, itemBuilder: (BuildContext context, int index) { // 判断是否是最后一个元素(索引等于 itemCount - 1) @@ -105,12 +181,8 @@ class _SpeechLanguageSettingsPageState ); }, shrinkWrap: true, - physics: const AlwaysScrollableScrollPhysics(), - ), - ), - SizedBox( - height: 8.h, - ), + physics: const NeverScrollableScrollPhysics() //add this line, + ), Column( children: _buildList(), ), diff --git a/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_page.dart b/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_page.dart index 03c36a5c..f236265c 100755 --- a/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_page.dart +++ b/lib/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_page.dart @@ -1,8 +1,8 @@ - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:fluwx/fluwx.dart'; import 'package:get/get.dart'; import 'package:star_lock/flavors.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKeyDetail/passwordKeyDetail_logic.dart'; @@ -84,8 +84,8 @@ class _PasswordKeyDetailPageState extends State // showCupertinoAlertDialog( // context, state.inputNameController); // })), - Obx(() => lockDataListItem('姓名'.tr, - state.keyboardPwdName.value, () { + Obx(() => + lockDataListItem('姓名'.tr, state.keyboardPwdName.value, () { showCupertinoAlertDialog( context, state.inputNameController); })), @@ -436,7 +436,18 @@ class _PasswordKeyDetailPageState extends State final String pwdShareStr = logic.getShareContentStr(); switch (itemIndex) { case 0: //微信好友 - NativeInteractionTool().loadNativeShare(shareText: pwdShareStr); + Fluwx fluwx = Fluwx(); + fluwx.registerApi( + appId: F.wechatAppInfo.wechatAppId, + universalLink: F.wechatAppInfo.universalLink, + ); + fluwx.share( + WeChatShareTextModel( + pwdShareStr, + scene: WeChatScene.session, + ), + ); + // NativeInteractionTool().loadNativeShare(shareText: pwdShareStr); break; case 1: //短信 case 2: //邮件 diff --git a/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart b/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart index edb88de7..7b99294e 100755 --- a/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart +++ b/lib/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_page.dart @@ -3,9 +3,11 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:fluwx/fluwx.dart'; import 'package:get/get.dart'; import 'package:star_lock/app_settings/app_colors.dart'; import 'package:star_lock/app_settings/app_settings.dart'; +import 'package:star_lock/flavors.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_logic.dart'; import 'package:star_lock/main/lockDetail/passwordKey/passwordKey_perpetual/passwordKey_perpetual_state.dart'; import 'package:star_lock/tools/commonDataManage.dart'; @@ -859,7 +861,18 @@ class _PasswordKeyPerpetualPageState extends State final String pwdShareStr = logic.getShareContentStr(); switch (itemIndex) { case 0: //微信好友 - NativeInteractionTool().loadNativeShare(shareText: pwdShareStr); + Fluwx fluwx = Fluwx(); + fluwx.registerApi( + appId: F.wechatAppInfo.wechatAppId, + universalLink: F.wechatAppInfo.universalLink, + ); + fluwx.share( + WeChatShareTextModel( + pwdShareStr, + scene: WeChatScene.session, + ), + ); + // NativeInteractionTool().loadNativeShare(shareText: pwdShareStr); break; case 1: //短信 case 2: //邮件 diff --git a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart index dff888e9..017f6dc9 100644 --- a/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart +++ b/lib/mine/addLock/lock_voice_setting/lock_voice_setting_logic.dart @@ -31,6 +31,11 @@ class LockVoiceSettingLogic extends BaseGetXController { LockVoiceSettingState state = LockVoiceSettingState(); StreamSubscription? _replySubscription; bool _isThrottled = false; +// 超时定时器(用于检测是否未收到回复) + Timer? _sendTimeoutTimer; + +// 超时标志位(可选,防止重复处理) + bool _isTimeout = false; @override void onInit() async { @@ -161,6 +166,12 @@ class LockVoiceSettingLogic extends BaseGetXController { BluetoothConnectionState.disconnected) { dismissEasyLoading(); cancelBlueConnetctToastTimer(); + // 延迟1秒后重试(避免频繁请求) + Future.delayed(const Duration(seconds: 2), () { + // 递归调用自身,重试次数+1 + sendFileToDevice(data, token); + }); + // showBlueConnetctToast(); } }); @@ -168,6 +179,9 @@ class LockVoiceSettingLogic extends BaseGetXController { void _handlerVoicePackageConfigureProcess( VoicePackageConfigureProcessReply reply) { + // 取消超时定时器(已收到回复,无需继续等待) + _sendTimeoutTimer?.cancel(); + _isTimeout = false; // 重置超时标志 final int status = reply.data[2]; switch (status) { case 0x00: @@ -300,8 +314,27 @@ class LockVoiceSettingLogic extends BaseGetXController { state.progress.value = 0.0; // 开始前重置进度 _sendNextPackage(); } + void _handleSendTimeout() { + _isTimeout = true; // 标记超时状态 + dismissEasyLoading(); + cancelBlueConnetctToastTimer(); + showBlueConnetctToast(); + + // 重置状态,避免后续错误操作 + state.voiceSubcontractingIndex = 0; + state.voiceSubcontractingCount = 0; + state.data = null; + state.progress.value = 0.0; + _isTimeout = false; // 标记超时状态 + } void _sendNextPackage() { + // 若已超时,直接返回 + if (_isTimeout) return; + + // 取消上一次未完成的定时器(避免重复触发) + _sendTimeoutTimer?.cancel(); + if (state.voiceSubcontractingIndex >= state.voiceSubcontractingCount) { print('所有分包已发送完成'); state.progress.value = 1.0; // 发送完成 @@ -309,6 +342,12 @@ class LockVoiceSettingLogic extends BaseGetXController { return; } + // 启动 3 秒超时定时器 + _sendTimeoutTimer = Timer(Duration(seconds: 3), () { + _handleSendTimeout(); // 触发超时处理 + }); + + int start = state.voiceSubcontractingIndex * state.voiceSubcontractingSize; int end = start + state.voiceSubcontractingSize; if (end > state.data!.length) end = state.data!.length;