|
|
|
@ -35,6 +35,14 @@ class ExtendedUserInfo { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 筛选类型枚举 |
|
|
|
enum FilterType { |
|
|
|
none, // 无筛选 |
|
|
|
lastChatTime, // 最后聊天时间 |
|
|
|
unread, // 未读消息 |
|
|
|
online, // 当前在线 |
|
|
|
} |
|
|
|
|
|
|
|
class ConversationController extends GetxController { |
|
|
|
// 会话列表数据 |
|
|
|
final conversations = <EMConversation>[].obs; |
|
|
|
@ -46,6 +54,9 @@ class ConversationController extends GetxController { |
|
|
|
// 用户信息缓存(userId -> ExtendedUserInfo) |
|
|
|
final Map<String, ExtendedUserInfo> _userInfoCache = {}; |
|
|
|
|
|
|
|
// 筛选类型 |
|
|
|
final filterType = FilterType.none.obs; |
|
|
|
|
|
|
|
/// 缓存用户信息(公开方法,供 ChatController 调用) |
|
|
|
void cacheUserInfo(String userId, ExtendedUserInfo userInfo) { |
|
|
|
_userInfoCache[userId] = userInfo; |
|
|
|
@ -591,4 +602,132 @@ class ConversationController extends GetxController { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 设置筛选类型 |
|
|
|
void setFilterType(FilterType type) { |
|
|
|
filterType.value = type; |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ConversationController] 设置筛选类型: $type'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 获取筛选后的会话列表 |
|
|
|
Future<List<EMConversation>> getFilteredConversations() async { |
|
|
|
List<EMConversation> filteredList = List.from(conversations); |
|
|
|
|
|
|
|
switch (filterType.value) { |
|
|
|
case FilterType.none: |
|
|
|
// 无筛选,按默认顺序返回 |
|
|
|
break; |
|
|
|
|
|
|
|
case FilterType.lastChatTime: |
|
|
|
// 按最后聊天时间排序(最新的在前) |
|
|
|
// 先获取所有消息的时间戳 |
|
|
|
final List<MapEntry<EMConversation, int>> conversationTimes = await Future.wait( |
|
|
|
filteredList.map((conv) async { |
|
|
|
final message = await lastMessage(conv); |
|
|
|
final time = message?.serverTime ?? 0; |
|
|
|
return MapEntry(conv, time); |
|
|
|
}), |
|
|
|
); |
|
|
|
// 按时间戳排序(降序,最新的在前) |
|
|
|
conversationTimes.sort((a, b) => b.value.compareTo(a.value)); |
|
|
|
filteredList = conversationTimes.map((entry) => entry.key).toList(); |
|
|
|
break; |
|
|
|
|
|
|
|
case FilterType.unread: |
|
|
|
// 只显示有未读消息的会话 |
|
|
|
final List<MapEntry<EMConversation, int>> conversationUnreads = await Future.wait( |
|
|
|
filteredList.map((conv) async { |
|
|
|
final unreadCount = await getUnreadCount(conv); |
|
|
|
return MapEntry(conv, unreadCount); |
|
|
|
}), |
|
|
|
); |
|
|
|
// 过滤出有未读消息的会话 |
|
|
|
final unreadConversations = conversationUnreads |
|
|
|
.where((entry) => entry.value > 0) |
|
|
|
.toList(); |
|
|
|
// 按未读数量排序(未读数多的在前) |
|
|
|
unreadConversations.sort((a, b) => b.value.compareTo(a.value)); |
|
|
|
filteredList = unreadConversations.map((entry) => entry.key).toList(); |
|
|
|
break; |
|
|
|
|
|
|
|
case FilterType.online: |
|
|
|
// 只显示在线用户的会话 |
|
|
|
final List<EMConversation?> onlineConversations = await Future.wait( |
|
|
|
filteredList.map((conv) async { |
|
|
|
final isOnline = await _checkUserOnline(conv); |
|
|
|
return isOnline ? conv : null; |
|
|
|
}), |
|
|
|
); |
|
|
|
filteredList = onlineConversations |
|
|
|
.whereType<EMConversation>() |
|
|
|
.toList(); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
return filteredList; |
|
|
|
} |
|
|
|
|
|
|
|
/// 检查用户是否在线 |
|
|
|
Future<bool> _checkUserOnline(EMConversation conversation) async { |
|
|
|
try { |
|
|
|
// 获取会话的最新消息 |
|
|
|
final message = await lastMessage(conversation); |
|
|
|
if (message == null) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// 从消息扩展字段中获取在线状态 |
|
|
|
Map<String, dynamic>? attributes; |
|
|
|
try { |
|
|
|
attributes = message.attributes; |
|
|
|
} catch (e) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (attributes == null || attributes.isEmpty) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// 检查在线状态字段 |
|
|
|
// 接收消息:检查 sender_isOnline |
|
|
|
// 发送消息:检查 receiver_isOnline |
|
|
|
String? isOnlineStr; |
|
|
|
String? lastActiveTimeStr; |
|
|
|
|
|
|
|
if (message.direction == MessageDirection.RECEIVE) { |
|
|
|
isOnlineStr = attributes['sender_isOnline'] as String?; |
|
|
|
lastActiveTimeStr = attributes['sender_lastActiveTime'] as String?; |
|
|
|
} else { |
|
|
|
isOnlineStr = attributes['receiver_isOnline'] as String?; |
|
|
|
lastActiveTimeStr = attributes['receiver_lastActiveTime'] as String?; |
|
|
|
} |
|
|
|
|
|
|
|
if (isOnlineStr == 'true') { |
|
|
|
// 进一步检查最后活跃时间(5分钟内认为在线) |
|
|
|
if (lastActiveTimeStr != null) { |
|
|
|
try { |
|
|
|
final lastActiveTime = int.parse(lastActiveTimeStr); |
|
|
|
final now = DateTime.now().millisecondsSinceEpoch; |
|
|
|
final diff = now - lastActiveTime; |
|
|
|
// 5分钟内认为在线(5 * 60 * 1000 毫秒) |
|
|
|
return diff < 5 * 60 * 1000; |
|
|
|
} catch (e) { |
|
|
|
// 解析失败,使用 isOnline 字段 |
|
|
|
return true; |
|
|
|
} |
|
|
|
} else { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ConversationController] 检查用户在线状态失败: $e'); |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |