import 'package:im_flutter_sdk/im_flutter_sdk.dart'; /// 环信在线状态管理器 class ChatPresenceManager { // 单例模式 static final ChatPresenceManager _instance = ChatPresenceManager._internal(); factory ChatPresenceManager() => _instance; ChatPresenceManager._internal(); // 用户ID到在线状态的映射 final Map _onlineStatusMap = {}; // 用户ID到EMPresence的映射 final Map _presenceMap = {}; // 监听器ID集合(避免重复添加监听器) final Set _listenerIds = {}; // 在线状态变化回调 final Map _statusCallbacks = {}; // 详细状态变化回调 final Map _presenceCallbacks = {}; /// 订阅用户在线状态 /// [userId] 目标用户ID /// [onStatusChanged] 状态变化回调(可选) /// [onPresenceChanged] 详细状态变化回调(可选) Future subscribeUserPresence({ required String userId, Function(bool)? onStatusChanged, Function(EMPresence)? onPresenceChanged, }) async { try { // 存储回调 if (onStatusChanged != null) { _statusCallbacks[userId] = onStatusChanged; } if (onPresenceChanged != null) { _presenceCallbacks[userId] = onPresenceChanged; } // 订阅用户状态(7天有效期) await EMClient.getInstance.presenceManager.subscribe( members: [userId], expiry: 604800, ); // 立即获取一次当前状态(会触发回调,更新UI) await _fetchUserPresence(userId); // 设置监听器(如果尚未设置) _setupPresenceListener(userId); print('✅ [ChatPresenceManager] 订阅成功: userId=$userId'); } on EMError catch (e) { print('订阅用户[$userId]在线状态失败: ${e.code}, ${e.description}'); rethrow; } } /// 批量订阅多个用户的在线状态 Future subscribeUsersPresence({ required List userIds, Function(String, bool)? onStatusChanged, Function(String, EMPresence)? onPresenceChanged, }) async { if (userIds.isEmpty) return; try { // 批量订阅(环信最多支持100个) await EMClient.getInstance.presenceManager.subscribe( members: userIds, expiry: 604800, ); // 为每个用户设置回调 for (final userId in userIds) { if (onStatusChanged != null) { _statusCallbacks[userId] = (isOnline) => onStatusChanged(userId, isOnline); } if (onPresenceChanged != null) { _presenceCallbacks[userId] = (presence) => onPresenceChanged(userId, presence); } // 立即获取一次当前状态 await _fetchUserPresence(userId); } // 设置监听器 _setupBatchPresenceListener(); } on EMError catch (e) { print('批量订阅用户在线状态失败: ${e.code}, ${e.description}'); rethrow; } } /// 获取用户的在线状态 bool isUserOnline(String userId) { return _onlineStatusMap[userId] ?? false; } /// 获取用户的详细在线状态信息 EMPresence? getUserPresence(String userId) { return _presenceMap[userId]; } /// 获取在线状态文本描述 String getStatusDescription(String userId) { final presence = _presenceMap[userId]; if (presence == null) return '未知'; final statusDesc = presence.statusDescription?.toLowerCase() ?? ''; // 根据标准状态返回 if (statusDesc.contains('online')) return '在线'; if (statusDesc.contains('away')) return '离开'; if (statusDesc.contains('busy')) return '忙碌'; if (statusDesc.contains('dnd')) return '勿扰'; if (statusDesc.contains('offline')) return '离线'; return '未知'; } /// 获取在线状态颜色 int getStatusColor(String userId) { final isOnline = _onlineStatusMap[userId] ?? false; final presence = _presenceMap[userId]; if (!isOnline) return 0xFF999999; // 灰色 final statusDesc = presence?.statusDescription?.toLowerCase() ?? ''; if (statusDesc.contains('busy')) return 0xFFFF3B30; // 红色 if (statusDesc.contains('away')) return 0xFFFF9500; // 橙色 if (statusDesc.contains('dnd')) return 0xFFAF52DE; // 紫色 if (statusDesc.contains('online')) return 0xFF34C759; // 绿色 return 0xFF34C759; // 默认绿色 } /// 手动刷新用户在线状态 Future refreshUserPresence(String userId) async { try { await _fetchUserPresence(userId); } on EMError catch (e) { print('刷新用户[$userId]在线状态失败: ${e.code}, ${e.description}'); rethrow; } } /// 取消订阅用户在线状态 Future unsubscribeUserPresence(String userId) async { try { // 取消订阅 await EMClient.getInstance.presenceManager.unsubscribe(members: [userId]); // 清理回调 _statusCallbacks.remove(userId); _presenceCallbacks.remove(userId); _onlineStatusMap.remove(userId); _presenceMap.remove(userId); } on EMError catch (e) { print('取消订阅用户[$userId]在线状态失败: ${e.code}, ${e.description}'); rethrow; } } /// 批量取消订阅 Future unsubscribeUsersPresence(List userIds) async { if (userIds.isEmpty) return; try { await EMClient.getInstance.presenceManager.unsubscribe(members: userIds); for (final userId in userIds) { _statusCallbacks.remove(userId); _presenceCallbacks.remove(userId); _onlineStatusMap.remove(userId); _presenceMap.remove(userId); } } on EMError catch (e) { print('批量取消订阅在线状态失败: ${e.code}, ${e.description}'); rethrow; } } /// 清理所有订阅和监听器 Future dispose() async { // 清理监听器 for (final listenerId in _listenerIds) { try { EMClient.getInstance.presenceManager.removeEventHandler(listenerId); } catch (e) { // 忽略清理错误 } } _listenerIds.clear(); // 清理回调 _statusCallbacks.clear(); _presenceCallbacks.clear(); // 清理数据 _onlineStatusMap.clear(); _presenceMap.clear(); } /// 私有方法:获取用户在线状态 Future _fetchUserPresence(String userId) async { try { List presences = await EMClient.getInstance.presenceManager .fetchPresenceStatus(members: [userId]); if (presences.isNotEmpty) { final presence = presences.first; print('📥 [ChatPresenceManager] 获取到Presence状态: userId=$userId, statusDescription=${presence.statusDescription}'); _presenceMap[userId] = presence; _updateOnlineStatus(userId, presence); } else { print('⚠️ [ChatPresenceManager] 未获取到Presence状态: userId=$userId'); } } on EMError catch (e) { print('获取用户[$userId]在线状态失败: ${e.code}, ${e.description}'); rethrow; } } /// 私有方法:更新在线状态 void _updateOnlineStatus(String userId, EMPresence presence) { final statusDesc = presence.statusDescription?.toLowerCase() ?? ''; final oldStatus = _onlineStatusMap[userId] ?? false; bool newStatus; // 判断在线状态逻辑 if (statusDesc.contains('online') || statusDesc.contains('available')) { newStatus = true; } else if (statusDesc.contains('offline')) { newStatus = false; } else { // away、busy、dnd 等状态,默认算"在线"(可根据业务需求调整) newStatus = true; } // 检查是否是首次设置状态 final isFirstTime = !_onlineStatusMap.containsKey(userId); // 更新状态 _onlineStatusMap[userId] = newStatus; // 打印调试信息 print('🔄 [ChatPresenceManager] 更新在线状态: userId=$userId, statusDescription=$statusDesc, oldStatus=$oldStatus, newStatus=$newStatus, isFirstTime=$isFirstTime'); // 触发回调(如果状态发生变化,或者首次设置) if (isFirstTime || oldStatus != newStatus) { print('✅ [ChatPresenceManager] 触发状态回调: userId=$userId, isOnline=$newStatus'); _statusCallbacks[userId]?.call(newStatus); } // 始终触发详细回调 _presenceCallbacks[userId]?.call(presence); } /// 私有方法:设置在线状态监听器 void _setupPresenceListener(String userId) { final listenerId = 'presence_$userId'; if (_listenerIds.contains(listenerId)) return; EMClient.getInstance.presenceManager.addEventHandler( listenerId, EMPresenceEventHandler( onPresenceStatusChanged: (list) { print('📡 [ChatPresenceManager] 收到Presence状态变化通知: userId=$userId, 变化数量=${list.length}'); for (var presence in list) { if (presence.publisher == userId) { print('✅ [ChatPresenceManager] 匹配到目标用户: userId=$userId'); _presenceMap[userId] = presence; _updateOnlineStatus(userId, presence); break; } } }, ), ); _listenerIds.add(listenerId); } /// 私有方法:设置批量监听器 void _setupBatchPresenceListener() { const listenerId = 'presence_batch_listener'; if (_listenerIds.contains(listenerId)) return; EMClient.getInstance.presenceManager.addEventHandler( listenerId, EMPresenceEventHandler( onPresenceStatusChanged: (list) { for (var presence in list) { final userId = presence.publisher; if (userId != null && _statusCallbacks.containsKey(userId)) { _presenceMap[userId] = presence; _updateOnlineStatus(userId, presence); } } }, ), ); _listenerIds.add(listenerId); } /// 私有方法:刷新所有已订阅用户的状态 Future _refreshAllSubscribedUsers() async { final userIds = _statusCallbacks.keys.toList(); if (userIds.isEmpty) return; try { List presences = await EMClient.getInstance.presenceManager .fetchPresenceStatus(members: userIds); for (var presence in presences) { final publisherId = presence.publisher; if (publisherId != null && publisherId.isNotEmpty) { _presenceMap[publisherId] = presence; _updateOnlineStatus(publisherId, presence); } } } on EMError catch (e) { print('刷新所有订阅用户状态失败: ${e.code}, ${e.description}'); } } }