import 'package:get/get.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import '../../im/im_manager.dart'; import 'package:im_flutter_sdk/im_flutter_sdk.dart'; import 'conversation_controller.dart'; class ChatController extends GetxController { final String userId; // 用户信息 final Rx userInfo = Rx(null); // 消息列表 final RxList messages = RxList([]); // 加载更多的游标 String? _cursor; // 视频发送状态 final RxBool isSendingVideo = RxBool(false); final RxString sendingStatus = RxString(''); ChatController({required this.userId}); @override void onInit() { super.onInit(); // 注册到 IMManager,以便接收消息时能通知到此 Controller IMManager.instance.registerChatController(this); // 初始化时获取用户信息和消息列表 fetchUserInfo(); fetchMessages(); } @override void onClose() { // 注销 ChatController IMManager.instance.unregisterChatController(userId); super.onClose(); } /// 获取用户信息 Future fetchUserInfo() async { try { final EMUserInfo? info = await IMManager.instance.getUserInfo(userId); if (info != null) { userInfo.value = info; update(); // 通知 GetBuilder 更新 UI if (Get.isLogEnable) { Get.log('获取用户信息成功: ${info.nickName}'); } } else { if (Get.isLogEnable) { Get.log('未找到用户信息: $userId'); } } } catch (e) { if (Get.isLogEnable) { Get.log('获取用户信息失败: $e'); } } } /// 发送消息 Future sendMessage(String content) async { try { // 先创建消息对象(即使发送失败也要显示在列表中) final tempMessage = EMMessage.createTxtSendMessage( targetId: userId, content: content, ); // 将消息添加到列表末尾(显示发送中状态) messages.add(tempMessage); update(); // 尝试发送消息 final message = await IMManager.instance.sendTextMessage(content, userId); if (message != null) { // 发送成功,替换临时消息 final index = messages.indexWhere((msg) => msg.msgId == tempMessage.msgId); if (index != -1) { messages[index] = message; } update(); // 更新会话列表 _refreshConversationList(); return true; } else { // 发送失败,消息状态会自动变为FAIL update(); SmartDialog.showToast('消息发送失败,请点击重发'); return false; } } catch (e) { if (Get.isLogEnable) { Get.log('发送消息失败: $e'); } SmartDialog.showToast('消息发送失败: $e'); return false; } } /// 发送图片消息 Future sendImageMessage(String imagePath) async { try { // 先创建消息对象(即使发送失败也要显示在列表中) final tempMessage = EMMessage.createImageSendMessage( targetId: userId, filePath: imagePath, sendOriginalImage: false, ); // 将消息添加到列表末尾(显示发送中状态) messages.add(tempMessage); update(); // 尝试发送消息 final message = await IMManager.instance.sendImageMessage( imagePath, userId, ); if (message != null) { // 发送成功,替换临时消息 final index = messages.indexWhere((msg) => msg.msgId == tempMessage.msgId); if (index != -1) { messages[index] = message; } update(); // 更新会话列表 _refreshConversationList(); return true; } else { // 发送失败,消息状态会自动变为FAIL update(); SmartDialog.showToast('图片发送失败,请点击重发'); return false; } } catch (e) { if (Get.isLogEnable) { Get.log('发送图片消息失败: $e'); } SmartDialog.showToast('图片发送失败: $e'); return false; } } /// 发送语音消息 Future sendVoiceMessage(String filePath, int seconds) async { try { // 先创建消息对象(即使发送失败也要显示在列表中) final tempMessage = EMMessage.createVoiceSendMessage( targetId: userId, filePath: filePath, duration: seconds, ); // 将消息添加到列表末尾(显示发送中状态) messages.add(tempMessage); update(); // 尝试发送消息 final message = await IMManager.instance.sendVoiceMessage( filePath, userId, seconds, ); if (message != null) { // 发送成功,替换临时消息 final index = messages.indexWhere((msg) => msg.msgId == tempMessage.msgId); if (index != -1) { messages[index] = message; } update(); // 更新会话列表 _refreshConversationList(); return true; } else { // 发送失败,消息状态会自动变为FAIL update(); SmartDialog.showToast('语音发送失败,请点击重发'); return false; } } catch (e) { if (Get.isLogEnable) { Get.log('发送语音消息失败: $e'); } SmartDialog.showToast('语音发送失败: $e'); return false; } } /// 发送视频消息 Future sendVideoMessage(String filePath, int duration) async { try { print('🎬 [ChatController] 准备发送视频消息'); print('视频路径: $filePath'); print('视频时长: $duration 秒'); // 先创建消息对象(即使发送失败也要显示在列表中) final tempMessage = EMMessage.createVideoSendMessage( targetId: userId, filePath: filePath, duration: duration, ); // 将消息添加到列表末尾(显示发送中状态) messages.add(tempMessage); update(); // 尝试发送消息(后台上传,消息状态会自动更新) final message = await IMManager.instance.sendVideoMessage( filePath, userId, duration, ); if (message != null) { print('✅ [ChatController] 视频消息发送成功'); // 发送成功,替换临时消息 final index = messages.indexWhere((msg) => msg.msgId == tempMessage.msgId); if (index != -1) { messages[index] = message; } update(); // 更新会话列表 _refreshConversationList(); return true; } else { // 发送失败,消息状态会自动变为FAIL update(); SmartDialog.showToast('视频发送失败,请点击重发'); return false; } } catch (e) { if (Get.isLogEnable) { Get.log('发送视频消息失败: $e'); } SmartDialog.showToast('视频发送失败: $e'); return false; } } /// 获取消息列表 Future fetchMessages({bool loadMore = false}) async { try { // 如果加载更多但没有游标,说明已经加载完所有消息 if (loadMore && _cursor == null) { if (Get.isLogEnable) { Get.log('没有更多消息了'); } return; } final List fetchedMessages = await IMManager.instance .getMessages( userId, pageSize: 20, startMsgId: loadMore ? _cursor : null, ); // 过滤掉null消息 final List validMessages = fetchedMessages .whereType() .toList(); if (loadMore) { // 加载更多时,需要去重并添加到列表开头(更旧的消息) final existingMsgIds = messages.map((msg) => msg.msgId).toSet(); final newMessages = validMessages .where((msg) => !existingMsgIds.contains(msg.msgId)) .toList(); if (newMessages.isNotEmpty) { messages.insertAll(0, newMessages); // 更新游标为最旧的消息ID(列表开头) _cursor = newMessages.first.msgId; if (Get.isLogEnable) { Get.log('加载更多消息成功,新增: ${newMessages.length} 条,总数量: ${messages.length}'); } } else { // 没有新消息,说明已经加载完所有消息 _cursor = null; if (Get.isLogEnable) { Get.log('没有更多消息了'); } } } else { // 刷新时替换整个列表 messages.assignAll(validMessages); // 更新游标为最旧的消息ID(列表开头) if (validMessages.isNotEmpty) { _cursor = validMessages.first.msgId; } else { _cursor = null; } if (Get.isLogEnable) { Get.log('刷新消息成功,数量: ${validMessages.length}'); } } // 通知UI更新 update(); } catch (e) { if (Get.isLogEnable) { Get.log('获取消息失败: $e'); } } } /// 加载更多消息 Future loadMoreMessages() async { if (_cursor != null) { await fetchMessages(loadMore: true); } } /// 检查是否还有更多消息可以加载 bool hasMoreMessages() { return _cursor != null; } /// 添加接收到的消息 void addReceivedMessage(EMMessage message) { // 检查消息是否已存在(避免重复添加) if (!messages.any((msg) => msg.msgId == message.msgId)) { // 将新消息添加到列表末尾 messages.add(message); update(); // 更新会话列表 _refreshConversationList(); if (Get.isLogEnable) { Get.log('收到新消息并添加到列表: ${message.msgId}'); } } } /// 撤回消息 Future recallMessage(EMMessage message) async { try { final success = await IMManager.instance.recallMessage(message); if (success) { // 从消息列表中移除或更新消息 final index = messages.indexWhere((msg) => msg.msgId == message.msgId); if (index != -1) { // 可以保留消息但标记为已撤回,或者直接移除 // 这里选择移除消息 messages.removeAt(index); update(); } // 更新会话列表 _refreshConversationList(); SmartDialog.showToast('消息已撤回'); return true; } return false; } catch (e) { if (Get.isLogEnable) { Get.log('撤回消息失败: $e'); } SmartDialog.showToast('撤回消息失败'); return false; } } /// 删除消息 Future deleteMessage(EMMessage message, {bool deleteRemote = false}) async { try { final conversationId = message.conversationId ?? userId; final messageId = message.msgId; if (messageId.isEmpty) { if (Get.isLogEnable) { Get.log('消息ID为空,无法删除'); } return false; } final success = await IMManager.instance.deleteMessage(conversationId, messageId, deleteRemote: deleteRemote); if (success) { // 从消息列表中移除 final index = messages.indexWhere((msg) => msg.msgId == message.msgId); if (index != -1) { messages.removeAt(index); update(); } // 更新会话列表 _refreshConversationList(); SmartDialog.showToast('消息已删除'); return true; } return false; } catch (e) { if (Get.isLogEnable) { Get.log('删除消息失败: $e'); } SmartDialog.showToast('删除消息失败'); return false; } } /// 标记消息为已读 Future markMessageAsRead(String messageId) async { try { final success = await IMManager.instance.markMessageAsRead(userId, messageId); if (success) { // 更新消息的已读状态 final index = messages.indexWhere((msg) => msg.msgId == messageId); if (index != -1) { update(); } // 更新会话列表 _refreshConversationList(); return true; } return false; } catch (e) { if (Get.isLogEnable) { Get.log('标记消息为已读失败: $e'); } return false; } } /// 标记会话所有消息为已读 Future markAllMessagesAsRead() async { try { final success = await IMManager.instance.markAllMessagesAsRead(userId); if (success) { // 更新所有消息的已读状态 update(); // 更新会话列表 _refreshConversationList(); return true; } return false; } catch (e) { if (Get.isLogEnable) { Get.log('标记所有消息为已读失败: $e'); } return false; } } /// 处理消息撤回通知 void handleMessageRecalled(EMMessage message) { try { // 从消息列表中移除或更新消息 final index = messages.indexWhere((msg) => msg.msgId == message.msgId); if (index != -1) { messages.removeAt(index); update(); } // 更新会话列表 _refreshConversationList(); if (Get.isLogEnable) { Get.log('处理消息撤回: ${message.msgId}'); } } catch (e) { if (Get.isLogEnable) { Get.log('处理消息撤回失败: $e'); } } } /// 更新消息状态 void updateMessageStatus(EMMessage message, MessageStatus status) { try { final index = messages.indexWhere((msg) => msg.msgId == message.msgId); if (index != -1) { // 更新消息状态 update(); if (Get.isLogEnable) { Get.log('更新消息状态: ${message.msgId}, status=$status'); } } } catch (e) { if (Get.isLogEnable) { Get.log('更新消息状态失败: $e'); } } } /// 检查消息是否发送失败 bool isMessageFailed(EMMessage message) { return message.status == MessageStatus.FAIL; } /// 重发消息 Future resendMessage(EMMessage failedMessage) async { try { if (Get.isLogEnable) { Get.log('🔄 [ChatController] 开始重发消息: ${failedMessage.msgId}'); } // 调用IMManager的重发方法 final newMessage = await IMManager.instance.resendMessage(failedMessage); if (newMessage != null) { // 找到原消息并替换 final index = messages.indexWhere((msg) => msg.msgId == failedMessage.msgId); if (index != -1) { messages[index] = newMessage; update(); if (Get.isLogEnable) { Get.log('✅ [ChatController] 消息重发成功'); } // 更新会话列表 _refreshConversationList(); SmartDialog.showToast('消息已重发'); return true; } } else { if (Get.isLogEnable) { Get.log('❌ [ChatController] 消息重发失败'); } SmartDialog.showToast('消息重发失败,请重试'); return false; } return false; } catch (e) { if (Get.isLogEnable) { Get.log('❌ [ChatController] 重发消息异常: $e'); } SmartDialog.showToast('重发消息失败: $e'); return false; } } /// 刷新会话列表 void _refreshConversationList() { try { // 尝试获取 ConversationController 并刷新会话列表 if (Get.isRegistered()) { final conversationController = Get.find(); conversationController.refreshConversations(); } } catch (e) { // ConversationController 可能未注册,忽略错误 if (Get.isLogEnable) { Get.log('刷新会话列表失败: $e'); } } } }