|
|
@ -17,6 +17,11 @@ class IMManager { |
|
|
static IMManager get instance => _instance; |
|
|
static IMManager get instance => _instance; |
|
|
|
|
|
|
|
|
bool _isInitialized = false; |
|
|
bool _isInitialized = false; |
|
|
|
|
|
bool _listenersRegistered = false; |
|
|
|
|
|
|
|
|
|
|
|
// 监听器标识符 |
|
|
|
|
|
static const String _connectionHandlerKey = 'im_manager_connection_handler'; |
|
|
|
|
|
static const String _chatHandlerKey = 'im_manager_chat_handler'; |
|
|
|
|
|
|
|
|
// 存储活跃的 ChatController 实例,key 为 userId |
|
|
// 存储活跃的 ChatController 实例,key 为 userId |
|
|
final Map<String, ChatController> _activeChatControllers = {}; |
|
|
final Map<String, ChatController> _activeChatControllers = {}; |
|
|
@ -55,75 +60,77 @@ class IMManager { |
|
|
// 注册监听器 |
|
|
// 注册监听器 |
|
|
void _registerListeners() { |
|
|
void _registerListeners() { |
|
|
try { |
|
|
try { |
|
|
// 消息监听器 |
|
|
|
|
|
|
|
|
// 防止重复注册 |
|
|
|
|
|
if (_listenersRegistered) { |
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('监听器已注册,跳过重复注册'); |
|
|
|
|
|
} |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 连接监听器 |
|
|
// 连接监听器 |
|
|
EMClient.getInstance.addConnectionEventHandler( |
|
|
EMClient.getInstance.addConnectionEventHandler( |
|
|
'', |
|
|
|
|
|
|
|
|
_connectionHandlerKey, |
|
|
EMConnectionEventHandler( |
|
|
EMConnectionEventHandler( |
|
|
onConnected: () { |
|
|
onConnected: () { |
|
|
print('Connected to IM server'); |
|
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('✅ [IMManager] 已连接到IM服务器'); |
|
|
|
|
|
} |
|
|
}, |
|
|
}, |
|
|
onDisconnected: () { |
|
|
onDisconnected: () { |
|
|
print('Disconnected from IM server:'); |
|
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('❌ [IMManager] 与IM服务器断开连接'); |
|
|
|
|
|
} |
|
|
|
|
|
// TODO: 可以在这里添加自动重连逻辑 |
|
|
}, |
|
|
}, |
|
|
onTokenDidExpire: () { |
|
|
onTokenDidExpire: () { |
|
|
print('IM token about to expire'); |
|
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('⚠️ [IMManager] IM token即将过期'); |
|
|
|
|
|
} |
|
|
|
|
|
// TODO: 可以在这里添加自动刷新token的逻辑 |
|
|
}, |
|
|
}, |
|
|
onUserKickedByOtherDevice: () { |
|
|
onUserKickedByOtherDevice: () { |
|
|
print('User kicked out of IM server'); |
|
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('⚠️ [IMManager] 用户被其他设备踢出'); |
|
|
|
|
|
} |
|
|
|
|
|
// TODO: 可以在这里添加处理逻辑,如跳转到登录页 |
|
|
}, |
|
|
}, |
|
|
), |
|
|
), |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// 消息监听器 |
|
|
EMClient.getInstance.chatManager.addEventHandler( |
|
|
EMClient.getInstance.chatManager.addEventHandler( |
|
|
// EMChatEventHandler 对应的 key。 |
|
|
|
|
|
"", |
|
|
|
|
|
|
|
|
_chatHandlerKey, |
|
|
EMChatEventHandler( |
|
|
EMChatEventHandler( |
|
|
onMessagesReceived: (messages) { |
|
|
onMessagesReceived: (messages) { |
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('📨 [IMManager] 收到 ${messages.length} 条新消息'); |
|
|
|
|
|
} |
|
|
// 收到新消息时,更新会话列表 |
|
|
// 收到新消息时,更新会话列表 |
|
|
_refreshConversationList(); |
|
|
_refreshConversationList(); |
|
|
|
|
|
|
|
|
// 通知对应的 ChatController 更新消息列表 |
|
|
// 通知对应的 ChatController 更新消息列表 |
|
|
_notifyChatControllers(messages); |
|
|
_notifyChatControllers(messages); |
|
|
|
|
|
|
|
|
for (var msg in messages) { |
|
|
|
|
|
switch (msg.body.type) { |
|
|
|
|
|
case MessageType.TXT: |
|
|
|
|
|
{} |
|
|
|
|
|
break; |
|
|
|
|
|
case MessageType.IMAGE: |
|
|
|
|
|
{} |
|
|
|
|
|
break; |
|
|
|
|
|
case MessageType.VIDEO: |
|
|
|
|
|
{} |
|
|
|
|
|
break; |
|
|
|
|
|
case MessageType.LOCATION: |
|
|
|
|
|
{} |
|
|
|
|
|
break; |
|
|
|
|
|
case MessageType.VOICE: |
|
|
|
|
|
{} |
|
|
|
|
|
break; |
|
|
|
|
|
case MessageType.FILE: |
|
|
|
|
|
{} |
|
|
|
|
|
break; |
|
|
|
|
|
case MessageType.CUSTOM: |
|
|
|
|
|
{} |
|
|
|
|
|
break; |
|
|
|
|
|
case MessageType.COMBINE: |
|
|
|
|
|
{} |
|
|
|
|
|
break; |
|
|
|
|
|
case MessageType.CMD: |
|
|
|
|
|
{ |
|
|
|
|
|
// 当前回调中不会有 CMD 类型消息,CMD 类型消息通过 `EMChatEventHandler#onCmdMessagesReceived` 回调接收 |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
}, |
|
|
|
|
|
onCmdMessagesReceived: (cmdMessages) { |
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('📨 [IMManager] 收到 ${cmdMessages.length} 条CMD消息'); |
|
|
|
|
|
} |
|
|
|
|
|
// 处理CMD消息(如撤回消息等) |
|
|
|
|
|
for (var msg in cmdMessages) { |
|
|
|
|
|
_handleCmdMessage(msg); |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
), |
|
|
), |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
_listenersRegistered = true; |
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('✅ [IMManager] 监听器注册成功'); |
|
|
|
|
|
} |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
print('Failed to register listeners: $e'); |
|
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('❌ [IMManager] 注册监听器失败: $e'); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -187,7 +194,7 @@ class IMManager { |
|
|
int duration, |
|
|
int duration, |
|
|
) async { |
|
|
) async { |
|
|
try { |
|
|
try { |
|
|
// 创建图片消息 |
|
|
|
|
|
|
|
|
// 创建语音消息 |
|
|
final message = EMMessage.createVoiceSendMessage( |
|
|
final message = EMMessage.createVoiceSendMessage( |
|
|
targetId: toChatUsername, |
|
|
targetId: toChatUsername, |
|
|
filePath: filePath, |
|
|
filePath: filePath, |
|
|
@ -196,10 +203,14 @@ class IMManager { |
|
|
|
|
|
|
|
|
// 发送消息 |
|
|
// 发送消息 |
|
|
await EMClient.getInstance.chatManager.sendMessage(message); |
|
|
await EMClient.getInstance.chatManager.sendMessage(message); |
|
|
print('Image message sent successfully'); |
|
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('✅ [IMManager] 语音消息发送成功'); |
|
|
|
|
|
} |
|
|
return message; |
|
|
return message; |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
print('Failed to send image message: $e'); |
|
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('❌ [IMManager] 发送语音消息失败: $e'); |
|
|
|
|
|
} |
|
|
return null; |
|
|
return null; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -310,7 +321,7 @@ class IMManager { |
|
|
return EMClient.getInstance.chatManager.loadAllConversations(); |
|
|
return EMClient.getInstance.chatManager.loadAllConversations(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// 获取好有列表 |
|
|
|
|
|
|
|
|
/// 获取用户信息(单个用户) |
|
|
Future<Map<String, EMUserInfo>> getContacts(String userId) async { |
|
|
Future<Map<String, EMUserInfo>> getContacts(String userId) async { |
|
|
return await EMClient.getInstance.userInfoManager.fetchUserInfoById([ |
|
|
return await EMClient.getInstance.userInfoManager.fetchUserInfoById([ |
|
|
userId, |
|
|
userId, |
|
|
@ -323,14 +334,44 @@ class IMManager { |
|
|
int pageSize = 20, |
|
|
int pageSize = 20, |
|
|
String? startMsgId, |
|
|
String? startMsgId, |
|
|
}) async { |
|
|
}) async { |
|
|
EMConversationType convType = EMConversationType.Chat; |
|
|
|
|
|
EMCursorResult<EMMessage?> cursor = await EMClient.getInstance.chatManager |
|
|
|
|
|
.fetchHistoryMessagesByOption( |
|
|
|
|
|
conversationId, |
|
|
|
|
|
convType, |
|
|
|
|
|
pageSize: pageSize, |
|
|
|
|
|
|
|
|
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 []; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 如果有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 cursor.data; |
|
|
|
|
|
|
|
|
return messages.map((msg) => msg as EMMessage?).toList(); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('❌ [IMManager] 获取消息失败: $e'); |
|
|
|
|
|
} |
|
|
|
|
|
return []; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/// 获取用户信息 |
|
|
/// 获取用户信息 |
|
|
@ -436,12 +477,336 @@ class IMManager { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// 处理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<EMMessage> 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<EMMessage> 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<EMMessage> 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<bool> 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<bool> 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<bool> 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<bool> 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<EMMessage?> 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() { |
|
|
void dispose() { |
|
|
try { |
|
|
try { |
|
|
EMClient.getInstance.removeConnectionEventHandler(""); |
|
|
|
|
|
|
|
|
if (_listenersRegistered) { |
|
|
|
|
|
EMClient.getInstance.removeConnectionEventHandler(_connectionHandlerKey); |
|
|
|
|
|
EMClient.getInstance.chatManager.removeEventHandler(_chatHandlerKey); |
|
|
|
|
|
_listenersRegistered = false; |
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('✅ [IMManager] 资源清理完成'); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} catch (e) { |
|
|
} catch (e) { |
|
|
print('Failed to dispose resources: $e'); |
|
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
|
|
Get.log('❌ [IMManager] 清理资源失败: $e'); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|