|
|
@ -116,12 +116,12 @@ class AgentController extends GetxController { |
|
|
// 切换TTS状态 |
|
|
// 切换TTS状态 |
|
|
Future<void> toggleTts() async { |
|
|
Future<void> toggleTts() async { |
|
|
isTtsEnabled.toggle(); |
|
|
isTtsEnabled.toggle(); |
|
|
|
|
|
|
|
|
// 如果关闭TTS,停止当前语音 |
|
|
// 如果关闭TTS,停止当前语音 |
|
|
if (!isTtsEnabled.value && isSpeaking.value) { |
|
|
if (!isTtsEnabled.value && isSpeaking.value) { |
|
|
await AgentService.stopTts(); |
|
|
await AgentService.stopTts(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 保存偏好设置 |
|
|
// 保存偏好设置 |
|
|
try { |
|
|
try { |
|
|
final storage = GetStorage(); |
|
|
final storage = GetStorage(); |
|
|
@ -382,22 +382,15 @@ class AgentController extends GetxController { |
|
|
logger.i('Flutter 结束调用 mcp: $result, $functionCall'); |
|
|
logger.i('Flutter 结束调用 mcp: $result, $functionCall'); |
|
|
if (result.isNotEmpty) { |
|
|
if (result.isNotEmpty) { |
|
|
final parsedResult = jsonDecode(result); |
|
|
final parsedResult = jsonDecode(result); |
|
|
final meta = parsedResult["meta"]; |
|
|
final meta = parsedResult["meta"] as String; |
|
|
Map<String, dynamic> metaResult = {}; |
|
|
final metaResult = jsonDecode(meta); |
|
|
|
|
|
if (meta.isNotEmpty) { |
|
|
if (meta != null && meta is String && meta.isNotEmpty) { |
|
|
logger.i('Flutter 结束调用 mcp metaResult: $metaResult'); |
|
|
try { |
|
|
|
|
|
metaResult = jsonDecode(meta); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
print('解析meta数据失败: $e'); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if(metaResult.isNotEmpty){ |
|
|
|
|
|
|
|
|
|
|
|
// 判断是否为新的回复或响应ID是否改变 |
|
|
// 判断是否为新的回复或响应ID是否改变 |
|
|
if (_isNewAssistantResponse || _currentResponseId != responseId) { |
|
|
if (_isNewAssistantResponse || _currentResponseId != responseId) { |
|
|
// 添加新消息 |
|
|
// 添加新消息 |
|
|
messages.add(Message(isUser: false, text: "", meta: metaResult)); |
|
|
messages |
|
|
|
|
|
.add(Message(isUser: false, text: "", meta: metaResult)); |
|
|
_isNewAssistantResponse = false; |
|
|
_isNewAssistantResponse = false; |
|
|
_currentResponseId = responseId; |
|
|
_currentResponseId = responseId; |
|
|
} else { |
|
|
} else { |
|
|
@ -407,11 +400,14 @@ class AgentController extends GetxController { |
|
|
messages[lastIndex] = Message( |
|
|
messages[lastIndex] = Message( |
|
|
isUser: false, |
|
|
isUser: false, |
|
|
text: messages[lastIndex].text, |
|
|
text: messages[lastIndex].text, |
|
|
meta: meta, |
|
|
meta: metaResult, |
|
|
timestamp: messages[lastIndex].timestamp, |
|
|
timestamp: messages[lastIndex].timestamp, |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
messages.refresh(); |
|
|
|
|
|
// 滚动到底部 |
|
|
|
|
|
_scrollToBottom(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
@ -467,7 +463,8 @@ class AgentController extends GetxController { |
|
|
// 标记为新的AI回复 |
|
|
// 标记为新的AI回复 |
|
|
_isNewAssistantResponse = true; |
|
|
_isNewAssistantResponse = true; |
|
|
// 根据TTS状态决定是否朗读 |
|
|
// 根据TTS状态决定是否朗读 |
|
|
await AgentService.processTextInput(text, speakResponse: isTtsEnabled.value); |
|
|
await AgentService.processTextInput(text, |
|
|
|
|
|
speakResponse: isTtsEnabled.value); |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
logger.e('发送文本消息失败: $e'); |
|
|
logger.e('发送文本消息失败: $e'); |
|
|
isProcessing.value = false; |
|
|
isProcessing.value = false; |
|
|
@ -549,18 +546,18 @@ class AgentController extends GetxController { |
|
|
Future<bool> _checkMicrophonePermission() async { |
|
|
Future<bool> _checkMicrophonePermission() async { |
|
|
try { |
|
|
try { |
|
|
PermissionStatus status = await Permission.microphone.status; |
|
|
PermissionStatus status = await Permission.microphone.status; |
|
|
|
|
|
|
|
|
// 如果已授权,直接返回 true |
|
|
// 如果已授权,直接返回 true |
|
|
if (status.isGranted) { |
|
|
if (status.isGranted) { |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 如果被永久拒绝,提示用户前往设置页面 |
|
|
// 如果被永久拒绝,提示用户前往设置页面 |
|
|
if (status.isPermanentlyDenied) { |
|
|
if (status.isPermanentlyDenied) { |
|
|
_showPermissionDialog(true); |
|
|
_showPermissionDialog(true); |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 如果之前拒绝但不是永久拒绝,或首次请求,尝试请求权限 |
|
|
// 如果之前拒绝但不是永久拒绝,或首次请求,尝试请求权限 |
|
|
if (status.isDenied) { |
|
|
if (status.isDenied) { |
|
|
status = await Permission.microphone.request(); |
|
|
status = await Permission.microphone.request(); |
|
|
@ -571,22 +568,22 @@ class AgentController extends GetxController { |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return false; |
|
|
return false; |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
logger.e('检查麦克风权限失败: $e'); |
|
|
logger.e('检查麦克风权限失败: $e'); |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 显示权限提示对话框 |
|
|
// 显示权限提示对话框 |
|
|
void _showPermissionDialog(bool isPermanent) { |
|
|
void _showPermissionDialog(bool isPermanent) { |
|
|
Get.dialog( |
|
|
Get.dialog( |
|
|
AlertDialog( |
|
|
AlertDialog( |
|
|
title: const Text('需要麦克风权限'), |
|
|
title: const Text('需要麦克风权限'), |
|
|
content: Text(isPermanent |
|
|
content: Text(isPermanent |
|
|
? '语音功能需要麦克风权限。请前往设置页面手动开启权限。' |
|
|
? '语音功能需要麦克风权限。请前往设置页面手动开启权限。' |
|
|
: '语音功能需要麦克风权限。请允许使用麦克风权限以继续使用语音功能。'), |
|
|
: '语音功能需要麦克风权限。请允许使用麦克风权限以继续使用语音功能。'), |
|
|
actions: [ |
|
|
actions: [ |
|
|
TextButton( |
|
|
TextButton( |
|
|
onPressed: () => Get.back(), |
|
|
onPressed: () => Get.back(), |
|
|
|