|
|
|
@ -116,6 +116,11 @@ class TranslationController extends GetxController with WidgetsBindingObserver { |
|
|
|
StreamSubscription? _voiceInteractionSubscription; |
|
|
|
Timer? _translationDebounceTimer; |
|
|
|
|
|
|
|
// 播放防重复机制 |
|
|
|
String? _lastPlayedItemKey; // 最后播放的项目标识 |
|
|
|
int _lastPlayTime = 0; // 最后播放时间 |
|
|
|
static const int _playDebounceInterval = 500; // 防抖间隔:500毫秒 |
|
|
|
|
|
|
|
// 底部控制栏高度 |
|
|
|
double _bottomBarHeight = 0.0; |
|
|
|
|
|
|
|
@ -1083,7 +1088,30 @@ class TranslationController extends GetxController with WidgetsBindingObserver { |
|
|
|
Future<void> playTranslationItem(TranslationItem item) async { |
|
|
|
if (item.translatedText.isEmpty) return; |
|
|
|
|
|
|
|
// 防重复点击:如果短时间内重复点击同一项,忽略后续点击 |
|
|
|
final currentTime = DateTime.now().millisecondsSinceEpoch; |
|
|
|
final itemKey = |
|
|
|
'${item.sessionId}_${item.timestamp.millisecondsSinceEpoch}'; |
|
|
|
|
|
|
|
// 检查是否是重复点击同一项 |
|
|
|
if (_lastPlayedItemKey == itemKey && |
|
|
|
currentTime - _lastPlayTime < _playDebounceInterval) { |
|
|
|
Logger.info('防重复播放:忽略短时间内的重复点击'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果正在播放,先停止当前播放 |
|
|
|
if (_ttsService.isSpeaking) { |
|
|
|
await _ttsService.stop(); |
|
|
|
// 短暂延迟确保停止完成 |
|
|
|
await Future.delayed(const Duration(milliseconds: 100)); |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
// 更新播放记录 |
|
|
|
_lastPlayedItemKey = itemKey; |
|
|
|
_lastPlayTime = currentTime; |
|
|
|
|
|
|
|
final voiceName = |
|
|
|
_languageManager.getTtsVoiceNameByAsrCode(item.targetLanguageCode) ?? |
|
|
|
'en-US-AriaNeural'; |
|
|
|
@ -1100,7 +1128,29 @@ class TranslationController extends GetxController with WidgetsBindingObserver { |
|
|
|
Future<void> playText(String text, {String? languageCode}) async { |
|
|
|
if (text.isEmpty) return; |
|
|
|
|
|
|
|
// 防重复点击:基于文本内容和语言代码生成唯一标识 |
|
|
|
final currentTime = DateTime.now().millisecondsSinceEpoch; |
|
|
|
final textKey = '${text}_${languageCode ?? targetLanguageCode.value}'; |
|
|
|
|
|
|
|
// 检查是否是重复点击同一文本 |
|
|
|
if (_lastPlayedItemKey == textKey && |
|
|
|
currentTime - _lastPlayTime < _playDebounceInterval) { |
|
|
|
Logger.info('防重复播放:忽略短时间内的重复文本播放请求'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果正在播放,先停止当前播放 |
|
|
|
if (_ttsService.isSpeaking) { |
|
|
|
await _ttsService.stop(); |
|
|
|
// 短暂延迟确保停止完成 |
|
|
|
await Future.delayed(const Duration(milliseconds: 100)); |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
// 更新播放记录 |
|
|
|
_lastPlayedItemKey = textKey; |
|
|
|
_lastPlayTime = currentTime; |
|
|
|
|
|
|
|
final voiceName = languageCode != null |
|
|
|
? _languageManager.getTtsVoiceNameByAsrCode(languageCode) ?? |
|
|
|
'en-US-AriaNeural' |
|
|
|
|