flutter/lib/IM/im_service.dart
2025-09-13 17:01:01 +08:00

1105 lines
36 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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_group_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/group_add_opt_enum.dart';
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';
import 'package:tencent_cloud_chat_sdk/enum/history_msg_get_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/receive_message_opt_enum.dart';
import 'package:tencent_cloud_chat_sdk/manager/v2_tim_group_manager.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_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';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member.dart';
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';
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_group_manager.dart';
import 'package:tencent_cloud_chat_sdk/native_im/adapter/tim_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<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
await Wxsdk.init();
// 注册用户信息(基本信息+自定义信息)
if (!Get.isRegistered<ImUserInfoController>()) {
final imInfo = Get.put(ImUserInfoController(), permanent: true);
await imInfo.refreshUserInfo();
} else {
await Get.find<ImUserInfoController>().refreshUserInfo();
}
// 登录成功后注册高级消息监听器
final messageService = ImMessageListenerService();
Get.put<ImMessageListenerService>(messageService, permanent: true);
await messageService.init();
// 注册群监听器
final groupListener = ImGroupListeners();
Get.put<ImGroupListeners>(groupListener, permanent: true);
groupListener.register();
// 注册关系链监听器
final friendListener = ImFriendListeners();
Get.put<ImFriendListeners>(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<ImResult> logout() async {
final res = await TencentImSDKPlugin.v2TIMManager.logout();
if (res.code == 0) {
/// 移出消息监听器
await Get.delete<ImMessageListenerService>(force: true);
/// 移出关系链监听器
Get.find<ImFriendListeners>().unregister();
await Get.delete<ImFriendListeners>(force: true);
// 移除群监听器
Get.find<ImGroupListeners>().unregister();
await Get.delete<ImGroupListeners>(force: true);
/// 清理tabbar
Get.find<TabBarController>().badgeMap.clear();
/// 清理会话列表数据
Get.find<ChatController>().initChatData();
/// 移出未读消息监听器
Get.find<GlobalBadge>().onClose();
await Get.delete<GlobalBadge>(force: true);
/// 移除推送服务
await PushService.unInitPush();
/// 反初始化
await ImCore.unInit();
}
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,
);
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);
}
/// 查询会话记录
Future<ImResult> 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 ?? [];
final userIDList = <String>[];
final groupIDList = <String>[];
// 提前收集所有需要批量查询的 userID 和 groupID
for (var conv in convList) {
logger.e('未过滤前到会话数据:${conv.toLogString()}');
if (conv.userID != null) {
userIDList.add(conv.userID!);
} else if (conv.groupID != null) {
groupIDList.add(conv.groupID!);
}
}
logger.e('用户ID$userIDList');
Map<String, String?> userFaceUrlMap = {};
Map<String, String?> groupFaceUrlMap = {};
Map<String, String> 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;
logger.w('自定义信息:${user.toJson()}');
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<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>);
}
}
}
return ImResult(
success: res.code == 0,
code: res.code,
desc: res.desc,
data: viewList,
);
}
///获取所有会话数据
Future<ImResult<V2TimConversationResult>> getConvData(String nextSeq, int count) async {
final res = await TencentImSDKPlugin.v2TIMManager.getConversationManager().getConversationList(nextSeq: nextSeq, count: count);
return ImResult.wrap(res);
}
///获取指定会话
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);
}
/// 获取消息
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);
}
/// 获取聊天记录 如果是群聊传 groupID单聊传 userID二选一
Future<ImResult<List<V2TimMessage>>> getHistoryMessageList({
HistoryMsgGetTypeEnum getType = HistoryMsgGetTypeEnum.V2TIM_GET_LOCAL_OLDER_MSG,
String? userID,
String? groupID,
int? lastMsgSeq,
int count = 10,
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.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]);
return ImResult(
success: res.code == 0,
code: res.code,
desc: res.desc,
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,
);
return ImResult.wrap(res);
}
/// 获取我的关注列表
/// [nextCursor] 分页游标,首次传空字符串
Future<ImResult<V2TimUserInfoResult>> getMyFollowingList({
required String nextCursor,
}) async {
final res = await TIMFriendshipManager.instance.getMyFollowingList(
nextCursor: nextCursor,
);
return ImResult.wrap(res);
}
/// 设置群消息免打扰
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);
}
///------------------------------------
/// 创建群
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);
}
/// 获取当前用户已经加入的群列表
/// 注意:
/// - 直播群(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);
}
/// 邀请他人入群(work群的入群方式任何人可邀请人入群)
///
/// [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);
}
}