import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:logger/logger.dart'; import 'package:loopin/IM/controller/chat_controller.dart'; import 'package:loopin/IM/controller/im_user_info_controller.dart'; import 'package:loopin/IM/controller/tab_bar_controller.dart'; import 'package:loopin/IM/global_badge.dart'; import 'package:loopin/IM/im_core.dart'; import 'package:loopin/IM/im_friend_listeners.dart'; import 'package:loopin/IM/im_message_listeners.dart'; import 'package:loopin/IM/im_result.dart'; import 'package:loopin/IM/push_service.dart'; import 'package:loopin/models/conversation_view_model.dart'; import 'package:loopin/utils/wxsdk.dart'; import 'package:tencent_cloud_chat_sdk/enum/friend_application_type_enum.dart'; import 'package:tencent_cloud_chat_sdk/enum/friend_response_type_enum.dart'; import 'package:tencent_cloud_chat_sdk/enum/friend_type_enum.dart'; import 'package:tencent_cloud_chat_sdk/enum/history_msg_get_type_enum.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation_filter.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation_operation_result.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation_result.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_follow_info.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_follow_operation_result.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_follow_type_check_result.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info_result.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_operation_result.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_change_info.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_param.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_result.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_info_result.dart'; import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart'; import 'package:tencent_cloud_chat_sdk/native_im/adapter/tim_conversation_manager.dart'; import 'package:tencent_cloud_chat_sdk/native_im/adapter/tim_friendship_manager.dart'; import 'package:tencent_cloud_chat_sdk/native_im/adapter/tim_message_manager.dart'; import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart'; final logger = Logger(); /// IM 服务封装类 class ImService { ImService._(); static final instance = ImService._(); /// 登录 Future login({ required String userID, required String userSig, }) async { final res = await TencentImSDKPlugin.v2TIMManager.login( userID: userID, userSig: userSig, ); final result = ImResult( success: res.code == 0, code: res.code, desc: res.desc, ); if (result.success) { logger.i("IM 登录成功:$userID"); // 初始化会话数据 final ctl = Get.find(); await ctl.getConversationList(); /// 初始化微信 SDK await Wxsdk.init(); // 注册用户信息(基本信息+自定义信息) if (!Get.isRegistered()) { final imInfo = Get.put(ImUserInfoController(), permanent: true); await imInfo.refreshUserInfo(); } else { await Get.find().refreshUserInfo(); } // 登录成功后注册高级消息监听器 final messageService = ImMessageListenerService(); Get.put(messageService, permanent: true); await messageService.init(); // 注册关系链监听器 final friendListener = ImFriendListeners(); Get.put(friendListener, permanent: true); friendListener.register(); /// 注册消息未读数监听器 Get.put(GlobalBadge(), permanent: true); // 初始化push服务 PushService().initPush( sdkAppId: 1600080789, appKey: 'vkFpe55aYqfV7Sk5uGaoxhEstJ3tcI9dquk7JwG1GloDSLD2HeMWeQweWWXgNlhC', ); } else { logger.i("IM 登录失败:${result.code} - ${result.desc}"); Get.snackbar( '登录失败', '${result.code} - ${result.desc}', backgroundColor: Colors.red.withAlpha(230), colorText: Colors.white, icon: const Icon(Icons.error_outline, color: Colors.white), ); } return result; } /// 登出 Future logout() async { final res = await TencentImSDKPlugin.v2TIMManager.logout(); if (res.code == 0) { /// 移出消息监听器 await Get.delete(force: true); /// 移出关系链监听器 Get.find().unregister(); await Get.delete(force: true); /// 清理tabbar Get.find().badgeMap.clear(); /// 清理会话列表数据 Get.find().initChatData(); /// 移出未读消息监听器 Get.find().onClose(); await Get.delete(force: true); /// 移除推送服务 await PushService.unInitPush(); /// 反初始化 await ImCore.unInit(); } return ImResult.wrapNoData(res); } /// 设置会话自定义属性 Future>> setConversationCustomData({ required String customData, required List conversationIDList, }) async { final res = await TIMConversationManager.instance.setConversationCustomData(customData: customData, conversationIDList: conversationIDList); return ImResult.wrap(res); } /// 获取符合过滤条件的未读消息总数 Future> getUnreadMessageCountByFilter({ required V2TimConversationFilter filter, }) async { final res = await TIMConversationManager.instance.getUnreadMessageCountByFilter( filter: filter, ); return ImResult.wrap(res); } /// 删除会话 Future> deleteConversation({ required String conversationID, }) async { final res = await TIMConversationManager.instance.deleteConversation(conversationID: conversationID); return ImResult.wrapNoData(res); } /// 创建会话分组 Future>> createConversationGroup({ required String groupName, required List conversationIDList, }) async { final res = await TIMConversationManager.instance.createConversationGroup( groupName: groupName, conversationIDList: conversationIDList, ); return ImResult.wrap(res); } /// 获取会话分组列表 Future>> getConversationGroupList() async { final res = await TIMConversationManager.instance.getConversationGroupList(); return ImResult.wrap(res); } /// 将会话添加到分组 Future>> addConversationsToGroup({ required String groupName, required List conversationIDList, }) async { final res = await TIMConversationManager.instance.addConversationsToGroup( groupName: groupName, conversationIDList: conversationIDList, ); return ImResult.wrap(res); } ///将会话移除分组 Future>> deleteConversationsFromGroup({ required String groupName, required List conversationIDList, }) async { final res = await TIMConversationManager.instance.deleteConversationsFromGroup( groupName: groupName, conversationIDList: conversationIDList, ); return ImResult.wrap(res); } /// 高级查询会话列表 Future> getConversationListByFilter({ required V2TimConversationFilter filter, required int nextSeq, int count = 20, }) async { final res = await TIMConversationManager.instance.getConversationListByFilter( filter: filter, nextSeq: nextSeq, count: count, ); return ImResult.wrap(res); } /// 查询会话记录 Future getConversationList(String nextSeq, int count) async { // final res = await TencentImSDKPlugin.v2TIMManager.getConversationManager().getConversationList(nextSeq: nextSeq, count: count); final res = await getConvData(nextSeq, count); if (res.success == false) { return ImResult( success: false, code: res.code, desc: res.desc, ); } final convList = res.data?.conversationList ?? []; logger.w('未过滤前到会话数据:$convList'); final userIDList = []; final groupIDList = []; // 提前收集所有需要批量查询的 userID 和 groupID for (var conv in convList) { if (conv.userID != null) { userIDList.add(conv.userID!); } else if (conv.groupID != null) { groupIDList.add(conv.groupID!); } } Map userFaceUrlMap = {}; Map groupFaceUrlMap = {}; Map isCustomAdmin = {}; if (userIDList.isNotEmpty) { final userRes = await TencentImSDKPlugin.v2TIMManager.getUsersInfo(userIDList: userIDList); if (userRes.code == 0) { for (var user in userRes.data!) { final userId = user.userID ?? ''; userFaceUrlMap[userId] = user.faceUrl; // 读取管理员标识 final customInfo = user.customInfo; if (customInfo != null) { isCustomAdmin[userId] = customInfo['admin'] ?? '0'; } } } } if (groupIDList.isNotEmpty) { final groupRes = await TencentImSDKPlugin.v2TIMManager.getGroupManager().getGroupsInfo(groupIDList: groupIDList); if (groupRes.code == 0) { for (var groupResult in groupRes.data!) { final info = groupResult.groupInfo; if (info != null) { groupFaceUrlMap[info.groupID] = info.faceUrl; } } } } final viewList = convList.map((conv) { String? faceUrl = conv.faceUrl; if (faceUrl == null || faceUrl.isEmpty) { if (conv.userID != null) { faceUrl = userFaceUrlMap[conv.userID!]; } else if (conv.groupID != null) { faceUrl = groupFaceUrlMap[conv.groupID!]; } } return ConversationViewModel( conversation: conv, faceUrl: faceUrl, isCustomAdmin: isCustomAdmin[conv.userID], ); }).toList(); // 筛选数据,过滤掉陌生人消息 viewList.removeWhere((conv) { final special = conv.conversation.conversationGroupList ?? []; return special.contains('noFriend'); }); ChatController chatcontroller = Get.find(); logger.e('新的分页内容:${res.data!.toLogString()},控制器中的:${chatcontroller.nextSeq.value}'); String newNextSeq = res.data?.nextSeq ?? '0'; bool isEnd = res.data?.isFinished ?? true; if (isEnd) { //没数据了,关闭拉取; chatcontroller.isFinished.value = isEnd; } else { // 没拉完,记录游标 chatcontroller.nextSeq.value = newNextSeq; } // 更新分页 chatcontroller.nextSeq.value = res.data!.nextSeq!; if (res.data!.isFinished == false) { if (viewList.length < 20) { // 递归补偿拉取 final nextRes = await getConversationList( res.data!.nextSeq!, count, ); if (nextRes.success && nextRes.data != null) { viewList.addAll(nextRes.data as List); } } } return ImResult( success: res.code == 0, code: res.code, desc: res.desc, data: viewList, ); } ///获取所有会话数据 Future> getConvData(String nextSeq, int count) async { final res = await TencentImSDKPlugin.v2TIMManager.getConversationManager().getConversationList(nextSeq: nextSeq, count: count); return ImResult.wrap(res); } ///获取指定会话 Future getConversation({ required String conversationID, }) async { final res = await TIMConversationManager.instance.getConversation(conversationID: conversationID); //c2c_conversationID,group_conversationID return ImResult( success: res.code == 0 && res.data != null, code: res.code, desc: res.desc, data: res.data, ); } /// 搜索本地消息 Future> searchLocalMessages({ required String page, required String conversationID, /// 关键词匹配机制or=0,and=1, int type = 1, /// ['你好','周末'] required List keywordList, /// 默认自定义消息 List messageTypeList = const [1, 2], }) async { final searchParam = V2TimMessageSearchParam( type: type, conversationID: conversationID, keywordList: keywordList, messageTypeList: messageTypeList, pageSize: 100, // pageIndex: page, searchCursor: page, ); final V2TimValueCallback res = await TIMMessageManager.instance.searchLocalMessages(searchParam: searchParam); return ImResult.wrap(res); } /// 获取消息 Future>> findMessages({ required List messageIDList, }) async { final res = await TIMMessageManager.instance.findMessages(messageIDList: messageIDList); return ImResult.wrap(res); } /// 修改消息 Future> modifyMessage({ required V2TimMessage message, }) async { final res = await TIMMessageManager.instance.modifyMessage(message: message); return ImResult.wrap(res); } /// 获取聊天记录 如果是群聊传 groupID,单聊传 userID,二选一 Future>> getHistoryMessageList({ HistoryMsgGetTypeEnum getType = HistoryMsgGetTypeEnum.V2TIM_GET_LOCAL_OLDER_MSG, String? userID, String? groupID, int? lastMsgSeq, int count = 10, V2TimMessage? lastMsg, List? messageTypeList, List? messageSeqList, int? timeBegin, int? timePeriod, }) async { if ((userID == null || userID.isEmpty) && (groupID == null || groupID.isEmpty)) { return ImResult( success: false, code: -1, desc: 'userID 或 groupID 必须至少传入一个', data: [], ); } final isC2C = userID != null && groupID == null; final manager = TencentImSDKPlugin.v2TIMManager.getMessageManager(); V2TimValueCallback> res; if (!isC2C && lastMsg == null && lastMsgSeq != null) { // 群聊 res = await manager.getHistoryMessageList( getType: getType, userID: userID, groupID: groupID, count: count, lastMsgSeq: lastMsgSeq, //群聊用,包含最后一条msg messageTypeList: messageTypeList, messageSeqList: messageSeqList, timeBegin: timeBegin, timePeriod: timePeriod, ); } else { // 单聊 res = await manager.getHistoryMessageList( getType: getType, userID: userID, groupID: groupID, count: count, lastMsg: lastMsg, // 单聊用,不包含最后一条msg messageTypeList: messageTypeList, messageSeqList: messageSeqList, timeBegin: timeBegin, timePeriod: timePeriod, ); } return ImResult>( success: res.code == 0, code: res.code, desc: res.desc, data: res.data ?? [], ); } /// /// 清理指定单聊会话的未读数 /// Future clearConversationUnreadCount({ required String conversationID, // 0表示全部清除 int cleanTimestamp = 0, int cleanSequence = 0, }) async { final res = await TIMConversationManager.instance.cleanConversationUnreadMessageCount( conversationID: conversationID, cleanTimestamp: cleanTimestamp, // 单聊生效 cleanSequence: cleanSequence, // 群聊生效 ); return ImResult.wrapNoData(res); } /// 获取自己的userId Future selfUserId() async { V2TimValueCallback self = await TencentImSDKPlugin.v2TIMManager.getLoginUser(); String? userId = self.data; return ImResult( success: self.code == 0, code: self.code, desc: self.desc, data: userId, ); } /// 查询当前登录用户的个人信息 Future selfInfo() async { // 获取当前登录的用户 ID final idRes = await selfUserId(); // 获取用户信息 V2TimValueCallback> res = await TencentImSDKPlugin.v2TIMManager.getUsersInfo(userIDList: [idRes.data]); return ImResult( success: res.code == 0, code: res.code, desc: res.desc, data: res.data?.isNotEmpty == true ? res.data!.first : null, ); } /// 查询其他人的信息 Future otherInfo(id) async { // 获取用户信息 V2TimValueCallback> res = await TencentImSDKPlugin.v2TIMManager.getUsersInfo(userIDList: [id]); return ImResult( success: res.code == 0, code: res.code, desc: res.desc, data: res.data?.isNotEmpty == true ? res.data!.first : null, ); } /// 设置个人资料 Future setSelfInfo({ required V2TimUserFullInfo userFullInfo, }) async { final res = await TencentImSDKPlugin.v2TIMManager.setSelfInfo( userFullInfo: userFullInfo, ); return ImResult.wrapNoData(res); } /// 检查是否是好友(双向或单向) Future isMyFriend(String userID, FriendTypeEnum checkType) async { final res = await TIMFriendshipManager.instance.checkFriend( userIDList: [userID], checkType: checkType, //V2TIM_FRIEND_TYPE_BOTH V2TIM_FRIEND_TYPE_SINGLE ); if (res.code == 0 && res.data != null && res.data!.isNotEmpty) { final resultType = res.data!.first.resultType; final isFriend = resultType == 3; //0=无, 1=单向, 2=我在对方列表,3=双向 return ImResult( success: true, desc: res.desc, code: res.code, data: isFriend, ); } else { return ImResult( success: false, code: res.code, desc: res.desc, data: false, ); } } /// 添加好友 Future> addFriend({ required String userID, String? remark, String? friendGroup, String? addWording, String? addSource, required FriendTypeEnum addType, }) async { final res = await TIMFriendshipManager.instance.addFriend( userID: userID, remark: remark, friendGroup: friendGroup, addWording: addWording, addSource: addSource, addType: addType, ); return ImResult.wrap(res); } ///接受好友申请 Future> acceptFriendApplication({ required FriendResponseTypeEnum responseType, required FriendApplicationTypeEnum type, // V2TIM_FRIEND_ACCEPT_AGREE,同意添加单向好友;V2TIM_FRIEND_ACCEPT_AGREE_AND_ADD,同意并添加为双向好友 required String userID, }) async { final res = await TIMFriendshipManager.instance.acceptFriendApplication( responseType: responseType, type: type, userID: userID, ); return ImResult.wrap(res); } /// 拉黑 Future>> addToBlackList({ required List userIDList, }) async { final res = await TIMFriendshipManager.instance.addToBlackList(userIDList: userIDList); return ImResult.wrap(res); } /// 取消拉黑 Future>> deleteFromBlackList({ required List userIDList, }) async { final res = await TIMFriendshipManager.instance.deleteFromBlackList(userIDList: userIDList); return ImResult.wrap(res); } ///获取好友列表 Future>> getFriendList() async { final res = await TIMFriendshipManager.instance.getFriendList(); return ImResult.wrap(res); } /// set好友备注 Future setFriendInfo({ required String userID, String? friendRemark, Map? friendCustomInfo, }) async { late V2TimCallback res; res = await TIMFriendshipManager.instance.setFriendInfo( userID: userID, friendRemark: friendRemark, friendCustomInfo: friendCustomInfo, ); return ImResult.wrapNoData(res); } /// 获取好友信息 Future>> getFriendInfo({ required List userIDList, }) async { final res = await TIMFriendshipManager.instance.getFriendsInfo(userIDList: userIDList); return ImResult.wrap(res); } ///关注 Future>> followUser({ required List userIDList, }) async { final res = await TIMFriendshipManager.instance.followUser( userIDList: userIDList, ); return ImResult.wrap(res); } ///取关 Future>> unfollowUser({ required List userIDList, }) async { final res = await TIMFriendshipManager.instance.unfollowUser( userIDList: userIDList, ); return ImResult.wrap(res); } /// check关注的类型 /// 0:不是好友也没有关注 /// 1:你关注了对方(单向) /// 2:对方关注了你(单向) /// 3:互相关注(双向好友) Future>> checkFollowType({ required List userIDList, }) async { final res = await TIMFriendshipManager.instance.checkFollowType( userIDList: userIDList, ); return ImResult.wrap(res); } ///获取指定用户的 关注/粉丝/互关 数量信息 Future>> getUserFollowInfo({ required List userIDList, }) async { final res = await TIMFriendshipManager.instance.getUserFollowInfo(userIDList: userIDList); return ImResult.wrap(res); } /// 获取双向关注列表(互关好友) /// [nextCursor] 分页游标,首次传空字符串 Future> getMutualFollowersList({ required String nextCursor, }) async { final res = await TIMFriendshipManager.instance.getMutualFollowersList( nextCursor: nextCursor, ); return ImResult.wrap(res); } /// 获取我的粉丝列表 /// [nextCursor] 分页游标,首次传空字符串 Future> getMyFollowersList({ required String nextCursor, }) async { final res = await TIMFriendshipManager.instance.getMyFollowersList( nextCursor: nextCursor, ); return ImResult.wrap(res); } }