flutter/lib/IM/im_service.dart

1105 lines
36 KiB
Dart
Raw Normal View History

2025-07-21 15:46:30 +08:00
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:logger/logger.dart';
2025-08-21 10:50:38 +08:00
import 'package:loopin/IM/controller/chat_controller.dart';
import 'package:loopin/IM/controller/im_user_info_controller.dart';
2025-07-21 15:46:30 +08:00
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';
2025-09-06 14:57:47 +08:00
import 'package:loopin/IM/im_group_listeners.dart';
2025-07-21 15:46:30 +08:00
import 'package:loopin/IM/im_message_listeners.dart';
import 'package:loopin/IM/im_result.dart';
2025-08-21 10:50:38 +08:00
import 'package:loopin/IM/push_service.dart';
2025-07-21 15:46:30 +08:00
import 'package:loopin/models/conversation_view_model.dart';
2025-08-21 10:50:38 +08:00
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';
2025-09-06 14:57:47 +08:00
import 'package:tencent_cloud_chat_sdk/enum/group_add_opt_enum.dart';
2025-09-09 10:57:52 +08:00
import 'package:tencent_cloud_chat_sdk/enum/group_application_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_filter_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_role_enum.dart';
2025-07-21 15:46:30 +08:00
import 'package:tencent_cloud_chat_sdk/enum/history_msg_get_type_enum.dart';
2025-09-13 17:01:01 +08:00
import 'package:tencent_cloud_chat_sdk/enum/receive_message_opt_enum.dart';
2025-09-06 14:57:47 +08:00
import 'package:tencent_cloud_chat_sdk/manager/v2_tim_group_manager.dart';
2025-08-21 10:50:38 +08:00
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart';
2025-07-21 15:46:30 +08:00
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
2025-08-21 10:50:38 +08:00
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';
2025-09-09 10:57:52 +08:00
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_application.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_application_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info_result.dart';
2025-09-06 14:57:47 +08:00
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member.dart';
2025-09-09 10:57:52 +08:00
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_search_param.dart';
2025-07-21 15:46:30 +08:00
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart';
2025-08-21 10:50:38 +08:00
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';
2025-07-21 15:46:30 +08:00
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart';
2025-08-21 10:50:38 +08:00
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_info_result.dart';
2025-07-21 15:46:30 +08:00
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';
2025-08-21 10:50:38 +08:00
import 'package:tencent_cloud_chat_sdk/native_im/adapter/tim_friendship_manager.dart';
2025-09-09 10:57:52 +08:00
import 'package:tencent_cloud_chat_sdk/native_im/adapter/tim_group_manager.dart';
import 'package:tencent_cloud_chat_sdk/native_im/adapter/tim_manager.dart';
2025-08-21 10:50:38 +08:00
import 'package:tencent_cloud_chat_sdk/native_im/adapter/tim_message_manager.dart';
2025-07-21 15:46:30 +08:00
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 ctl = Get.find<ChatController>();
await ctl.getConversationList();
/// 初始化微信 SDK
2025-08-21 10:50:38 +08:00
await Wxsdk.init();
// 注册用户信息(基本信息+自定义信息)
if (!Get.isRegistered<ImUserInfoController>()) {
final imInfo = Get.put(ImUserInfoController(), permanent: true);
await imInfo.refreshUserInfo();
} else {
await Get.find<ImUserInfoController>().refreshUserInfo();
}
2025-07-21 15:46:30 +08:00
// 登录成功后注册高级消息监听器
final messageService = ImMessageListenerService();
Get.put<ImMessageListenerService>(messageService, permanent: true);
await messageService.init();
2025-09-06 14:57:47 +08:00
// 注册群监听器
final groupListener = ImGroupListeners();
Get.put<ImGroupListeners>(groupListener, permanent: true);
groupListener.register();
2025-07-21 15:46:30 +08:00
// 注册关系链监听器
final friendListener = ImFriendListeners();
Get.put<ImFriendListeners>(friendListener, permanent: true);
friendListener.register();
/// 注册消息未读数监听器
Get.put(GlobalBadge(), permanent: true);
// 初始化push服务
PushService().initPush(
sdkAppId: 1600080789,
appKey: 'vkFpe55aYqfV7Sk5uGaoxhEstJ3tcI9dquk7JwG1GloDSLD2HeMWeQweWWXgNlhC',
);
2025-07-21 15:46:30 +08:00
} 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) {
/// 移出消息监听器
await Get.delete<ImMessageListenerService>(force: true);
2025-07-21 15:46:30 +08:00
/// 移出关系链监听器
Get.find<ImFriendListeners>().unregister();
await Get.delete<ImFriendListeners>(force: true);
2025-07-21 15:46:30 +08:00
2025-09-06 14:57:47 +08:00
// 移除群监听器
Get.find<ImGroupListeners>().unregister();
await Get.delete<ImGroupListeners>(force: true);
2025-07-21 15:46:30 +08:00
/// 清理tabbar
Get.find<TabBarController>().badgeMap.clear();
2025-08-21 10:50:38 +08:00
/// 清理会话列表数据
Get.find<ChatController>().initChatData();
2025-07-21 15:46:30 +08:00
/// 移出未读消息监听器
Get.find<GlobalBadge>().onClose();
await Get.delete<GlobalBadge>(force: true);
2025-07-21 15:46:30 +08:00
2025-08-21 10:50:38 +08:00
/// 移除推送服务
await PushService.unInitPush();
2025-08-21 10:50:38 +08:00
2025-07-21 15:46:30 +08:00
/// 反初始化
await ImCore.unInit();
2025-07-21 15:46:30 +08:00
}
2025-08-21 10:50:38 +08:00
return ImResult.wrapNoData(res);
}
/// 设置会话自定义属性
Future<ImResult<List<V2TimConversationOperationResult>>> setConversationCustomData({
required String customData,
required List<String> conversationIDList,
}) async {
final res = await TIMConversationManager.instance.setConversationCustomData(customData: customData, conversationIDList: conversationIDList);
return ImResult.wrap(res);
}
/// 获取符合过滤条件的未读消息总数
Future<ImResult<int>> getUnreadMessageCountByFilter({
required V2TimConversationFilter filter,
}) async {
final res = await TIMConversationManager.instance.getUnreadMessageCountByFilter(
filter: filter,
);
return ImResult.wrap(res);
}
/// 删除会话
Future<ImResult<void>> deleteConversation({
required String conversationID,
}) async {
final res = await TIMConversationManager.instance.deleteConversation(conversationID: conversationID);
return ImResult.wrapNoData(res);
}
/// 创建会话分组
Future<ImResult<List<V2TimConversationOperationResult>>> createConversationGroup({
required String groupName,
required List<String> conversationIDList,
}) async {
final res = await TIMConversationManager.instance.createConversationGroup(
groupName: groupName,
conversationIDList: conversationIDList,
);
return ImResult.wrap(res);
}
/// 获取会话分组列表
Future<ImResult<List<String>>> getConversationGroupList() async {
final res = await TIMConversationManager.instance.getConversationGroupList();
return ImResult.wrap(res);
}
/// 将会话添加到分组
Future<ImResult<List<V2TimConversationOperationResult>>> addConversationsToGroup({
required String groupName,
required List<String> conversationIDList,
}) async {
final res = await TIMConversationManager.instance.addConversationsToGroup(
groupName: groupName,
conversationIDList: conversationIDList,
2025-07-21 15:46:30 +08:00
);
2025-08-21 10:50:38 +08:00
return ImResult.wrap(res);
}
///将会话移除分组
Future<ImResult<List<V2TimConversationOperationResult>>> deleteConversationsFromGroup({
required String groupName,
required List<String> conversationIDList,
}) async {
final res = await TIMConversationManager.instance.deleteConversationsFromGroup(
groupName: groupName,
conversationIDList: conversationIDList,
);
return ImResult.wrap(res);
}
/// 高级查询会话列表
Future<ImResult<V2TimConversationResult>> 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);
2025-07-21 15:46:30 +08:00
}
/// 查询会话记录
Future<ImResult> getConversationList(String nextSeq, int count) async {
2025-08-21 10:50:38 +08:00
// final res = await TencentImSDKPlugin.v2TIMManager.getConversationManager().getConversationList(nextSeq: nextSeq, count: count);
final res = await getConvData(nextSeq, count);
if (res.success == false) {
2025-07-21 15:46:30 +08:00
return ImResult(
success: false,
code: res.code,
desc: res.desc,
);
}
final convList = res.data?.conversationList ?? [];
2025-07-21 15:46:30 +08:00
final userIDList = <String>[];
final groupIDList = <String>[];
// 提前收集所有需要批量查询的 userID 和 groupID
for (var conv in convList) {
2025-08-27 23:26:29 +08:00
logger.e('未过滤前到会话数据:${conv.toLogString()}');
if (conv.userID != null) {
userIDList.add(conv.userID!);
} else if (conv.groupID != null) {
groupIDList.add(conv.groupID!);
2025-07-21 15:46:30 +08:00
}
}
2025-08-27 23:26:29 +08:00
logger.e('用户ID$userIDList');
2025-07-21 15:46:30 +08:00
Map<String, String?> userFaceUrlMap = {};
Map<String, String?> groupFaceUrlMap = {};
Map<String, String> isCustomAdmin = {};
2025-07-21 15:46:30 +08:00
if (userIDList.isNotEmpty) {
final userRes = await TencentImSDKPlugin.v2TIMManager.getUsersInfo(userIDList: userIDList);
2025-07-21 15:46:30 +08:00
if (userRes.code == 0) {
for (var user in userRes.data!) {
final userId = user.userID ?? '';
userFaceUrlMap[userId] = user.faceUrl;
// 读取管理员标识
final customInfo = user.customInfo;
2025-08-27 23:26:29 +08:00
logger.w('自定义信息:${user.toJson()}');
2025-07-21 15:46:30 +08:00
if (customInfo != null) {
isCustomAdmin[userId] = customInfo['admin'] ?? '0';
2025-07-21 15:46:30 +08:00
}
}
}
}
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],
);
2025-07-21 15:46:30 +08:00
}).toList();
2025-08-21 10:50:38 +08:00
// 筛选数据,过滤掉陌生人消息
viewList.removeWhere((conv) {
final special = conv.conversation.conversationGroupList ?? [];
return special.contains('noFriend');
});
ChatController chatcontroller = Get.find<ChatController>();
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<ConversationViewModel>);
}
}
}
2025-07-21 15:46:30 +08:00
return ImResult(
success: res.code == 0,
code: res.code,
desc: res.desc,
data: viewList,
);
}
2025-08-21 10:50:38 +08:00
///获取所有会话数据
Future<ImResult<V2TimConversationResult>> getConvData(String nextSeq, int count) async {
final res = await TencentImSDKPlugin.v2TIMManager.getConversationManager().getConversationList(nextSeq: nextSeq, count: count);
return ImResult.wrap(res);
2025-07-21 15:46:30 +08:00
}
///获取指定会话
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,
);
}
/// 搜索本地消息
Future<ImResult<V2TimMessageSearchResult>> searchLocalMessages({
required String page,
required String conversationID,
/// 关键词匹配机制or=0and=1
int type = 1,
/// ['你好','周末']
required List<String> keywordList,
/// 默认自定义消息
List<int> messageTypeList = const [1, 2],
}) async {
final searchParam = V2TimMessageSearchParam(
type: type,
conversationID: conversationID,
keywordList: keywordList,
messageTypeList: messageTypeList,
pageSize: 100,
// pageIndex: page,
searchCursor: page,
);
final V2TimValueCallback<V2TimMessageSearchResult> res = await TIMMessageManager.instance.searchLocalMessages(searchParam: searchParam);
return ImResult.wrap(res);
}
2025-08-21 10:50:38 +08:00
/// 获取消息
Future<ImResult<List<V2TimMessage>>> findMessages({
required List<String> messageIDList,
}) async {
final res = await TIMMessageManager.instance.findMessages(messageIDList: messageIDList);
return ImResult.wrap(res);
}
/// 修改消息
Future<ImResult<V2TimMessageChangeInfo>> modifyMessage({
required V2TimMessage message,
}) async {
final res = await TIMMessageManager.instance.modifyMessage(message: message);
return ImResult.wrap(res);
}
2025-07-21 15:46:30 +08:00
/// 获取聊天记录 如果是群聊传 groupID单聊传 userID二选一
Future<ImResult<List<V2TimMessage>>> getHistoryMessageList({
HistoryMsgGetTypeEnum getType = HistoryMsgGetTypeEnum.V2TIM_GET_LOCAL_OLDER_MSG,
String? userID,
String? groupID,
int? lastMsgSeq,
2025-08-21 10:50:38 +08:00
int count = 10,
2025-07-21 15:46:30 +08:00
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, // 群聊生效
);
2025-08-21 10:50:38 +08:00
return ImResult.wrapNoData(res);
}
/// 获取自己的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]);
2025-07-21 15:46:30 +08:00
return ImResult(
success: res.code == 0,
code: res.code,
desc: res.desc,
2025-08-21 10:50:38 +08:00
data: res.data?.isNotEmpty == true ? res.data!.first : null,
);
}
/// 查询其他人的信息
Future<ImResult> otherInfo(id) async {
// 获取用户信息
V2TimValueCallback<List<V2TimUserFullInfo>> 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<ImResult> setSelfInfo({
required V2TimUserFullInfo userFullInfo,
}) async {
final res = await TencentImSDKPlugin.v2TIMManager.setSelfInfo(
userFullInfo: userFullInfo,
);
return ImResult.wrapNoData(res);
}
/// 检查是否是好友(双向或单向)
Future<ImResult> 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<ImResult<V2TimFriendOperationResult>> 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<ImResult<V2TimFriendOperationResult>> 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<ImResult<List<V2TimFriendOperationResult>>> addToBlackList({
required List<String> userIDList,
}) async {
final res = await TIMFriendshipManager.instance.addToBlackList(userIDList: userIDList);
return ImResult.wrap(res);
}
/// 取消拉黑
Future<ImResult<List<V2TimFriendOperationResult>>> deleteFromBlackList({
required List<String> userIDList,
}) async {
final res = await TIMFriendshipManager.instance.deleteFromBlackList(userIDList: userIDList);
return ImResult.wrap(res);
}
///获取好友列表
Future<ImResult<List<V2TimFriendInfo>>> getFriendList() async {
final res = await TIMFriendshipManager.instance.getFriendList();
return ImResult.wrap(res);
}
/// set好友备注
Future<ImResult> setFriendInfo({
required String userID,
String? friendRemark,
Map<String, String>? friendCustomInfo,
}) async {
late V2TimCallback res;
res = await TIMFriendshipManager.instance.setFriendInfo(
userID: userID,
friendRemark: friendRemark,
friendCustomInfo: friendCustomInfo,
);
return ImResult.wrapNoData(res);
}
/// 获取好友信息
Future<ImResult<List<V2TimFriendInfoResult>>> getFriendInfo({
required List<String> userIDList,
}) async {
final res = await TIMFriendshipManager.instance.getFriendsInfo(userIDList: userIDList);
return ImResult.wrap(res);
}
///关注
Future<ImResult<List<V2TimFollowOperationResult>>> followUser({
required List<String> userIDList,
}) async {
final res = await TIMFriendshipManager.instance.followUser(
userIDList: userIDList,
);
return ImResult.wrap(res);
}
///取关
Future<ImResult<List<V2TimFollowOperationResult>>> unfollowUser({
required List<String> userIDList,
}) async {
final res = await TIMFriendshipManager.instance.unfollowUser(
userIDList: userIDList,
);
return ImResult.wrap(res);
}
/// check关注的类型
/// 0不是好友也没有关注
/// 1你关注了对方单向
/// 2对方关注了你单向
/// 3互相关注双向好友
Future<ImResult<List<V2TimFollowTypeCheckResult>>> checkFollowType({
required List<String> userIDList,
}) async {
final res = await TIMFriendshipManager.instance.checkFollowType(
userIDList: userIDList,
);
return ImResult.wrap(res);
}
///获取指定用户的 关注/粉丝/互关 数量信息
Future<ImResult<List<V2TimFollowInfo>>> getUserFollowInfo({
required List<String> userIDList,
}) async {
final res = await TIMFriendshipManager.instance.getUserFollowInfo(userIDList: userIDList);
return ImResult.wrap(res);
}
/// 获取双向关注列表(互关好友)
/// [nextCursor] 分页游标,首次传空字符串
Future<ImResult<V2TimUserInfoResult>> getMutualFollowersList({
required String nextCursor,
}) async {
final res = await TIMFriendshipManager.instance.getMutualFollowersList(
nextCursor: nextCursor,
);
return ImResult.wrap(res);
}
/// 获取我的粉丝列表
/// [nextCursor] 分页游标,首次传空字符串
Future<ImResult<V2TimUserInfoResult>> getMyFollowersList({
required String nextCursor,
}) async {
final res = await TIMFriendshipManager.instance.getMyFollowersList(
nextCursor: nextCursor,
2025-07-21 15:46:30 +08:00
);
2025-08-21 10:50:38 +08:00
return ImResult.wrap(res);
2025-07-21 15:46:30 +08:00
}
2025-09-03 11:25:31 +08:00
/// 获取我的关注列表
/// [nextCursor] 分页游标,首次传空字符串
Future<ImResult<V2TimUserInfoResult>> getMyFollowingList({
required String nextCursor,
}) async {
final res = await TIMFriendshipManager.instance.getMyFollowingList(
nextCursor: nextCursor,
);
return ImResult.wrap(res);
}
2025-09-06 14:57:47 +08:00
2025-09-13 17:01:01 +08:00
/// 设置群消息免打扰
Future<ImResult<void>> setGroupReceiveMessageOpt({
required String groupID,
required ReceiveMsgOptEnum opt,
}) async {
final res = await TIMMessageManager.instance.setGroupReceiveMessageOpt(
groupID: groupID,
opt: opt,
);
return ImResult.wrapNoData(res);
}
/// 设置单聊消息免打扰
Future<ImResult<void>> setC2CReceiveMessageOpt({
required List<String> userIDList,
required ReceiveMsgOptEnum opt,
}) async {
final res = await TIMMessageManager.instance.setC2CReceiveMessageOpt(
userIDList: userIDList,
opt: opt,
);
return ImResult.wrapNoData(res);
}
2025-09-09 10:57:52 +08:00
///------------------------------------
2025-09-06 14:57:47 +08:00
/// 创建群
Future<ImResult<String>> createGroup({
String? groupID,
required String groupType,
required String groupName,
String? notification,
String? introduction,
String? faceUrl,
bool? isAllMuted,
bool isSupportTopic = false,
GroupAddOptTypeEnum? addOpt,
List<V2TimGroupMember>? memberList,
GroupAddOptTypeEnum? approveOpt,
bool? isEnablePermissionGroup,
int? defaultPermissions,
}) async {
final res = await V2TIMGroupManager().createGroup(
groupID: groupID,
groupType: groupType,
groupName: groupName,
notification: notification, // 群公告
introduction: introduction, // 群简介
faceUrl: faceUrl, // 群头像
isAllMuted: isAllMuted, // true=全员禁言
isSupportTopic: isSupportTopic, // 是否支持话题
addOpt: addOpt, // 加群方式(非直播群有效)
memberList: memberList, // 初始群成员(不支持直播群)
approveOpt: approveOpt, //入群申请的处理方式(一般和 addOpt 配合使用)对 Work / Public 群有用
isEnablePermissionGroup: isEnablePermissionGroup, // 是否开启权限组
defaultPermissions: defaultPermissions, // 默认权限配置,搭配 isEnablePermissionGroup 使用
);
return ImResult.wrap(res);
}
2025-09-09 10:57:52 +08:00
/// 获取当前用户已经加入的群列表
/// 注意:
/// - 直播群(AVChatRoom) 不支持该 API
/// - SDK 限制调用频率为 1 秒 10 次,超过限制后会报错 7008
Future<ImResult<List<V2TimGroupInfo>>> getJoinedGroupList() async {
final res = await V2TIMGroupManager().getJoinedGroupList();
return ImResult.wrap(res);
}
/// 申请加入群不包含work群work群只能邀请进群
Future<ImResult<void>> joinGroup({
required String groupID,
required String message,
}) async {
final res = await TIMManager.instance.joinGroup(
groupID: groupID,
message: message,
);
return ImResult.wrapNoData(res);
}
/// 拉取群资料
/// 参数:
/// - [groupIDList] 群 ID 列表
Future<ImResult<List<V2TimGroupInfoResult>>> getGroupsInfo({
required List<String> groupIDList,
}) async {
final res = await V2TIMGroupManager().getGroupsInfo(groupIDList: groupIDList);
return ImResult.wrap(res);
}
/// 修改群资料
///
/// 参数:
/// - [info] 群资料参数
Future<ImResult<void>> setGroupInfo({
required V2TimGroupInfo info,
}) async {
final res = await V2TIMGroupManager().setGroupInfo(info: info);
return ImResult.wrapNoData(res);
}
/// 获取群成员列表
///
/// 参数说明:
/// [groupID] 群 ID
/// [filter] 成员过滤类型:
/// - V2TIM_GROUP_MEMBER_FILTER_ALL所有类型
/// - V2TIM_GROUP_MEMBER_FILTER_OWNER群主
/// - V2TIM_GROUP_MEMBER_FILTER_ADMIN群管理员
/// - V2TIM_GROUP_MEMBER_FILTER_COMMON普通群成员
/// [nextSeq] 分页拉取标志,首次传 0
/// [count] 拉取数量,最大 100
Future<ImResult<V2TimGroupMemberInfoResult>> getGroupMemberList({
required String groupID,
required GroupMemberFilterTypeEnum filter,
required String nextSeq,
int count = 20,
}) async {
final res = await V2TIMGroupManager().getGroupMemberList(
groupID: groupID,
filter: filter,
nextSeq: nextSeq,
count: count,
);
return ImResult.wrap(res);
}
/// 获取指定的群成员资料
///
/// [groupID] 群 ID
/// [memberList] 需要获取资料的成员 ID 列表
Future<ImResult<List<V2TimGroupMemberFullInfo>>> getGroupMembersInfo({
required String groupID,
required List<String> memberList,
}) async {
final res = await V2TIMGroupManager().getGroupMembersInfo(
groupID: groupID,
memberList: memberList,
);
return ImResult.wrap(res);
}
/// 修改指定的群成员资料
///
/// [groupID] 群 ID
/// [userID] 成员 ID
/// [nameCard] 群名片(昵称)
/// [customInfo] 自定义字段
Future<ImResult<void>> setGroupMemberInfo({
required String groupID,
required String userID,
String? nameCard,
Map<String, String>? customInfo,
}) async {
final res = await V2TIMGroupManager().setGroupMemberInfo(
groupID: groupID,
userID: userID,
nameCard: nameCard,
customInfo: customInfo,
);
return ImResult.wrapNoData(res);
}
2025-09-13 17:01:01 +08:00
/// 邀请他人入群(work群的入群方式任何人可邀请人入群)
2025-09-09 10:57:52 +08:00
///
/// [groupID] 群 ID
/// [userList] 被邀请成员的 userID 列表
///
/// 注意:
///
/// ```
/// 工作群Work群里的任何人都可以邀请其他人进群。
/// 会议群Meeting和公开群Public只有通过 REST API 使用 App 管理员身份才可以邀请其他人进群。
/// 直播群AVChatRoom不支持此功能。
/// ```
Future<ImResult<List<V2TimGroupMemberOperationResult>>> inviteUserToGroup({
required String groupID,
required List<String> userList,
}) async {
final res = await TIMGroupManager.instance.inviteUserToGroup(
groupID: groupID,
userList: userList,
);
return ImResult.wrap(res);
}
/// 踢人
///
/// [groupID] 群 ID
/// [memberList] 被踢成员的 userID 列表
/// [duration] 禁言时长,单位秒(可选,仅对禁言有效)
/// [reason] 踢人的原因(可选)
///
/// 注意:
/// ```
/// 工作群Work只有群主或 APP 管理员可以踢人。
/// 公开群Public、会议群Meeting群主、管理员和 APP 管理员可以踢人。
/// 直播群AVChatRoom只支持禁言muteGroupMember不支持踢人。
/// ```
Future<ImResult<void>> kickGroupMember({
required String groupID,
required List<String> memberList,
int? duration,
String? reason,
}) async {
final res = await TIMGroupManager.instance.kickGroupMember(
groupID: groupID,
memberList: memberList,
duration: duration,
reason: reason,
);
return ImResult.wrapNoData(res);
}
/// 切换群成员的角色
///
/// [groupID] 群 ID
/// [userID] 被切换角色的成员 userID
/// [role] 目标角色
///
/// 注意:
/// ```
/// 公开群Public和会议群Meeting只有群主才能对群成员进行普通成员和管理员之间的角色切换。
/// 其他群不支持设置群成员角色。
/// 转让群组请调用 transferGroupOwner 接口。
/// ```
Future<ImResult<void>> setGroupMemberRole({
required String groupID,
required String userID,
required GroupMemberRoleTypeEnum role,
}) async {
final res = await TIMGroupManager.instance.setGroupMemberRole(
groupID: groupID,
userID: userID,
role: role,
);
return ImResult.wrapNoData(res);
}
/// 转让群主
///
/// [groupID] 群 ID
/// [userID] 新群主的 userID
///
/// 注意:
/// ```
/// 普通类型的群Work、Public、Meeting只有群主才有权限进行群转让操作。
/// 直播群AVChatRoom不支持转让群主。
/// ```
Future<ImResult<void>> transferGroupOwner({
required String groupID,
required String userID,
}) async {
final res = await TIMGroupManager.instance.transferGroupOwner(
groupID: groupID,
userID: userID,
);
return ImResult.wrapNoData(res);
}
/// 获取加群的申请列表
Future<ImResult<V2TimGroupApplicationResult>> getGroupApplicationList() async {
final res = await TIMGroupManager.instance.getGroupApplicationList();
return ImResult.wrap(res);
}
/// 同意某一条加群申请
Future<ImResult<void>> acceptGroupApplication({
required String groupID,
String? reason,
required String fromUser,
required String toUser, // 处理这条数据的人,管理员或者群主
int? addTime,
GroupApplicationTypeEnum? type,
V2TimGroupApplication? application,
String? webMessageInstance,
}) async {
final res = await TIMGroupManager.instance.acceptGroupApplication(
groupID: groupID,
reason: reason,
fromUser: fromUser,
toUser: toUser,
addTime: addTime,
type: type,
application: application,
);
return ImResult.wrapNoData(res);
}
/// 拒绝某一条加群申请
Future<ImResult> refuseGroupApplication({
required String groupID,
String? reason,
required String fromUser,
required String toUser,
required int addTime,
required GroupApplicationTypeEnum type,
V2TimGroupApplication? application,
}) async {
final res = await TIMGroupManager.instance.refuseGroupApplication(
groupID: groupID,
fromUser: fromUser,
toUser: toUser,
addTime: addTime,
type: type,
application: application,
);
return ImResult.wrapNoData(res);
}
/// 标记加群申请列表为已读
Future<ImResult> setGroupApplicationRead() async {
final res = await TIMGroupManager.instance.setGroupApplicationRead();
return ImResult.wrapNoData(res);
}
/// 搜索本地群组资料
Future<ImResult<List<V2TimGroupInfo>>> searchGroups({
required V2TimGroupSearchParam searchParam,
}) async {
final res = await TIMGroupManager.instance.searchGroups(searchParam: searchParam);
return ImResult.wrap(res);
}
/// 搜索本地群成员
Future<ImResult<V2GroupMemberInfoSearchResult>> searchGroupMembers({
required V2TimGroupMemberSearchParam param,
}) async {
final res = await TIMGroupManager.instance.searchGroupMembers(param: param);
return ImResult.wrap(res);
}
/// 解散群(Work任何人都无法解散群组,其他群:群主可以解散群组)
Future<ImResult<void>> dismissGroup({
required String groupID,
}) async {
final res = await TIMManager.instance.dismissGroup(groupID: groupID);
return ImResult.wrapNoData(res);
}
/// 退群 ,在公开群Public、会议Meeting和直播群AVChatRoom群主是不可以退群的群主只能调用 dismissGroup 解散群组。
Future<ImResult<void>> quitGroup({
required String groupID,
}) async {
final res = await TIMManager.instance.quitGroup(groupID: groupID);
return ImResult.wrapNoData(res);
}
2025-07-21 15:46:30 +08:00
}