import 'dart:io'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:im_flutter_sdk/im_flutter_sdk.dart'; import 'package:video_thumbnail/video_thumbnail.dart'; import 'package:path_provider/path_provider.dart'; import '../controller/message/conversation_controller.dart'; import '../controller/message/chat_controller.dart'; import '../controller/global.dart'; // 完整的IM管理器实现,使用实际的SDK类型和方法 class IMManager { // 单例模式 static final IMManager _instance = IMManager._internal(); factory IMManager() => _instance; final storage = GetStorage(); // 静态getter用于instance访问 static IMManager get instance => _instance; bool _isInitialized = false; bool _listenersRegistered = false; bool _isLoggedIn = false; // 监听器标识符 static const String _connectionHandlerKey = 'im_manager_connection_handler'; static const String _chatHandlerKey = 'im_manager_chat_handler'; // 存储活跃的 ChatController 实例,key 为 userId final Map _activeChatControllers = {}; IMManager._internal() { print('IMManager instance created'); } /// 初始化IM SDK Future initialize(String appKey) async { try { if (_isInitialized) { print('IM SDK already initialized'); return true; } // 创建EMOptions实例 final options = EMOptions( appKey: appKey, autoLogin: false, acceptInvitationAlways: false, ); // 初始化SDK await EMClient.getInstance.init(options); _isInitialized = true; print('IM SDK initialized successfully'); return true; } catch (e) { print('Failed to initialize IM SDK: $e'); return false; } } // 注册监听器 void _registerListeners() { try { // 防止重复注册 if (_listenersRegistered) { if (Get.isLogEnable) { Get.log('监听器已注册,跳过重复注册'); } return; } // 连接监听器 EMClient.getInstance.addConnectionEventHandler( _connectionHandlerKey, EMConnectionEventHandler( onConnected: () { if (Get.isLogEnable) { Get.log('✅ [IMManager] 已连接到IM服务器'); } // 连接成功后,通知 ConversationController 加载会话列表 _refreshConversationList(); }, onDisconnected: () { if (Get.isLogEnable) { Get.log('❌ [IMManager] 与IM服务器断开连接'); } // TODO: 可以在这里添加自动重连逻辑 }, onTokenDidExpire: () { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] IM token即将过期'); } // TODO: 可以在这里添加自动刷新token的逻辑 }, onUserKickedByOtherDevice: () { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] 用户被其他设备踢出'); } // TODO: 可以在这里添加处理逻辑,如跳转到登录页 }, ), ); // 消息监听器 EMClient.getInstance.chatManager.addEventHandler( _chatHandlerKey, EMChatEventHandler( onMessagesReceived: (messages) { if (Get.isLogEnable) { Get.log('📨 [IMManager] 收到 ${messages.length} 条新消息'); } // 从消息扩展字段中解析用户信息并缓存 for (var message in messages) { if (message.direction == MessageDirection.RECEIVE) { _parseUserInfoFromMessageExt(message); } } // 收到新消息时,更新会话列表 _refreshConversationList(); // 通知对应的 ChatController 更新消息列表 _notifyChatControllers(messages); }, onCmdMessagesReceived: (cmdMessages) { if (Get.isLogEnable) { Get.log('📨 [IMManager] 收到 ${cmdMessages.length} 条CMD消息'); } // 处理CMD消息(如撤回消息等) for (var msg in cmdMessages) { _handleCmdMessage(msg); } }, ), ); EMClient.getInstance.chatManager.addMessageEvent(_chatHandlerKey, ChatMessageEvent( onSuccess: (str, message){ Get.log('✅ [IMManager] 发送消息成功: $str'); }, onError: (str, message, err){ //code: 508为拦截 Get.log('❌ [IMManager] 发送消息失败: $err----$str'); }, )); _listenersRegistered = true; if (Get.isLogEnable) { Get.log('✅ [IMManager] 监听器注册成功'); } } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 注册监听器失败: $e'); } } } /// 登录IM服务 Future login(String token) async { try { if (!_isInitialized) { print('IM SDK not initialized'); return false; } var userId = storage.read('userId'); if (Get.isLogEnable) { Get.log('🔐 [IMManager] 准备登录IM,userId: $userId'); } else { print('🔐 [IMManager] 准备登录IM,userId: $userId'); } await EMClient.getInstance.logout(); await EMClient.getInstance.loginWithToken(userId, token); // 注册监听器 _registerListeners(); // 设置登录状态 _isLoggedIn = true; // 登录成功后,通知 ConversationController 刷新会话列表 _refreshConversationList(); if (Get.isLogEnable) { Get.log('✅ [IMManager] IM登录成功,userId: $userId'); } else { print('✅ [IMManager] IM登录成功,userId: $userId'); } return true; } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] IM登录失败: $e'); } else { print('❌ [IMManager] IM登录失败: $e'); } return false; } } /// 登出IM服务 Future logout() async { try { await EMClient.getInstance.logout(); // 清除登录状态 _isLoggedIn = false; print('IM logout successful'); return true; } catch (e) { print('IM logout failed: $e'); return false; } } /// 检查是否已登录 bool get isLoggedIn => _isLoggedIn; /// 检查用户是否存在于IM系统中 Future checkUserExists(String userId) async { try { final userInfo = await getUserInfo(userId); if (userInfo != null) { if (Get.isLogEnable) { Get.log('✅ [IMManager] 用户存在: $userId'); } else { print('✅ [IMManager] 用户存在: $userId'); } return true; } else { if (Get.isLogEnable) { Get.log('❌ [IMManager] 用户不存在: $userId'); } else { print('❌ [IMManager] 用户不存在: $userId'); } return false; } } catch (e) { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] 检查用户是否存在失败: $e'); } else { print('⚠️ [IMManager] 检查用户是否存在失败: $e'); } return false; } } /// 发送文本消息 Future sendTextMessage( String content, String toChatUsername, ) async { try { // 检查是否已登录 // 注意:如果发送失败,可能是未登录或目标用户ID不正确 if (Get.isLogEnable) { Get.log('📤 [IMManager] 准备发送消息: to=$toChatUsername, content=$content'); } else { print('📤 [IMManager] 准备发送消息: to=$toChatUsername, content=$content'); } // 检查当前登录的用户ID final currentUserId = storage.read('userId'); if (Get.isLogEnable) { Get.log('📤 [IMManager] 当前登录用户ID: $currentUserId, 目标用户ID: $toChatUsername'); } else { print('📤 [IMManager] 当前登录用户ID: $currentUserId, 目标用户ID: $toChatUsername'); } // 检查目标用户是否存在于IM系统中 final userExists = await checkUserExists(toChatUsername); if (!userExists) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 目标用户不存在于IM系统中: $toChatUsername'); } else { print('❌ [IMManager] 目标用户不存在于IM系统中: $toChatUsername'); } // 即使用户不存在,也尝试发送,因为某些IM系统可能允许发送给未注册用户 // 但会记录警告信息 } // 创建文本消息 final message = EMMessage.createTxtSendMessage( targetId: toChatUsername, content: content, ); // 在消息扩展字段中添加当前用户信息(用于接收方显示头像和昵称) _addUserInfoToMessageExt(message); // 发送消息(如果未登录会抛出异常) final sentMessage = await EMClient.getInstance.chatManager.sendMessage(message); if (Get.isLogEnable) { Get.log('✅ [IMManager] 文本消息发送成功: to=$toChatUsername, content=$content'); } else { print('✅ [IMManager] 文本消息发送成功: to=$toChatUsername, content=$content'); } return sentMessage; } catch (e) { // 捕获异常,可能是未登录或其他错误 if (Get.isLogEnable) { Get.log('❌ [IMManager] 发送文本消息失败: to=$toChatUsername, 错误: $e'); } else { print('❌ [IMManager] 发送文本消息失败: to=$toChatUsername, 错误: $e'); } return null; } } /// 发送语音消息 Future sendVoiceMessage( String filePath, String toChatUsername, int duration, ) async { try { // 创建语音消息 final message = EMMessage.createVoiceSendMessage( targetId: toChatUsername, filePath: filePath, duration: duration, ); // 在消息扩展字段中添加当前用户信息 _addUserInfoToMessageExt(message); // 发送消息 await EMClient.getInstance.chatManager.sendMessage(message); if (Get.isLogEnable) { Get.log('✅ [IMManager] 语音消息发送成功'); } return message; } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 发送语音消息失败: $e'); } return null; } } /// 发送图片消息 Future sendImageMessage( String imagePath, String toChatUsername, ) async { try { // 创建图片消息 final message = EMMessage.createImageSendMessage( targetId: toChatUsername, filePath: imagePath, sendOriginalImage: false, ); // 在消息扩展字段中添加当前用户信息 _addUserInfoToMessageExt(message); // 发送消息 await EMClient.getInstance.chatManager.sendMessage(message); print('Image message sent successfully'); return message; } catch (e) { print('Failed to send image message: $e'); return null; } } /// 发送视频消息 Future sendVideoMessage( String videoPath, String toChatUsername, int duration, ) async { try { print('🎬 [IMManager] 创建视频消息'); print('视频路径: $videoPath'); print('接收用户: $toChatUsername'); print('视频时长: $duration 秒'); // 🎯 手动生成视频缩略图 String? thumbnailPath; try { print('📸 [IMManager] 开始生成视频缩略图...'); // 获取临时目录 final tempDir = await getTemporaryDirectory(); final fileName = videoPath.split('/').last.split('.').first; final thumbFileName = '${fileName}_thumb.jpg'; thumbnailPath = '${tempDir.path}/$thumbFileName'; // 使用 video_thumbnail 生成缩略图 final uint8list = await VideoThumbnail.thumbnailFile( video: videoPath, thumbnailPath: thumbnailPath, imageFormat: ImageFormat.JPEG, maxWidth: 400, // 缩略图最大宽度 quality: 75, // 图片质量 ); if (uint8list != null && File(uint8list).existsSync()) { thumbnailPath = uint8list; print('✅ [IMManager] 缩略图生成成功: $thumbnailPath'); } else { print('⚠️ [IMManager] 缩略图生成返回null'); thumbnailPath = null; } } catch (e) { print('❌ [IMManager] 生成缩略图失败: $e'); thumbnailPath = null; } // 创建视频消息 final message = EMMessage.createVideoSendMessage( targetId: toChatUsername, filePath: videoPath, duration: duration, thumbnailLocalPath: thumbnailPath, // 🎯 指定缩略图路径 ); // 在消息扩展字段中添加当前用户信息 _addUserInfoToMessageExt(message); print('消息创建成功,消息类型: ${message.body.type}'); print('消息体是否为视频: ${message.body is EMVideoMessageBody}'); // 检查缩略图信息 if (message.body is EMVideoMessageBody) { final videoBody = message.body as EMVideoMessageBody; print('📸 [IMManager] 缩略图本地路径: ${videoBody.thumbnailLocalPath}'); print('📸 [IMManager] 缩略图远程路径: ${videoBody.thumbnailRemotePath}'); // 验证缩略图文件是否存在 if (videoBody.thumbnailLocalPath != null) { final thumbFile = File(videoBody.thumbnailLocalPath!); print('📸 [IMManager] 缩略图文件是否存在: ${thumbFile.existsSync()}'); } } // 发送消息 await EMClient.getInstance.chatManager.sendMessage(message); print('✅ [IMManager] 视频消息发送成功'); return message; } catch (e) { print('❌ [IMManager] 发送视频消息失败: $e'); return null; } } /// 发送自定义消息 Future sendCustomMessage(String targetId, String event, Map? data) async { final customMsg = EMMessage.createCustomSendMessage( targetId: targetId, // `event` 为需要传递的自定义消息事件,比如礼物消息,可以设置: event: event, // `params` 类型为 `Map`。 params: data, ); return await EMClient.getInstance.chatManager.sendMessage(customMsg); } /// 获取所有联系人 Future> getAllContacts() async { return await EMClient.getInstance.contactManager.fetchAllContacts(); } /// 获取会话列表 Future> getConversations() async { return await EMClient.getInstance.chatManager.loadAllConversations(); } /// 获取用户信息(单个用户) /// 删除指定会话 Future deleteConversation( String conversationId, { bool deleteMessages = true, }) async { try { await EMClient.getInstance.chatManager.deleteConversation( conversationId, deleteMessages: deleteMessages, ); return true; } catch (e) { if (Get.isLogEnable) { Get.log('删除会话失败: $e'); } else { print('删除会话失败: $e'); } return false; } } /// 获取好有列表 Future> getContacts(String userId) async { return await EMClient.getInstance.userInfoManager.fetchUserInfoById([ userId, ]); } /// 获取指定会话的消息记录 Future> getMessages( String conversationId, { int pageSize = 20, String? startMsgId, bool createIfNeed = false, }) async { try { EMConversationType convType = EMConversationType.Chat; // 获取会话对象 final conversation = await EMClient.getInstance.chatManager.getConversation( conversationId, type: convType, createIfNeed: createIfNeed, ); if (conversation == null) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 会话不存在: $conversationId'); } return []; } // 如果有startMsgId,从该消息开始加载;否则加载最新消息 if (startMsgId != null && startMsgId.isNotEmpty) { // 从指定消息ID开始加载更旧的消息 final messages = await conversation.loadMessages( startMsgId: startMsgId, loadCount: pageSize, ); return messages.map((msg) => msg as EMMessage?).toList(); } else { // 加载最新消息 final messages = await conversation.loadMessages( loadCount: pageSize, ); return messages.map((msg) => msg as EMMessage?).toList(); } } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 获取消息失败: $e'); } return []; } } /// 从 SDK 重新获取消息的最新状态(用于检查消息发送状态) Future getMessageById(String conversationId, String messageId) async { try { EMConversationType convType = EMConversationType.Chat; // 获取会话对象 final conversation = await EMClient.getInstance.chatManager.getConversation( conversationId, type: convType, createIfNeed: false, ); if (conversation == null) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 会话不存在: $conversationId'); } return null; } // 加载最新消息(包含刚发送的消息) final messages = await conversation.loadMessages(loadCount: 50); // 查找指定 messageId 的消息 for (var msg in messages) { if (msg.msgId == messageId) { return msg; } } return null; } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 获取消息状态失败: $e'); } return null; } } /// 获取用户信息 Future getUserInfo(String userId) async { var data = await EMClient.getInstance.userInfoManager.fetchUserInfoById([ userId, ]); return data[userId]; } /// 在消息扩展字段中添加当前用户信息 /// 这样接收方可以从消息中获取发送方的头像和昵称 void _addUserInfoToMessageExt(EMMessage message) { try { // 获取当前登录用户ID final currentUserId = storage.read('userId'); if (currentUserId == null) { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] 无法获取当前用户ID,跳过添加用户信息到消息扩展字段'); } return; } // 获取接收者ID(消息的 to 字段) final receiverId = message.to; // ========== 获取发送者信息 ========== String? senderNickName; String? senderAvatarUrl; // 尝试从 ChatController 获取发送者信息 final senderChatController = _activeChatControllers[currentUserId]; if (senderChatController != null) { senderNickName = senderChatController.userNickName; senderAvatarUrl = senderChatController.userAvatarUrl; } // 如果 ChatController 中没有,尝试从全局数据获取 if (senderNickName == null || senderAvatarUrl == null) { try { final globalData = GlobalData.instance; final userData = globalData.userData; if (userData != null) { senderNickName = senderNickName ?? userData.nickName; senderAvatarUrl = senderAvatarUrl ?? userData.profilePhoto; } } catch (e) { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] 从 GlobalData 获取发送者信息失败: $e'); } } } // ========== 获取接收者信息 ========== String? receiverNickName; String? receiverAvatarUrl; // 尝试从 ChatController 获取接收者信息(通过接收者ID查找) if (receiverId != null && receiverId.isNotEmpty) { final receiverChatController = _activeChatControllers[receiverId]; if (receiverChatController != null && receiverChatController.userData != null) { // 从接收者的 ChatController 获取接收者的信息 // 注意:这里获取的是接收者自己的信息(用于发送方在聊天列表显示) receiverNickName = receiverChatController.userData!.nickName; receiverAvatarUrl = receiverChatController.userData!.profilePhoto; } } // ========== 设置消息扩展字段 ========== // 同时存储发送者和接收者的信息 // 发送者信息:用于接收方在聊天列表显示发送者的头像和昵称 // 接收者信息:用于发送方在聊天列表显示接收者的头像和昵称 if (message.attributes == null) { message.attributes = {}; } // 发送者信息(sender_ 前缀) message.attributes!['sender_userId'] = currentUserId; if (senderNickName != null && senderNickName.isNotEmpty) { message.attributes!['sender_nickName'] = senderNickName; } if (senderAvatarUrl != null && senderAvatarUrl.isNotEmpty) { final cleanSenderAvatarUrl = senderAvatarUrl.trim().replaceAll('`', ''); message.attributes!['sender_avatarUrl'] = cleanSenderAvatarUrl; } // 接收者信息(receiver_ 前缀) if (receiverId != null && receiverId.isNotEmpty) { message.attributes!['receiver_userId'] = receiverId; if (receiverNickName != null && receiverNickName.isNotEmpty) { message.attributes!['receiver_nickName'] = receiverNickName; } if (receiverAvatarUrl != null && receiverAvatarUrl.isNotEmpty) { final cleanReceiverAvatarUrl = receiverAvatarUrl.trim().replaceAll('`', ''); message.attributes!['receiver_avatarUrl'] = cleanReceiverAvatarUrl; } } // 为了兼容旧代码,也保留原来的字段(发送者信息) message.attributes!['userId'] = currentUserId; if (senderNickName != null && senderNickName.isNotEmpty) { message.attributes!['nickName'] = senderNickName; } if (senderAvatarUrl != null && senderAvatarUrl.isNotEmpty) { final cleanSenderAvatarUrl = senderAvatarUrl.trim().replaceAll('`', ''); message.attributes!['avatarUrl'] = cleanSenderAvatarUrl; } if (Get.isLogEnable) { Get.log('✅ [IMManager] 已添加用户信息到消息扩展字段:'); Get.log(' 发送者: userId=$currentUserId, nickName=$senderNickName, avatarUrl=${senderAvatarUrl?.trim().replaceAll('`', '')}'); Get.log(' 接收者: userId=$receiverId, nickName=$receiverNickName, avatarUrl=${receiverAvatarUrl?.trim().replaceAll('`', '')}'); } } catch (e) { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] 添加用户信息到消息扩展字段失败: $e'); } } } /// 从消息扩展字段中解析用户信息并缓存 void _parseUserInfoFromMessageExt(EMMessage message) { try { // 获取发送方用户ID final fromUserId = message.from; if (fromUserId == null || fromUserId.isEmpty) { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] 消息发送者ID为空,跳过解析用户信息'); } return; } // 从消息扩展字段中获取用户信息 Map? attributes; try { attributes = message.attributes; } catch (e) { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] 无法访问消息扩展字段: $e'); } return; } if (attributes == null || attributes.isEmpty) { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] 消息扩展字段为空: msgId=${message.msgId}, fromUserId=$fromUserId'); } return; } if (Get.isLogEnable) { Get.log('🔍 [IMManager] 消息扩展字段内容: $attributes'); } final nickName = attributes['nickName'] as String?; final avatarUrl = attributes['avatarUrl'] as String?; if (nickName == null && avatarUrl == null) { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] 消息扩展字段中没有用户信息: msgId=${message.msgId}'); } return; } // 缓存用户信息到 ConversationController if (Get.isRegistered()) { final conversationController = Get.find(); final extendedInfo = ExtendedUserInfo( userId: fromUserId, nickName: nickName, avatarUrl: avatarUrl, ); conversationController.cacheUserInfo(fromUserId, extendedInfo); if (Get.isLogEnable) { Get.log('✅ [IMManager] 从消息扩展字段解析并缓存用户信息: userId=$fromUserId, nickName=$nickName, avatarUrl=$avatarUrl'); } } else { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] ConversationController 未注册,无法缓存用户信息'); } } } catch (e) { if (Get.isLogEnable) { Get.log('⚠️ [IMManager] 从消息扩展字段解析用户信息失败: $e'); } } } /// 注册 ChatController void registerChatController(ChatController controller) { _activeChatControllers[controller.userId] = controller; if (Get.isLogEnable) { Get.log('注册 ChatController: ${controller.userId}'); } } /// 注销 ChatController void unregisterChatController(String userId) { _activeChatControllers.remove(userId); if (Get.isLogEnable) { Get.log('注销 ChatController: $userId'); } } /// 通知 ChatController 更新消息列表 void _notifyChatControllers(List messages) { try { // 遍历所有收到的消息 for (var message in messages) { // 只处理接收到的消息(direction == RECEIVE) if (message.direction == MessageDirection.RECEIVE) { // 获取消息的发送者ID(from 属性) final fromId = message.from; if (fromId != null && fromId.isNotEmpty) { // 查找对应的 ChatController final controller = _activeChatControllers[fromId]; if (controller != null) { controller.addReceivedMessage(message); if (Get.isLogEnable) { Get.log('通知 ChatController 更新消息: $fromId'); } } } } } } catch (e) { if (Get.isLogEnable) { Get.log('通知 ChatController 更新消息列表失败: $e'); } } } /// 刷新会话列表 void _refreshConversationList() { try { // 尝试获取 ConversationController 并刷新会话列表 if (Get.isRegistered()) { final conversationController = Get.find(); conversationController.refreshConversations(); } } catch (e) { // ConversationController 可能未注册,忽略错误 if (Get.isLogEnable) { Get.log('刷新会话列表失败: $e'); } } } /// 添加用户到黑名单 Future addToBlacklist(String userId) async { try { await EMClient.getInstance.contactManager.addUserToBlockList(userId); print('已将用户 $userId 添加到黑名单'); } catch (e) { print('添加黑名单失败: $e'); rethrow; } } /// 从黑名单移除用户 Future removeFromBlacklist(String userId) async { try { await EMClient.getInstance.contactManager.removeUserFromBlockList(userId); print('已将用户 $userId 从黑名单移除'); } catch (e) { print('移除黑名单失败: $e'); rethrow; } } /// 获取黑名单列表 Future> getBlacklist() async { try { final list = await EMClient.getInstance.contactManager.getBlockListFromServer(); print('获取黑名单列表成功,共 ${list.length} 个用户'); return list; } catch (e) { print('获取黑名单列表失败: $e'); return []; } } /// 处理CMD消息 void _handleCmdMessage(EMMessage cmdMessage) { try { // 这里可以处理各种CMD消息,如撤回消息等 if (Get.isLogEnable) { Get.log('处理CMD消息: ${cmdMessage.msgId}'); } } catch (e) { if (Get.isLogEnable) { Get.log('处理CMD消息失败: $e'); } } } // 注意:以下方法保留用于未来扩展,当SDK支持更多回调时可以使用 // 目前环信SDK的EMChatEventHandler可能不支持这些回调,所以暂时注释掉 /* /// 通知消息已读 void _notifyMessageRead(List messages, String from, String to) { try { // 找到对应的 ChatController 并通知消息已读 final controller = _activeChatControllers[from]; if (controller != null) { // TODO: 在 ChatController 中添加更新消息已读状态的方法 if (Get.isLogEnable) { Get.log('通知消息已读: $from'); } } } catch (e) { if (Get.isLogEnable) { Get.log('通知消息已读失败: $e'); } } } /// 通知消息已送达 void _notifyMessageDelivered(List messages, String to) { try { // 找到对应的 ChatController 并通知消息已送达 for (var message in messages) { final targetId = message.to; if (targetId != null) { final controller = _activeChatControllers[targetId]; if (controller != null) { // TODO: 在 ChatController 中添加更新消息送达状态的方法 if (Get.isLogEnable) { Get.log('通知消息已送达: $targetId'); } } } } } catch (e) { if (Get.isLogEnable) { Get.log('通知消息已送达失败: $e'); } } } /// 通知消息撤回 void _notifyMessageRecalled(List messages) { try { // 通知所有相关的 ChatController 更新消息列表 for (var message in messages) { final fromId = message.from; final toId = message.to; // 通知发送方的 ChatController if (fromId != null) { final controller = _activeChatControllers[fromId]; if (controller != null) { // TODO: 在 ChatController 中添加处理消息撤回的方法 if (Get.isLogEnable) { Get.log('通知消息撤回(发送方): $fromId'); } } } // 通知接收方的 ChatController if (toId != null) { final controller = _activeChatControllers[toId]; if (controller != null) { // TODO: 在 ChatController 中添加处理消息撤回的方法 if (Get.isLogEnable) { Get.log('通知消息撤回(接收方): $toId'); } } } } // 刷新会话列表 _refreshConversationList(); } catch (e) { if (Get.isLogEnable) { Get.log('通知消息撤回失败: $e'); } } } /// 通知消息状态变更 void _notifyMessageStatusChanged(EMMessage message, MessageStatus status, EMError? error) { try { final targetId = message.to; if (targetId != null) { final controller = _activeChatControllers[targetId]; if (controller != null) { // TODO: 在 ChatController 中添加更新消息状态的方法 if (Get.isLogEnable) { Get.log('通知消息状态变更: $targetId, status=$status'); } } } } catch (e) { if (Get.isLogEnable) { Get.log('通知消息状态变更失败: $e'); } } } */ /// 撤回消息 Future recallMessage(EMMessage message) async { try { final messageId = message.msgId; if (messageId.isEmpty) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 消息ID为空,无法撤回'); } return false; } await EMClient.getInstance.chatManager.recallMessage(messageId); if (Get.isLogEnable) { Get.log('✅ [IMManager] 消息撤回成功: $messageId'); } // 刷新会话列表 _refreshConversationList(); return true; } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 消息撤回失败: $e'); } return false; } } /// 删除消息 Future deleteMessage(String conversationId, String messageId, {bool deleteRemote = false}) async { try { final conversation = await EMClient.getInstance.chatManager.getConversation( conversationId, type: EMConversationType.Chat, createIfNeed: false, ); if (conversation != null) { await conversation.deleteMessage(messageId); if (Get.isLogEnable) { Get.log('✅ [IMManager] 消息删除成功: $messageId'); } // 刷新会话列表 _refreshConversationList(); return true; } return false; } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 消息删除失败: $e'); } return false; } } /// 标记消息为已读 Future markMessageAsRead(String conversationId, String messageId) async { try { final conversation = await EMClient.getInstance.chatManager.getConversation( conversationId, type: EMConversationType.Chat, createIfNeed: false, ); if (conversation != null) { await conversation.markMessageAsRead(messageId); if (Get.isLogEnable) { Get.log('✅ [IMManager] 消息标记为已读: $messageId'); } // 刷新会话列表 _refreshConversationList(); return true; } return false; } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 标记消息为已读失败: $e'); } return false; } } /// 标记会话所有消息为已读 Future markAllMessagesAsRead(String conversationId) async { try { final conversation = await EMClient.getInstance.chatManager.getConversation( conversationId, type: EMConversationType.Chat, createIfNeed: false, ); if (conversation != null) { await conversation.markAllMessagesAsRead(); if (Get.isLogEnable) { Get.log('✅ [IMManager] 会话所有消息标记为已读: $conversationId'); } // 刷新会话列表 _refreshConversationList(); return true; } return false; } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 标记会话所有消息为已读失败: $e'); } return false; } } /// 重发消息 Future resendMessage(EMMessage failedMessage) async { try { final targetId = failedMessage.to ?? failedMessage.conversationId; if (targetId == null || targetId.isEmpty) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 重发消息失败:目标ID为空'); } return null; } EMMessage? newMessage; // 根据消息类型重新创建消息 switch (failedMessage.body.type) { case MessageType.TXT: final textBody = failedMessage.body as EMTextMessageBody; newMessage = EMMessage.createTxtSendMessage( targetId: targetId, content: textBody.content, ); break; case MessageType.IMAGE: final imageBody = failedMessage.body as EMImageMessageBody; final localPath = imageBody.localPath; if (localPath.isEmpty) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 重发图片消息失败:本地路径为空'); } return null; } newMessage = EMMessage.createImageSendMessage( targetId: targetId, filePath: localPath, sendOriginalImage: false, ); break; case MessageType.VOICE: final voiceBody = failedMessage.body as EMVoiceMessageBody; final localPath = voiceBody.localPath; if (localPath.isEmpty) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 重发语音消息失败:本地路径为空'); } return null; } newMessage = EMMessage.createVoiceSendMessage( targetId: targetId, filePath: localPath, duration: voiceBody.duration, ); break; case MessageType.VIDEO: final videoBody = failedMessage.body as EMVideoMessageBody; final localPath = videoBody.localPath; if (localPath.isEmpty) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 重发视频消息失败:本地路径为空'); } return null; } newMessage = EMMessage.createVideoSendMessage( targetId: targetId, filePath: localPath, duration: videoBody.duration ?? 0, thumbnailLocalPath: videoBody.thumbnailLocalPath, ); break; default: if (Get.isLogEnable) { Get.log('❌ [IMManager] 不支持重发该类型的消息: ${failedMessage.body.type}'); } return null; } // 重新发送消息 final result = await EMClient.getInstance.chatManager.sendMessage(newMessage); if (Get.isLogEnable) { Get.log('✅ [IMManager] 消息重发成功: ${newMessage.msgId}'); } return result; } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 重发消息失败: $e'); } return null; } } /// 清理资源 void dispose() { try { if (_listenersRegistered) { EMClient.getInstance.removeConnectionEventHandler(_connectionHandlerKey); EMClient.getInstance.chatManager.removeEventHandler(_chatHandlerKey); _listenersRegistered = false; if (Get.isLogEnable) { Get.log('✅ [IMManager] 资源清理完成'); } } } catch (e) { if (Get.isLogEnable) { Get.log('❌ [IMManager] 清理资源失败: $e'); } } } } // 导出单例实例 final IMManager imManager = IMManager();