|
|
|
@ -2,6 +2,7 @@ import 'package:get/get.dart'; |
|
|
|
import 'package:im_flutter_sdk/im_flutter_sdk.dart'; |
|
|
|
import '../../im/im_manager.dart'; |
|
|
|
import '../../model/mine/user_base_data.dart'; |
|
|
|
import 'chat_controller.dart'; |
|
|
|
|
|
|
|
// 扩展类用于存储用户信息(包括业务系统的信息) |
|
|
|
class ExtendedUserInfo { |
|
|
|
@ -157,26 +158,42 @@ class ConversationController extends GetxController { |
|
|
|
// 如果缓存中已有该用户信息,跳过 |
|
|
|
if (_userInfoCache.containsKey(targetUserId)) continue; |
|
|
|
|
|
|
|
// 获取会话的最新消息(最多获取最近20条) |
|
|
|
// 获取会话的最新消息(增加数量以提高找到用户信息的概率) |
|
|
|
final messages = await conversation.loadMessages( |
|
|
|
loadCount: 20, |
|
|
|
loadCount: 50, // 从20增加到50,提高找到用户信息的概率 |
|
|
|
); |
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('🔍 [ConversationController] 开始提取用户信息: userId=$targetUserId, 消息数量=${messages.length}'); |
|
|
|
} |
|
|
|
|
|
|
|
// 从消息中提取用户信息 |
|
|
|
// 接收消息:提取发送者信息(sender_ 前缀) |
|
|
|
// 发送消息:提取接收者信息(receiver_ 前缀) |
|
|
|
// 遍历所有消息,找到最新的包含用户信息的消息 |
|
|
|
ExtendedUserInfo? foundUserInfo; |
|
|
|
for (var message in messages) { |
|
|
|
Map<String, dynamic>? attributes; |
|
|
|
try { |
|
|
|
attributes = message.attributes; |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log(' ⚠️ 无法访问消息 attributes: msgId=${message.msgId}, error=$e'); |
|
|
|
} |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (attributes == null || attributes.isEmpty) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log(' ⚠️ 消息 attributes 为空: msgId=${message.msgId}, direction=${message.direction}'); |
|
|
|
} |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log(' 📨 检查消息: msgId=${message.msgId}, direction=${message.direction}, from=${message.from}, to=${message.to}, attributes keys=${attributes.keys.toList()}'); |
|
|
|
} |
|
|
|
|
|
|
|
if (message.direction == MessageDirection.RECEIVE) { |
|
|
|
// 接收到的消息:从扩展字段中提取发送者信息(sender_ 前缀) |
|
|
|
final fromUserId = message.from; |
|
|
|
@ -186,17 +203,16 @@ class ConversationController extends GetxController { |
|
|
|
final avatarUrl = attributes['sender_avatarUrl'] as String? ?? attributes['avatarUrl'] as String?; |
|
|
|
|
|
|
|
if (nickName != null || avatarUrl != null) { |
|
|
|
final extendedInfo = ExtendedUserInfo( |
|
|
|
// 如果找到用户信息,保存(但继续遍历以找到最新的) |
|
|
|
foundUserInfo = ExtendedUserInfo( |
|
|
|
userId: targetUserId, |
|
|
|
nickName: nickName, |
|
|
|
avatarUrl: avatarUrl, |
|
|
|
); |
|
|
|
_userInfoCache[targetUserId] = extendedInfo; |
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ConversationController] 从接收消息恢复对方用户信息: userId=$targetUserId, nickName=$nickName'); |
|
|
|
Get.log('✅ [ConversationController] 从接收消息找到用户信息: userId=$targetUserId, nickName=$nickName, msgId=${message.msgId}'); |
|
|
|
} |
|
|
|
// 找到一个就足够了,跳出循环 |
|
|
|
// 继续遍历,找到最新的消息(因为消息是按时间倒序的,第一个就是最新的) |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -209,22 +225,46 @@ class ConversationController extends GetxController { |
|
|
|
final avatarUrl = attributes['receiver_avatarUrl'] as String?; |
|
|
|
|
|
|
|
if (nickName != null || avatarUrl != null) { |
|
|
|
final extendedInfo = ExtendedUserInfo( |
|
|
|
// 如果找到用户信息,保存(但继续遍历以找到最新的) |
|
|
|
foundUserInfo = ExtendedUserInfo( |
|
|
|
userId: targetUserId, |
|
|
|
nickName: nickName, |
|
|
|
avatarUrl: avatarUrl, |
|
|
|
); |
|
|
|
_userInfoCache[targetUserId] = extendedInfo; |
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ConversationController] 从发送消息恢复对方用户信息: userId=$targetUserId, nickName=$nickName'); |
|
|
|
Get.log('✅ [ConversationController] 从发送消息找到用户信息: userId=$targetUserId, nickName=$nickName, msgId=${message.msgId}'); |
|
|
|
} |
|
|
|
// 找到一个就足够了,跳出循环 |
|
|
|
// 继续遍历,找到最新的消息(因为消息是按时间倒序的,第一个就是最新的) |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 如果找到了用户信息,保存到缓存 |
|
|
|
if (foundUserInfo != null) { |
|
|
|
_userInfoCache[targetUserId] = foundUserInfo; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果从消息中提取不到用户信息,尝试从环信获取(作为备选) |
|
|
|
if (!_userInfoCache.containsKey(targetUserId)) { |
|
|
|
try { |
|
|
|
var data = await IMManager.instance.getContacts(targetUserId); |
|
|
|
var emUserInfo = data[targetUserId]; |
|
|
|
|
|
|
|
if (emUserInfo != null && (emUserInfo.nickName?.isNotEmpty ?? false)) { |
|
|
|
final extendedInfo = ExtendedUserInfo.fromEMUserInfo(emUserInfo); |
|
|
|
_userInfoCache[targetUserId] = extendedInfo; |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ConversationController] 从环信获取到用户信息: userId=$targetUserId, nickName=${extendedInfo.nickName}'); |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ConversationController] 从环信获取用户信息失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ConversationController] 从会话提取用户信息失败: ${conversation.id}, 错误: $e'); |
|
|
|
@ -256,21 +296,30 @@ class ConversationController extends GetxController { |
|
|
|
|
|
|
|
/// 获取会话的最新消息 |
|
|
|
String getLastMessageContent(EMMessage? message) { |
|
|
|
if(message?.body.type == MessageType.TXT){ |
|
|
|
final body = message?.body as EMTextMessageBody; |
|
|
|
if (message == null) { |
|
|
|
return '暂无消息'; |
|
|
|
} |
|
|
|
|
|
|
|
// 检查消息是否发送失败(发送的消息且状态为FAIL) |
|
|
|
if (message.direction == MessageDirection.SEND && message.status == MessageStatus.FAIL) { |
|
|
|
return '[发送失败]'; |
|
|
|
} |
|
|
|
|
|
|
|
if(message.body.type == MessageType.TXT){ |
|
|
|
final body = message.body as EMTextMessageBody; |
|
|
|
return body.content; |
|
|
|
}else if(message?.body.type == MessageType.IMAGE){ |
|
|
|
}else if(message.body.type == MessageType.IMAGE){ |
|
|
|
return '[图片]'; |
|
|
|
}else if(message?.body.type == MessageType.VOICE){ |
|
|
|
}else if(message.body.type == MessageType.VOICE){ |
|
|
|
return '[语音]'; |
|
|
|
}else if(message?.body.type == MessageType.VIDEO){ |
|
|
|
}else if(message.body.type == MessageType.VIDEO){ |
|
|
|
return '[视频]'; |
|
|
|
}else if(message?.body.type == MessageType.FILE){ |
|
|
|
}else if(message.body.type == MessageType.FILE){ |
|
|
|
return '[文件]'; |
|
|
|
}else if(message?.body.type == MessageType.LOCATION){ |
|
|
|
}else if(message.body.type == MessageType.LOCATION){ |
|
|
|
return '[位置]'; |
|
|
|
}else if(message?.body.type == MessageType.CUSTOM){ |
|
|
|
final body = message?.body as EMCustomMessageBody; |
|
|
|
}else if(message.body.type == MessageType.CUSTOM){ |
|
|
|
final body = message.body as EMCustomMessageBody; |
|
|
|
// 检查是否是分享房间类型 |
|
|
|
if(body.event == 'live_room_invite'){ |
|
|
|
return '[分享房间]'; |
|
|
|
@ -339,9 +388,9 @@ class ConversationController extends GetxController { |
|
|
|
createIfNeed: false, |
|
|
|
); |
|
|
|
if (conversation != null) { |
|
|
|
// 获取最近的消息(最多20条),查找包含用户信息的消息 |
|
|
|
// 获取最近的消息(增加数量以提高找到用户信息的概率) |
|
|
|
final messages = await conversation.loadMessages( |
|
|
|
loadCount: 20, |
|
|
|
loadCount: 50, // 从20增加到50,提高找到用户信息的概率 |
|
|
|
); |
|
|
|
|
|
|
|
// 从消息中查找用户信息(只查找接收到的消息,因为那是对方的用户信息) |
|
|
|
@ -484,7 +533,45 @@ class ConversationController extends GetxController { |
|
|
|
} |
|
|
|
|
|
|
|
Future<EMMessage?> lastMessage(EMConversation conversation) async{ |
|
|
|
return await conversation.latestMessage(); |
|
|
|
try { |
|
|
|
// 优先尝试从ChatController获取最后一条消息(如果ChatController还在内存中) |
|
|
|
// 这样可以获取到失败状态的消息(SDK可能不会保存失败消息) |
|
|
|
try { |
|
|
|
final tag = 'chat_${conversation.id}'; |
|
|
|
if (Get.isRegistered<ChatController>(tag: tag)) { |
|
|
|
final chatController = Get.find<ChatController>(tag: tag); |
|
|
|
if (chatController.messages.isNotEmpty) { |
|
|
|
// 获取最后一条消息(列表末尾,按时间戳排序后最后一条是最新的) |
|
|
|
// 注意:messages列表是按时间戳从旧到新排序的,所以last是最新的 |
|
|
|
final lastMsg = chatController.messages.last; |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ConversationController] 从ChatController获取最后一条消息: msgId=${lastMsg.msgId}, status=${lastMsg.status}, direction=${lastMsg.direction}, content=${lastMsg.body.type == MessageType.TXT ? (lastMsg.body as EMTextMessageBody).content : lastMsg.body.type}'); |
|
|
|
} |
|
|
|
return lastMsg; |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ConversationController] 从ChatController获取最后一条消息失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 如果ChatController不存在或没有消息,从SDK获取 |
|
|
|
final sdkMessage = await conversation.latestMessage(); |
|
|
|
if (Get.isLogEnable) { |
|
|
|
if (sdkMessage != null) { |
|
|
|
Get.log('✅ [ConversationController] 从SDK获取最后一条消息: msgId=${sdkMessage.msgId}, status=${sdkMessage.status}, direction=${sdkMessage.direction}'); |
|
|
|
} else { |
|
|
|
Get.log('⚠️ [ConversationController] SDK返回的最后一条消息为null'); |
|
|
|
} |
|
|
|
} |
|
|
|
return sdkMessage; |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ConversationController] 获取最后一条消息失败: $e'); |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 删除会话 |
|
|
|
|