tanlongsheng 1 year ago
parent
commit
b19ac2926a
  1. 3
      lib/data/services/network/nw_api.dart
  2. 31
      lib/modules/agent/controllers/agent_controller.dart
  3. 78
      lib/modules/agent/views/agent_view.dart
  4. 2
      lib/modules/agent/views/message_bubble.dart
  5. 3
      lib/modules/home/bindings/home_binding.dart
  6. 9
      lib/modules/home/controllers/home_controller.dart
  7. 6
      lib/modules/home/views/home_view.dart
  8. 12
      lib/modules/ota_upgrade/views/ota_upgrade_view.dart

3
lib/data/services/network/nw_api.dart

@ -1,4 +1,5 @@
class NWApi { class NWApi {
// static const baseApi = "https://www.deapsound.com"; // static const baseApi = "https://www.deapsound.com";
static const baseApi = "https://api.deapsound.com"; // static const baseApi = "https://api.deapsound.com";
static const baseApi = "https://api.ideapsound.com";
} }

31
lib/modules/agent/controllers/agent_controller.dart

@ -13,15 +13,16 @@ import 'package:permission_handler/permission_handler.dart';
import 'package:app_settings/app_settings.dart'; import 'package:app_settings/app_settings.dart';
class Message { class Message {
final bool isUser; final bool isUser; //标识信息是否来自用户还是AI
final String text; final String text; //信息文本内容
final DateTime timestamp; final DateTime timestamp; // 消息时间戳
final bool isRecognizing; // 是否为语音识别中的临时消息 final bool isRecognizing; // 是否为语音识别中的临时消息
final bool hasImage; // 是否包含图片 final bool hasImage; // 是否包含图片
final String? imagePath; // 图片路径 final String? imagePath; // 图片路径
final Map? meta; //卡片数据 final Map? meta; //卡片数据
Message({ Message({
// 构造函数
required this.isUser, required this.isUser,
required this.text, required this.text,
DateTime? timestamp, DateTime? timestamp,
@ -33,14 +34,14 @@ class Message {
} }
class AgentController extends GetxController { class AgentController extends GetxController {
static AgentController get to => Get.find(); static AgentController get to => Get.find(); //单例访问模式
final logger = Logger(); final logger = Logger();
// 聊天消息列表 // 聊天消息列表
final messages = <Message>[].obs; final messages = <Message>[].obs;
// 控制器 // UI控制器
final TextEditingController textController = TextEditingController(); final TextEditingController textController = TextEditingController();
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
@ -49,10 +50,10 @@ class AgentController extends GetxController {
var isPlaying = false.obs; var isPlaying = false.obs;
var currentUrl = "".obs; var currentUrl = "".obs;
// 状态标志 // 各种状态标志
final isInitialized = false.obs; final isInitialized = false.obs;
final isListening = false.obs; final isListening = false.obs; //是否正在语音识别
final isSpeaking = false.obs; final isSpeaking = false.obs; //是否正在播放tts
final isProcessing = false.obs; final isProcessing = false.obs;
// TTS启用状态 // TTS启用状态
final isTtsEnabled = true.obs; final isTtsEnabled = true.obs;
@ -61,7 +62,7 @@ class AgentController extends GetxController {
final isImageProcessing = false.obs; final isImageProcessing = false.obs;
// 输入模式控制 // 输入模式控制
final isTextInputMode = true.obs; final isTextInputMode = true.obs; //文本输入模式vs语音输入模式
// 当前输入的文本内容 // 当前输入的文本内容
final currentText = ''.obs; final currentText = ''.obs;
@ -86,15 +87,15 @@ class AgentController extends GetxController {
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
_loadTtsPreference(); _loadTtsPreference(); //加载TTS偏好设置
_loadChatHistory(); _loadChatHistory(); //加载聊天历史记录
_subscribeToEvents(); _subscribeToEvents(); //订阅代理服务事件
} }
@override @override
void onClose() { void onClose() {
AgentService.stopConversation(); AgentService.stopConversation(); // 停止当前会话
AgentService.stopTts(); AgentService.stopTts(); // 停止当前语音
textController.dispose(); textController.dispose();
scrollController.dispose(); scrollController.dispose();
_eventSubscription?.cancel(); _eventSubscription?.cancel();
@ -179,7 +180,7 @@ class AgentController extends GetxController {
void _addWelcomeMessage() { void _addWelcomeMessage() {
messages.add(Message( messages.add(Message(
isUser: false, isUser: false,
text: '你好!我是DeepVoice AI助手,我能帮你:\n\n' text: '你好!我是Emma,我能帮你:\n\n'
'• 回答问题和提供信息\n' '• 回答问题和提供信息\n'
'• 实时语音翻译\n' '• 实时语音翻译\n'
'• 推荐音乐和播客\n' '• 推荐音乐和播客\n'

78
lib/modules/agent/views/agent_view.dart

@ -14,15 +14,14 @@ class AgentView extends StatelessWidget {
final primaryColor = theme.primaryColor; final primaryColor = theme.primaryColor;
final backgroundColor = theme.scaffoldBackgroundColor; final backgroundColor = theme.scaffoldBackgroundColor;
final isDarkMode = Theme.of(context).brightness == Brightness.dark; final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
elevation: 1, elevation: 1,
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
leading: IconButton( leading: IconButton(
icon: Icon(Icons.arrow_back_ios, icon: Icon(Icons.arrow_back_ios,
color: isDarkMode ? Colors.white : Colors.black87, color: isDarkMode ? Colors.white : Colors.black87, size: 20),
size: 20),
onPressed: () => Get.back(), onPressed: () => Get.back(),
), ),
titleSpacing: 0, titleSpacing: 0,
@ -53,7 +52,7 @@ class AgentView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'DeepVoice AI', 'Emma',
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -72,7 +71,7 @@ class AgentView extends StatelessWidget {
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Text(
'在线', '在线'.tr,
style: TextStyle( style: TextStyle(
fontSize: 12, fontSize: 12,
color: Colors.green, color: Colors.green,
@ -88,26 +87,27 @@ class AgentView extends StatelessWidget {
actions: [ actions: [
// TTS开关 // TTS开关
Obx(() => IconButton( Obx(() => IconButton(
icon: Icon( icon: Icon(
controller.isTtsEnabled.value controller.isTtsEnabled.value
? Icons.volume_up ? Icons.volume_up
: Icons.volume_off, : Icons.volume_off,
color: controller.isTtsEnabled.value color: controller.isTtsEnabled.value
? primaryColor ? primaryColor
: isDarkMode : isDarkMode
? Colors.grey[400] ? Colors.grey[400]
: Colors.grey, : Colors.grey,
), ),
onPressed: () => controller.toggleTts(), onPressed: () => controller.toggleTts(),
)), )),
// 更多选项 // 更多选项
Container( Container(
width: 34, width: 34,
height: 34, height: 34,
margin: const EdgeInsets.only(right: 8), margin: const EdgeInsets.only(right: 8),
decoration: BoxDecoration( decoration: BoxDecoration(
color: isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[100], color:
isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[100],
shape: BoxShape.circle, shape: BoxShape.circle,
boxShadow: [ boxShadow: [
if (!isDarkMode) if (!isDarkMode)
@ -119,9 +119,8 @@ class AgentView extends StatelessWidget {
], ],
), ),
child: PopupMenuButton( child: PopupMenuButton(
icon: Icon(Icons.more_vert, icon: Icon(Icons.more_vert,
color: isDarkMode ? Colors.white : Colors.black87, color: isDarkMode ? Colors.white : Colors.black87, size: 20),
size: 20),
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
@ -132,7 +131,7 @@ class AgentView extends StatelessWidget {
children: [ children: [
Icon(Icons.delete_outline, color: primaryColor, size: 20), Icon(Icons.delete_outline, color: primaryColor, size: 20),
const SizedBox(width: 8), const SizedBox(width: 8),
const Text('清除聊天记录', style: TextStyle(fontSize: 14)), Text('清除聊天记录'.tr, style: TextStyle(fontSize: 14)),
], ],
), ),
onTap: () => Future.delayed( onTap: () => Future.delayed(
@ -153,10 +152,12 @@ class AgentView extends StatelessWidget {
() => ListView.builder( () => ListView.builder(
controller: controller.scrollController, controller: controller.scrollController,
reverse: true, reverse: true,
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), padding:
const EdgeInsets.symmetric(vertical: 16, horizontal: 16),
itemCount: controller.messages.length, itemCount: controller.messages.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final message = controller.messages[controller.messages.length - 1 - index]; final message = controller
.messages[controller.messages.length - 1 - index];
return Padding( return Padding(
padding: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.only(bottom: 8),
child: MessageBubble( child: MessageBubble(
@ -245,19 +246,19 @@ class AgentView extends StatelessWidget {
children: [ children: [
_buildPromptChip( _buildPromptChip(
context: context, context: context,
label: '总结图片内容', label: '总结图片内容'.tr,
onTap: () => controller.summarizeImage(), onTap: () => controller.summarizeImage(),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
_buildPromptChip( _buildPromptChip(
context: context, context: context,
label: '抽取图像文字', label: '抽取图像文字'.tr,
onTap: () => controller.extractTextFromImage(), onTap: () => controller.extractTextFromImage(),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
_buildPromptChip( _buildPromptChip(
context: context, context: context,
label: '翻译图像文字', label: '翻译图像文字'.tr,
onTap: () => controller.translateImageText(), onTap: () => controller.translateImageText(),
), ),
], ],
@ -307,6 +308,7 @@ class AgentView extends StatelessWidget {
if (isTextMode) { if (isTextMode) {
// 文本输入模式 - 注意观察图片模式时的高度变化 // 文本输入模式 - 注意观察图片模式时的高度变化
return Container( return Container(
height: 44,
padding: const EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[200], color: Colors.grey[200],
@ -330,7 +332,9 @@ class AgentView extends StatelessWidget {
minLines: isImageActive ? 2 : 1, minLines: isImageActive ? 2 : 1,
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
color: isDarkMode ? Colors.white : Colors.black87, color: isDarkMode
? Colors.white
: Colors.black87,
), ),
decoration: InputDecoration( decoration: InputDecoration(
hintText: isImageActive hintText: isImageActive
@ -470,7 +474,8 @@ class AgentView extends StatelessWidget {
Icon(Icons.camera_alt, Icon(Icons.camera_alt,
color: primaryColor, size: 20), color: primaryColor, size: 20),
const SizedBox(width: 8), const SizedBox(width: 8),
const Text('拍照', style: TextStyle(fontSize: 14)), const Text('拍照',
style: TextStyle(fontSize: 14)),
], ],
), ),
), ),
@ -481,7 +486,8 @@ class AgentView extends StatelessWidget {
Icon(Icons.photo_library, Icon(Icons.photo_library,
color: primaryColor, size: 20), color: primaryColor, size: 20),
const SizedBox(width: 8), const SizedBox(width: 8),
const Text('从相册选择', style: TextStyle(fontSize: 14)), const Text('从相册选择',
style: TextStyle(fontSize: 14)),
], ],
), ),
), ),
@ -506,7 +512,7 @@ class AgentView extends StatelessWidget {
}) { }) {
final theme = Theme.of(context); final theme = Theme.of(context);
final primaryColor = theme.primaryColor; final primaryColor = theme.primaryColor;
return GestureDetector( return GestureDetector(
onTap: onTap, onTap: onTap,
child: Container( child: Container(
@ -614,14 +620,14 @@ class _SoundBarState extends State<_SoundBar>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final primaryColor = Theme.of(context).primaryColor; final primaryColor = Theme.of(context).primaryColor;
return Container( return Container(
width: 2.5, width: 2.5,
height: widget.isActive ? _animation.value : 3, height: widget.isActive ? _animation.value : 3,
margin: const EdgeInsets.symmetric(horizontal: 1), margin: const EdgeInsets.symmetric(horizontal: 1),
decoration: BoxDecoration( decoration: BoxDecoration(
color: widget.isActive color: widget.isActive
? primaryColor.withOpacity(0.8) ? primaryColor.withOpacity(0.8)
: Colors.grey.withOpacity(0.4), : Colors.grey.withOpacity(0.4),
borderRadius: BorderRadius.circular(1.5), borderRadius: BorderRadius.circular(1.5),
), ),

2
lib/modules/agent/views/message_bubble.dart

@ -311,7 +311,7 @@ class MessageBubble extends GetView<AgentController> {
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
Text( Text(
'雨天时光 · 播放列表', '播放列表'.tr,
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,

3
lib/modules/home/bindings/home_binding.dart

@ -1,4 +1,3 @@
import '../../explore/controllers/explore_controller.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../controllers/home_controller.dart'; import '../controllers/home_controller.dart';
@ -6,7 +5,5 @@ class HomeBinding extends Bindings {
@override @override
void dependencies() { void dependencies() {
Get.lazyPut<HomeController>(() => HomeController()); Get.lazyPut<HomeController>(() => HomeController());
Get.lazyPut<ExploreController>(
() => ExploreController()); // 注册ExploreController
} }
} }

9
lib/modules/home/controllers/home_controller.dart

@ -3,7 +3,6 @@ import 'dart:async';
import '../../../routes/app_routes.dart'; import '../../../routes/app_routes.dart';
import '../../../core/utils/logger.dart'; import '../../../core/utils/logger.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../../explore/controllers/explore_controller.dart';
import 'package:classic_bluetooth/classic_bluetooth.dart' show BluetoothDevice; import 'package:classic_bluetooth/classic_bluetooth.dart' show BluetoothDevice;
import '../../../data/services/bluetooth_manager.dart'; import '../../../data/services/bluetooth_manager.dart';
import '../../../data/services/ble_manager.dart'; import '../../../data/services/ble_manager.dart';
@ -20,9 +19,6 @@ enum ConnectionStatus {
class HomeController extends GetxController { class HomeController extends GetxController {
static HomeController get to => Get.find(); static HomeController get to => Get.find();
// 依赖的控制器
final ExploreController exploreController = Get.find<ExploreController>();
// 连接状态相关 // 连接状态相关
final _connectionStatus = ConnectionStatus.disconnected.obs; final _connectionStatus = ConnectionStatus.disconnected.obs;
final _connectionErrorMsg = ''.obs; final _connectionErrorMsg = ''.obs;
@ -197,11 +193,6 @@ class HomeController extends GetxController {
Get.toNamed(Routes.translation); Get.toNamed(Routes.translation);
} }
/// 打开AI伴侣功能
void openAIGirlfriend() {
exploreController.onAIFeatureTap(2);
}
/// 展示AI功能 /// 展示AI功能
void exploreAIFeatures() { void exploreAIFeatures() {
Get.toNamed(Routes.agent); Get.toNamed(Routes.agent);

6
lib/modules/home/views/home_view.dart

@ -461,8 +461,8 @@ class HomeView extends GetView<HomeController> {
), ),
SizedBox(height: 12.h), SizedBox(height: 12.h),
_buildBatteryInfoGrid(isDarkMode), _buildBatteryInfoGrid(isDarkMode),
SizedBox(height: 16.h), // SizedBox(height: 16.h),
_buildDeviceDetailsCard(isDarkMode), // _buildDeviceDetailsCard(isDarkMode),
], ],
); );
} }
@ -875,7 +875,7 @@ class HomeView extends GetView<HomeController> {
Color(0xFFFF5252).withOpacity(0.3), Color(0xFFFF5252).withOpacity(0.3),
], ],
), ),
onTap: controller.openAIGirlfriend, onTap: () {},
height: 85.h, // 增加高度 height: 85.h, // 增加高度
isDarkMode: isDarkMode, isDarkMode: isDarkMode,
iconColor: const Color(0xFFE91E63), iconColor: const Color(0xFFE91E63),

12
lib/modules/ota_upgrade/views/ota_upgrade_view.dart

@ -289,8 +289,16 @@ class OtaUpgradeView extends GetView<OtaUpgradeController> {
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: isDarkMode ? Colors.blue[300] : Colors.blue[700])), color: isDarkMode ? Colors.blue[300] : Colors.blue[700])),
SizedBox(height: 16), SizedBox(height: 16),
SizedBox( //SizedBox(
width: 240, //width: 240,
Container(
decoration: BoxDecoration(
border: Border.all(
color: isDarkMode ? Colors.blue[400]! : Colors.blue[300]!,
width: 1.5,
),
borderRadius: BorderRadius.circular(12),
),
child: LinearProgressIndicator( child: LinearProgressIndicator(
value: controller.downloadProgress.value, value: controller.downloadProgress.value,
backgroundColor: backgroundColor:

Loading…
Cancel
Save