308 lines
9.3 KiB
Dart
308 lines
9.3 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:get/get.dart';
|
||
import 'package:logger/logger.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/models/conversation_view_model.dart';
|
||
import 'package:tencent_cloud_chat_sdk/enum/history_msg_get_type_enum.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
|
||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.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/tencent_im_sdk_plugin.dart';
|
||
|
||
final logger = Logger();
|
||
|
||
/// IM 服务封装类
|
||
class ImService {
|
||
ImService._();
|
||
static final instance = ImService._();
|
||
|
||
/// 登录
|
||
Future<ImResult> 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 messageService = ImMessageListenerService();
|
||
Get.put<ImMessageListenerService>(messageService, permanent: true);
|
||
|
||
await messageService.init();
|
||
|
||
// 注册关系链监听器
|
||
final friendListener = ImFriendListeners();
|
||
logger.i(friendListener);
|
||
Get.put<ImFriendListeners>(friendListener, permanent: true);
|
||
friendListener.register();
|
||
|
||
/// 注册消息未读数监听器
|
||
Get.put(GlobalBadge(), permanent: true);
|
||
// Get.lazyPut<GlobalBadge>(() => GlobalBadge());
|
||
} 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<ImResult> logout() async {
|
||
final res = await TencentImSDKPlugin.v2TIMManager.logout();
|
||
if (res.code == 0) {
|
||
/// 移出消息监听器
|
||
Get.find<ImMessageListenerService>().onClose();
|
||
Get.delete<ImMessageListenerService>(force: true);
|
||
|
||
/// 移出关系链监听器
|
||
Get.find<ImFriendListeners>().unregister();
|
||
Get.delete<ImFriendListeners>(force: true);
|
||
|
||
/// 清理tabbar
|
||
Get.find<TabBarController>().badgeMap.clear();
|
||
|
||
/// 移出未读消息监听器
|
||
Get.find<GlobalBadge>().onClose();
|
||
Get.delete<GlobalBadge>(force: true);
|
||
|
||
/// 反初始化
|
||
ImCore.unInit();
|
||
}
|
||
return ImResult(
|
||
success: res.code == 0,
|
||
code: res.code,
|
||
desc: res.desc,
|
||
);
|
||
}
|
||
|
||
/// 查询会话记录
|
||
Future<ImResult> getConversationList(String nextSeq, int count) async {
|
||
final res = await TencentImSDKPlugin.v2TIMManager.getConversationManager().getConversationList(nextSeq: nextSeq, count: count);
|
||
|
||
if (res.code != 0) {
|
||
return ImResult(
|
||
success: false,
|
||
code: res.code,
|
||
desc: res.desc,
|
||
);
|
||
}
|
||
|
||
final convList = res.data?.conversationList ?? [];
|
||
final userIDList = <String>[];
|
||
final groupIDList = <String>[];
|
||
|
||
// 提前收集所有需要批量查询的 userID 和 groupID
|
||
for (var conv in convList) {
|
||
if ((conv.faceUrl == null || conv.faceUrl!.isEmpty)) {
|
||
if (conv.userID != null) {
|
||
userIDList.add(conv.userID!);
|
||
} else if (conv.groupID != null) {
|
||
groupIDList.add(conv.groupID!);
|
||
}
|
||
}
|
||
}
|
||
|
||
Map<String, String?> userFaceUrlMap = {};
|
||
Map<String, String?> groupFaceUrlMap = {};
|
||
String isCustomAdmin = '0';
|
||
|
||
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 = customInfo['Tag_Profile_Custom_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;
|
||
|
||
// 如果 faceUrl 本身为空,尝试从查到的 map 中取值
|
||
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);
|
||
}).toList();
|
||
|
||
return ImResult(
|
||
success: res.code == 0,
|
||
code: res.code,
|
||
desc: res.desc,
|
||
data: viewList,
|
||
);
|
||
}
|
||
|
||
/// 获取自己的userId
|
||
Future<ImResult> selfUserId() async {
|
||
V2TimValueCallback<String> self = await TencentImSDKPlugin.v2TIMManager.getLoginUser();
|
||
String? userId = self.data;
|
||
return ImResult(
|
||
success: self.code == 0,
|
||
code: self.code,
|
||
desc: self.desc,
|
||
data: userId,
|
||
);
|
||
}
|
||
|
||
/// 查询当前登录用户的个人信息
|
||
Future<ImResult> selfInfo() async {
|
||
// 获取当前登录的用户 ID
|
||
final idRes = await selfUserId();
|
||
// 获取用户信息
|
||
V2TimValueCallback<List<V2TimUserFullInfo>> 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![0] : null,
|
||
);
|
||
}
|
||
|
||
///获取指定会话
|
||
Future<ImResult> getConversation({
|
||
required String conversationID,
|
||
}) async {
|
||
final res = await TIMConversationManager.instance.getConversation(conversationID: conversationID); //c2c_conversationID,group_conversationID
|
||
|
||
return ImResult<V2TimConversation?>(
|
||
success: res.code == 0 && res.data != null,
|
||
code: res.code,
|
||
desc: res.desc,
|
||
data: res.data,
|
||
);
|
||
}
|
||
|
||
/// 获取聊天记录 如果是群聊传 groupID,单聊传 userID,二选一
|
||
Future<ImResult<List<V2TimMessage>>> getHistoryMessageList({
|
||
HistoryMsgGetTypeEnum getType = HistoryMsgGetTypeEnum.V2TIM_GET_LOCAL_OLDER_MSG,
|
||
String? userID,
|
||
String? groupID,
|
||
int? lastMsgSeq,
|
||
int count = 20,
|
||
V2TimMessage? lastMsg,
|
||
List<int>? messageTypeList,
|
||
List<int>? 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<List<V2TimMessage>> 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<List<V2TimMessage>>(
|
||
success: res.code == 0,
|
||
code: res.code,
|
||
desc: res.desc,
|
||
data: res.data ?? [],
|
||
);
|
||
}
|
||
|
||
///
|
||
/// 清理指定单聊会话的未读数
|
||
///
|
||
Future<ImResult> 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(
|
||
success: res.code == 0,
|
||
code: res.code,
|
||
desc: res.desc,
|
||
);
|
||
}
|
||
}
|