This commit is contained in:
2025-06-30 16:24:20 +08:00
commit 68de5eb048
454 changed files with 56921 additions and 0 deletions
BIN
View File
Binary file not shown.
@@ -0,0 +1,15 @@
import 'package:flutter/cupertino.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/base_life_cycle.dart';
class AddFriendLifeCycle {
/// Before requesting to add a user as friend or a contact,
/// `true` means can add continually, while `false` will not add.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(
String userID, String? remark, String? friendGroup, String? addWording,
[BuildContext? context]) shouldAddFriend;
AddFriendLifeCycle({
this.shouldAddFriend = DefaultLifeCycle.defaultAddFriend,
});
}
@@ -0,0 +1,14 @@
import 'package:flutter/cupertino.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/base_life_cycle.dart';
class AddGroupLifeCycle {
/// Before requesting to add or join to a group,
/// `true` means can add continually, while `false` will not add.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(String groupID, String message, [BuildContext? context])
shouldAddGroup;
AddGroupLifeCycle({
this.shouldAddGroup = DefaultLifeCycle.defaultAddGroup,
});
}
@@ -0,0 +1,89 @@
import 'package:flutter/cupertino.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_ui_kit_class.dart';
import 'package:tencent_cloud_chat_uikit/base_widgets/tim_callback.dart';
typedef MessageFunction = Future<V2TimMessage?> Function(V2TimMessage message);
typedef MessageFunctionNullCallback = Function(V2TimValueCallback<V2TimMessage> res);
typedef MessageFunctionOptional = Future<V2TimMessage?> Function(V2TimMessage message);
typedef MessageListFunction = Future<List<V2TimMessage>> Function(List<V2TimMessage> messageList);
typedef MessageListFunctionAsync = List<V2TimMessage> Function(List<V2TimMessage> messageList);
typedef FutureBool = Future<bool>;
typedef AddFriendFunction = Function(String userID, String? remark, String? friendGroup, String? addWording);
typedef ConversationListFunction = Future<List<V2TimConversation?>> Function(List<V2TimConversation?> conversationList);
typedef FriendListFunction = Future<List<V2TimFriendInfo>> Function(List<V2TimFriendInfo> friendList);
typedef FriendInfoFunction = Future<V2TimFriendInfo?> Function(V2TimFriendInfo? friendInfo);
/// Here is the default life cycle hooks implementation for all the hooks in TUIKit.
abstract class DefaultLifeCycle {
static Future<List<V2TimConversation?>> defaultConversationListSolution(List<V2TimConversation?> list) async {
return list;
}
static Future<List<V2TimFriendInfo>> defaultFriendListSolution(List<V2TimFriendInfo> list) async {
return list;
}
static Future<V2TimMessage> defaultMessageSolution(V2TimMessage message) async {
return message;
}
static Future<V2TimMessage> defaultTwoMessagesSolution(V2TimMessage message, [V2TimMessage? repliedMessage]) async {
return message;
}
static Future<List<V2TimMessage>> defaultMessageListSolution(List<V2TimMessage> list) async {
return list;
}
static List<V2TimMessage> defaultMessageListSolutionAsync(List<V2TimMessage> list) {
return list;
}
static Future<bool> defaultAsyncBooleanSolution(dynamic) async {
return true;
}
static bool defaultBooleanSolution(dynamic) {
return true;
}
static defaultNullCallbackSolution(dynamic) {}
static Future<bool> defaultAddFriend(String userID, String? remark, String? friendGroup, String? addWording,
[BuildContext? context]) async {
return true;
}
static Future<bool> defaultAddGroup(String groupID, String message, [BuildContext? context]) async {
return true;
}
static Future<V2TimFriendInfo?> defaultFriendInfoSolution(V2TimFriendInfo? friendInfo) async {
return friendInfo;
}
static Future<void> defaultPopBackRemind() async {
// You have to implement the exact life cycle hook in this case.
TIMUIKitClass.onTIMCallback(TIMCallback(
type: TIMCallbackType.INFO, infoRecommendText: TIM_t("请传入离开群组生命周期函数,提供返回首页或其他页面的导航方法。"), infoCode: 6661402));
return;
}
}
@@ -0,0 +1,12 @@
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/base_life_cycle.dart';
class BlockListLifeCycle {
/// Before requesting to delete a user from block list,
/// `true` means can delete continually, while `false` will not delete.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(List<String> userIDList) shouldDeleteFromBlockList;
BlockListLifeCycle({
this.shouldDeleteFromBlockList = DefaultLifeCycle.defaultAsyncBooleanSolution,
});
}
@@ -0,0 +1,54 @@
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/base_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
class ChatLifeCycle {
/// Before a new message will be added to historical message list from long connection.
/// You may not render this message by return null.
MessageFunctionOptional newMessageWillMount;
/// Before a modified message updated to historical message list UI.
MessageFunction modifiedMessageWillMount;
/// Before a new message will be sent.
/// Returns null can block the message from sending.
// Future<V2TimMessage?> Function(V2TimMessage message, [V2TimMessage? repliedMessage]) messageWillSend;
/// After a new message been sent.
MessageFunctionNullCallback messageDidSend;
/// After getting the latest message list from API,
/// and before historical message list will be rendered.
/// You may add or delete some messages here.
MessageListFunction didGetHistoricalMessageList;
/// Before deleting a message from historical message list,
/// `true` means can delete continually, while `false` will not delete.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(String msgID) shouldDeleteMessage;
/// Before clearing the historical message list,
/// `true` means can clear continually, while `false` will not clear.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(String conversationID) shouldClearHistoricalMessageList;
/// Before rendering a message to message list.
bool Function(V2TimMessage msg) messageShouldMount;
/// Before all message will be rendered on the message list.
/// You may add or delete some messages here.
MessageListFunctionAsync messageListShouldMount;
ChatLifeCycle({
this.shouldClearHistoricalMessageList = DefaultLifeCycle.defaultAsyncBooleanSolution,
this.shouldDeleteMessage = DefaultLifeCycle.defaultAsyncBooleanSolution,
this.messageDidSend = DefaultLifeCycle.defaultNullCallbackSolution,
this.didGetHistoricalMessageList = DefaultLifeCycle.defaultMessageListSolution,
// this.messageWillSend = DefaultLifeCycle.defaultTwoMessagesSolution,
this.modifiedMessageWillMount = DefaultLifeCycle.defaultMessageSolution,
this.newMessageWillMount = DefaultLifeCycle.defaultMessageSolution,
this.messageShouldMount = DefaultLifeCycle.defaultBooleanSolution,
this.messageListShouldMount = DefaultLifeCycle.defaultMessageListSolutionAsync,
});
}
@@ -0,0 +1,25 @@
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/base_life_cycle.dart';
class ConversationLifeCycle {
/// Before deleting a conversation, or a channel, from the conversation list,
/// `true` means can delete continually, while `false` will not delete.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(String conversationID) shouldDeleteConversation;
/// Before clearing the historical message for a specific conversation, provided in parameter,
/// `true` means can clear continually, while `false` will not clear.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(String conversationID)
shouldClearHistoricalMessageForConversation;
/// Before conversation list will mount or update to conversation page.
ConversationListFunction conversationListWillMount;
ConversationLifeCycle({
this.conversationListWillMount =
DefaultLifeCycle.defaultConversationListSolution,
this.shouldClearHistoricalMessageForConversation =
DefaultLifeCycle.defaultAsyncBooleanSolution,
this.shouldDeleteConversation = DefaultLifeCycle.defaultAsyncBooleanSolution,
});
}
@@ -0,0 +1,10 @@
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/base_life_cycle.dart';
class FriendListLifeCycle {
/// Before friend list (contacts list) will mount or update to contacts page.
FriendListFunction friendListWillMount;
FriendListLifeCycle({
this.friendListWillMount = DefaultLifeCycle.defaultFriendListSolution,
});
}
@@ -0,0 +1,11 @@
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/base_life_cycle.dart';
class GroupProfileLifeCycle {
/// In this case, you have better navigating to you home page or conversation list page,
/// due to user request to leave the group, as quitting or disbanding.
Future<void> Function() didLeaveGroup;
GroupProfileLifeCycle({
this.didLeaveGroup = DefaultLifeCycle.defaultPopBackRemind,
});
}
@@ -0,0 +1,20 @@
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/base_life_cycle.dart';
class NewContactLifeCycle {
/// Before accepting a friend or contact requirement from other user,
/// `true` means can accept continually, while `false` will not accept.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(String userID) shouldAcceptContactApplication;
/// Before refusing a friend or contact requirement from other user,
/// `true` means can refuse continually, while `false` will not refuse.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(String userID) shouldRefuseContactApplication;
NewContactLifeCycle({
this.shouldAcceptContactApplication =
DefaultLifeCycle.defaultAsyncBooleanSolution,
this.shouldRefuseContactApplication =
DefaultLifeCycle.defaultAsyncBooleanSolution,
});
}
@@ -0,0 +1,33 @@
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/base_life_cycle.dart';
class ProfileLifeCycle {
/// Before adding a contact to block list,
/// `true` means can add continually, while `false` will not add.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(String userID) shouldAddToBlockList;
/// Before deleting a contact or friend,
/// `true` means can delete continually, while `false` will not delete.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(String userID) shouldDeleteFriend;
/// Before requesting to add a user as friend or a contact,
/// `true` means can add continually, while `false` will not add.
/// You can make a second confirmation here by a modal, etc.
FutureBool Function(String userID) shouldAddFriend;
/// After getting the user info of friend or contact,
/// and before rendering it to the profile page.
FriendInfoFunction didGetFriendInfo;
/// The callback after the remark to a friend changed.
FutureBool Function(String userID) didRemarkUpdated;
ProfileLifeCycle({
this.didRemarkUpdated = DefaultLifeCycle.defaultAsyncBooleanSolution,
this.didGetFriendInfo = DefaultLifeCycle.defaultFriendInfoSolution,
this.shouldAddToBlockList = DefaultLifeCycle.defaultAsyncBooleanSolution,
this.shouldAddFriend = DefaultLifeCycle.defaultAsyncBooleanSolution,
this.shouldDeleteFriend = DefaultLifeCycle.defaultAsyncBooleanSolution,
});
}
@@ -0,0 +1,169 @@
// ignore_for_file: unnecessary_getters_setters
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimGroupListener.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_change_info_type.dart';
import 'package:tencent_cloud_chat_sdk/manager/v2_tim_manager.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_change_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_change_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info_result.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_member_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_topic_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_topic_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
enum UpdateType { groupInfo, memberList, joinApplicationList, groupDismissed, kickedFromGroup }
class NeedUpdate {
final String groupID;
final UpdateType updateType;
final String extraData;
int? groupInfoSubType;
String? ownerID;
NeedUpdate(this.groupID, this.updateType, this.extraData);
}
class TUIGroupListenerModel extends ChangeNotifier {
final GroupServices _groupServices = serviceLocator<GroupServices>();
V2TimGroupListener? _groupListener;
NeedUpdate? _needUpdate;
final TUIChatGlobalModel chatViewModel = serviceLocator<TUIChatGlobalModel>();
late CoreServicesImpl coreInstance = TIMUIKitCore.getInstance();
late V2TIMManager sdkInstance = TIMUIKitCore.getSDKInstance();
NeedUpdate? get needUpdate => _needUpdate;
set needUpdate(NeedUpdate? value) {
Future.delayed(const Duration(seconds: 0), () {
_needUpdate = value;
});
}
TUIGroupListenerModel() {
_groupListener = V2TimGroupListener(onMemberInvited: (groupID, opUser, memberList) {
_needUpdate = NeedUpdate(groupID, UpdateType.memberList, "");
notifyListeners();
}, onMemberKicked: (groupID, opUser, memberList) async {
if (_isLoginUserKickedFromGroup(groupID, memberList)) {
_deleteGroupConversation(groupID);
final groupName = await _getGroupName(groupID);
_needUpdate = NeedUpdate(groupID, UpdateType.kickedFromGroup, groupName);
notifyListeners();
}
}, onMemberEnter: (String groupID, List<V2TimGroupMemberInfo> memberList) {
_needUpdate = NeedUpdate(groupID, UpdateType.memberList, "");
notifyListeners();
}, onMemberLeave: (String groupID, V2TimGroupMemberInfo member) {
_needUpdate = NeedUpdate(groupID, UpdateType.memberList, "");
notifyListeners();
}, onGroupInfoChanged: (groupID, changeInfos) {
_needUpdate = NeedUpdate(groupID, UpdateType.groupInfo, "");
for (V2TimGroupChangeInfo info in changeInfos) {
if (info.type == GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_OWNER) {
_needUpdate!.groupInfoSubType = GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_OWNER;
_needUpdate!.ownerID = info.value;
}
}
notifyListeners();
}, onReceiveJoinApplication: (String groupID, V2TimGroupMemberInfo member, String opReason) async {
_onReceiveJoinApplication(groupID, member, opReason);
chatViewModel.refreshGroupApplicationList();
notifyListeners();
}, onGroupDismissed: (String groupID, V2TimGroupMemberInfo opUser) async {
_deleteGroupConversation(groupID);
final groupName = await _getGroupName(groupID);
_needUpdate = NeedUpdate(groupID, UpdateType.groupDismissed, groupName);
notifyListeners();
});
}
setGroupListener() {
_groupServices.addGroupListener(listener: _groupListener!);
}
removeGroupListener() {
_groupServices.removeGroupListener(listener: _groupListener!);
}
getCommunityCategoryList(String groupID) async {
final Map<String, String>? customInfo = await getCommunityCustomInfo(groupID);
if (customInfo != null) {
final String? categoryListString = customInfo["categoryList"];
if (categoryListString != null && categoryListString.isNotEmpty) {
return jsonDecode(categoryListString);
}
}
}
Future<Map<String, String>?> getCommunityCustomInfo(String groupID) async {
V2TimValueCallback<List<V2TimGroupInfoResult>> res =
await TencentImSDKPlugin.v2TIMManager.getGroupManager().getGroupsInfo(groupIDList: [groupID]);
if (res.code != 0) {
final V2TimGroupInfoResult? groupInfo = res.data?[0];
if (groupInfo != null) {
Map<String, String>? customInfo = groupInfo.groupInfo?.customInfo;
return customInfo;
}
}
return null;
}
setCommunityCategoryList(String groupID, String groupType, List<String> newCategoryList) async {
final Map<String, String>? customInfo = await getCommunityCustomInfo(groupID);
customInfo?["categoryList"] = jsonEncode(newCategoryList);
TencentImSDKPlugin.v2TIMManager.getGroupManager().setGroupInfo(
info: V2TimGroupInfo(
customInfo: customInfo,
groupID: groupID,
groupType: groupType,
// ...其他资料
));
}
addCategoryForTopic(String groupID, String categoryName) {
TencentImSDKPlugin.v2TIMManager.getGroupManager().setTopicInfo(
topicInfo: V2TimTopicInfo(customString: categoryName),
);
}
_onReceiveJoinApplication(String groupID, V2TimGroupMemberInfo member, String opReason) {
Future.delayed(const Duration(milliseconds: 500), () => chatViewModel.refreshGroupApplicationList());
}
Future<String> _getGroupName(String groupID) async {
final groupInfoList = await sdkInstance.getGroupManager().getGroupsInfo(groupIDList: [groupID]);
String groupName = TIM_t("群组");
if (groupInfoList.data != null) {
groupName = groupInfoList.data!.first!.groupInfo!.groupName!;
}
return groupName;
}
void _deleteGroupConversation(String groupID) async {
sdkInstance.getConversationManager().deleteConversation(conversationID: "group_${groupID}");
}
bool _isLoginUserKickedFromGroup(String groupID, List<V2TimGroupMemberInfo> memberList) {
final loginUserInfo = coreInstance.loginInfo;
int index = memberList.indexWhere((element) => element.userID == loginUserInfo.userID);
if (index > -1) {
return true;
}
return false;
}
}
@@ -0,0 +1,12 @@
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
class UserProfile {
late V2TimFriendInfo? friendInfo;
late V2TimConversation? conversation;
UserProfile({required this.friendInfo, required this.conversation});
}
@@ -0,0 +1,174 @@
import 'dart:convert';
import 'dart:io';
import 'package:tencent_chat_i18n_tool/tencent_chat_i18n_tool.dart';
import 'package:tencent_cloud_chat_sdk/enum/message_elem_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/offlinePushInfo.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_uikit/ui/views/TIMUIKitChat/tim_uikit_cloud_custom_data.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
class TUIChatModelTools {
final TUIChatGlobalModel globalModel = serviceLocator<TUIChatGlobalModel>();
final CoreServicesImpl _coreServices = serviceLocator<CoreServicesImpl>();
OfflinePushInfo buildMessagePushInfo(V2TimMessage message, String convID, ConvType convType) {
String createJSON(String convID) {
return "{\"conversationID\": \"$convID\"}";
}
if (globalModel.chatConfig.offlinePushInfo != null) {
final customData = globalModel.chatConfig.offlinePushInfo!(message, convID, convType);
if (customData != null) {
return customData;
}
}
String title = globalModel.chatConfig.notificationTitle;
// If user provides null, use default ext.
String ext = globalModel.chatConfig.notificationExt != null
? globalModel.chatConfig.notificationExt!(message, convID, convType) ??
(convType == ConvType.c2c ? createJSON("c2c_${message.sender}") : createJSON("group_$convID"))
: (convType == ConvType.c2c ? createJSON("c2c_${message.sender}") : createJSON("group_$convID"));
String desc = message.userID ?? message.groupID ?? "";
String messageSummary = "";
switch (message.elemType) {
case MessageElemType.V2TIM_ELEM_TYPE_CUSTOM:
messageSummary = TIM_t("自定义消息");
break;
case MessageElemType.V2TIM_ELEM_TYPE_FACE:
messageSummary = TIM_t("表情消息");
break;
case MessageElemType.V2TIM_ELEM_TYPE_FILE:
messageSummary = TIM_t("文件消息");
break;
case MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS:
messageSummary = TIM_t("群提示消息");
break;
case MessageElemType.V2TIM_ELEM_TYPE_IMAGE:
messageSummary = TIM_t("图片消息");
break;
case MessageElemType.V2TIM_ELEM_TYPE_LOCATION:
messageSummary = TIM_t("位置消息");
break;
case MessageElemType.V2TIM_ELEM_TYPE_MERGER:
messageSummary = TIM_t("合并转发消息");
break;
case MessageElemType.V2TIM_ELEM_TYPE_SOUND:
messageSummary = TIM_t("语音消息");
break;
case MessageElemType.V2TIM_ELEM_TYPE_TEXT:
messageSummary = message.textElem!.text!;
break;
case MessageElemType.V2TIM_ELEM_TYPE_VIDEO:
messageSummary = TIM_t("视频消息");
break;
}
if (globalModel.chatConfig.notificationBody != null) {
desc = globalModel.chatConfig.notificationBody!(message, convID, convType) ?? messageSummary;
} else {
desc = messageSummary;
}
return OfflinePushInfo(
title: title,
desc: desc,
disablePush: false,
ext: ext,
iOSSound: globalModel.chatConfig.notificationIOSSound,
androidSound: globalModel.chatConfig.notificationAndroidSound,
ignoreIOSBadge: false,
androidOPPOChannelID: globalModel.chatConfig.notificationOPPOChannelID,
androidVIVOClassification: 1,
);
}
V2TimMessage setUserInfoForMessage(V2TimMessage messageInfo, String? id) {
final loginUserInfo = _coreServices.loginUserInfo;
if (loginUserInfo != null) {
messageInfo.faceUrl = loginUserInfo.faceUrl;
messageInfo.nickName = loginUserInfo.nickName;
messageInfo.sender = loginUserInfo.userID;
}
messageInfo.timestamp = (DateTime.now().millisecondsSinceEpoch / 1000).ceil();
messageInfo.isSelf = true;
messageInfo.id = id;
return messageInfo;
}
String getMessageSummary(V2TimMessage message, String? Function(V2TimMessage message)? abstractMessageBuilder) {
final String? customAbstractMessage = abstractMessageBuilder != null ? abstractMessageBuilder(message) : null;
if (customAbstractMessage != null) {
return customAbstractMessage;
}
final elemType = message.elemType;
switch (elemType) {
case MessageElemType.V2TIM_ELEM_TYPE_FACE:
return "[表情消息]";
case MessageElemType.V2TIM_ELEM_TYPE_CUSTOM:
return "[自定义消息]";
case MessageElemType.V2TIM_ELEM_TYPE_FILE:
return "[文件消息]";
case MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS:
return "[群消息]";
case MessageElemType.V2TIM_ELEM_TYPE_IMAGE:
return "[图片消息]";
case MessageElemType.V2TIM_ELEM_TYPE_LOCATION:
return "[位置消息]";
case MessageElemType.V2TIM_ELEM_TYPE_MERGER:
return "[合并消息]";
case MessageElemType.V2TIM_ELEM_TYPE_NONE:
return "[没有元素]";
case MessageElemType.V2TIM_ELEM_TYPE_SOUND:
return "[语音消息]";
case MessageElemType.V2TIM_ELEM_TYPE_TEXT:
return message.textElem?.text ?? "[文本消息]";
case MessageElemType.V2TIM_ELEM_TYPE_VIDEO:
return "[视频消息]";
default:
return "";
}
}
String getMessageAbstract(V2TimMessage message, String? Function(V2TimMessage message)? abstractMessageBuilder) {
final messageAbstract = RepliedMessageAbstract(
summary: TIM_t(getMessageSummary(message, abstractMessageBuilder)),
elemType: message.elemType,
msgID: message.msgID,
timestamp: message.timestamp,
seq: message.seq);
return jsonEncode(messageAbstract.toJson());
}
Future<V2TimMessage?> getExistingMessageByID(
{required String msgID, required String conversationID, required ConvType conversationType}) async {
final currentHistoryMsgList = globalModel.messageListMap[conversationID] ?? [];
final int? targetIndex = currentHistoryMsgList.indexWhere((item) {
return item.msgID == msgID;
});
if (targetIndex != null && targetIndex > -1 && currentHistoryMsgList.isNotEmpty) {
return currentHistoryMsgList[targetIndex];
} else {
return null;
}
}
Future<bool> hasZeroSize(String filePath) async {
try {
final file = File(filePath);
final fileSize = await file.length();
return fileSize == 0;
} catch (e) {
return false;
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,363 @@
// ignore_for_file: unnecessary_getters_setters, avoid_print
import 'package:flutter/cupertino.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_filter_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_role.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_member_role_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/group_type.dart';
import 'package:tencent_cloud_chat_sdk/enum/receive_message_opt_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_operation_result.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_member_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_param.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_member_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_search_result.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_member_search_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_value_callback.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_value_callback.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/group_profile_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/friendShip/friendship_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/logger.dart';
class TUIGroupProfileModel extends ChangeNotifier {
final CoreServicesImpl _coreServices = serviceLocator<CoreServicesImpl>();
final GroupServices _groupServices = serviceLocator<GroupServices>();
final ConversationService _conversationService = serviceLocator<ConversationService>();
final MessageService _messageService = serviceLocator<MessageService>();
final FriendshipServices _friendshipServices = serviceLocator<FriendshipServices>();
GroupProfileLifeCycle? _lifeCycle;
V2TimConversation? _conversation;
String _groupID = "";
List<V2TimFriendInfo>? _contactList;
List<V2TimGroupMemberFullInfo?>? _groupMemberList;
String _groupMemberListSeq = "0";
V2TimGroupInfo? _groupInfo;
Function(V2TimGroupMemberFullInfo groupMemberFullInfo, TapDownDetails? tapDetails)? onClickUser;
GroupProfileLifeCycle? get lifeCycle => _lifeCycle;
set lifeCycle(GroupProfileLifeCycle? value) {
_lifeCycle = value;
}
V2TimConversation? get conversation => _conversation;
set conversation(V2TimConversation? value) {
_conversation = value;
}
String get groupID => _groupID;
set groupID(String value) {
_groupID = value;
}
List<V2TimFriendInfo> get contactList => _contactList ?? [];
set contactList(List<V2TimFriendInfo> value) {
_contactList = value;
}
List<V2TimGroupMemberFullInfo?> get groupMemberList => _groupMemberList ?? [];
set groupMemberList(List<V2TimGroupMemberFullInfo?> value) {
_groupMemberList = value;
}
V2TimGroupInfo? get groupInfo => _groupInfo;
set groupInfo(V2TimGroupInfo? value) {
_groupInfo = value;
}
void loadData(String groupID) {
_groupID = groupID;
loadGroupInfo(groupID);
loadGroupMemberList(groupID: groupID);
_loadConversation();
_loadContactList();
}
loadGroupInfo(String groupID) async {
final groupInfo = await _groupServices.getGroupsInfo(groupIDList: [groupID]);
if (groupInfo != null) {
final groupRes = groupInfo.first;
if (groupRes.resultCode == 0) {
_groupInfo = groupRes.groupInfo;
}
}
notifyListeners();
}
Future<void> loadGroupMemberList({required String groupID, int count = 100, String? seq}) async {
final String? nextSeq = await _loadGroupMemberListFunction(groupID: groupID, seq: seq, count: count);
if (nextSeq != null && nextSeq != "0" && nextSeq != "") {
return await loadGroupMemberList(groupID: groupID, count: count, seq: nextSeq);
} else {
notifyListeners();
}
}
Future<String?> _loadGroupMemberListFunction({required String groupID, int count = 100, String? seq}) async {
if (seq == null || seq == "" || seq == "0") {
_groupMemberList?.clear();
}
final res = await _groupServices.getGroupMemberList(
groupID: groupID,
filter: GroupMemberFilterTypeEnum.V2TIM_GROUP_MEMBER_FILTER_ALL,
count: count,
nextSeq: seq ?? _groupMemberListSeq);
final groupMemberListRes = res.data;
if (res.code == 0 && groupMemberListRes != null) {
final groupMemberListTemp = groupMemberListRes.memberInfoList ?? [];
// TODO
outputLogger.i(
"loadGroupMemberListfinish,groupMemberListTemp, ${groupMemberListRes.nextSeq}, ${groupMemberListTemp.length}");
_groupMemberList = [...?_groupMemberList, ...groupMemberListTemp];
_groupMemberListSeq = groupMemberListRes.nextSeq ?? "0";
}
return groupMemberListRes?.nextSeq;
}
_loadConversation() async {
conversation = await _conversationService.getConversation(conversationID: "group_$_groupID");
}
_loadContactList() async {
final res = await _friendshipServices.getFriendList();
_contactList = res;
}
pinedConversation(bool isPined) async {
await _conversationService.pinConversation(conversationID: "group_$_groupID", isPinned: isPined);
conversation?.isPinned = isPined;
notifyListeners();
}
setMessageDisturb(bool value) async {
final res = await _messageService.setGroupReceiveMessageOpt(
groupID: _groupID,
opt: value ? ReceiveMsgOptEnum.V2TIM_RECEIVE_NOT_NOTIFY_MESSAGE : ReceiveMsgOptEnum.V2TIM_RECEIVE_MESSAGE);
if (res.code == 0) {
conversation?.recvOpt =
(value ? ReceiveMsgOptEnum.V2TIM_RECEIVE_NOT_NOTIFY_MESSAGE : ReceiveMsgOptEnum.V2TIM_RECEIVE_MESSAGE).index;
}
notifyListeners();
}
Future<V2TimValueCallback<V2GroupMemberInfoSearchResult>> searchGroupMember(
V2TimGroupMemberSearchParam searchParam) async {
final res = await _groupServices.searchGroupMembers(searchParam: searchParam);
if (res.code == 0) {}
return res;
}
Future<V2TimCallback?> setGroupName(String groupName) async {
if (_groupInfo != null) {
String? originalGroupName = _groupInfo?.groupName;
_groupInfo?.groupName = groupName;
V2TimGroupInfo v2timGroupInfo = V2TimGroupInfo(groupID: _groupID, groupType: _groupInfo!.groupType);
v2timGroupInfo.groupName = groupName;
final response = await _groupServices.setGroupInfo(info: v2timGroupInfo);
if (response.code != 0) {
_groupInfo?.groupName = originalGroupName;
}
notifyListeners();
return response;
}
return null;
}
setGroupNotification(String notification) async {
if (_groupInfo != null) {
V2TimGroupInfo v2timGroupInfo = V2TimGroupInfo(groupID: _groupID, groupType: _groupInfo!.groupType);
v2timGroupInfo.notification = notification;
final response = await _groupServices.setGroupInfo(info: v2timGroupInfo);
if (response.code == 0) {
notifyListeners();
_groupInfo?.notification = notification;
}
}
}
String getSelfNameCard() {
try {
final loginUserID = _coreServices.loginUserInfo?.userID;
String nameCard = "";
if (_groupMemberList != null) {
nameCard = groupMemberList.firstWhere((element) => element?.userID == loginUserID)?.nameCard ?? "";
}
return nameCard;
} catch (err) {
return "";
}
}
Future<V2TimCallback?> setNameCard(String nameCard) async {
final loginUserID = _coreServices.loginUserInfo?.userID;
if (loginUserID != null) {
final res = await _groupServices.setGroupMemberInfo(groupID: _groupID, userID: loginUserID, nameCard: nameCard);
if (res.code == 0) {
final targetIndex = _groupMemberList?.indexWhere((element) => element?.userID == loginUserID);
if (targetIndex != -1) {
_groupMemberList![targetIndex!]!.nameCard = nameCard;
notifyListeners();
}
}
return res;
}
return null;
}
Future<V2TimCallback?> setGroupAddOpt(int addOpt) async {
if (_groupInfo != null) {
int? originalAddopt = _groupInfo?.groupAddOpt;
_groupInfo?.groupAddOpt = addOpt;
V2TimGroupInfo v2timGroupInfo = V2TimGroupInfo(groupID: _groupID, groupType: _groupInfo!.groupType);
v2timGroupInfo.groupAddOpt = addOpt;
final response = await _groupServices.setGroupInfo(info: v2timGroupInfo);
if (response.code != 0) {
_groupInfo?.groupAddOpt = originalAddopt;
}
notifyListeners();
return response;
}
return null;
}
Future<V2TimCallback> setMemberToNormal(String userID) async {
final res = await _groupServices.setGroupMemberRole(
groupID: _groupID, userID: userID, role: GroupMemberRoleTypeEnum.V2TIM_GROUP_MEMBER_ROLE_MEMBER);
if (res.code == 0) {
final targetIndex = _groupMemberList!.indexWhere((e) => e!.userID == userID);
if (targetIndex != -1) {
final targetElem = _groupMemberList![targetIndex];
targetElem?.role = GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER;
_groupMemberList![targetIndex] = targetElem;
}
notifyListeners();
}
return res;
}
Future<V2TimCallback> setMemberToAdmin(String userID) async {
final res = await _groupServices.setGroupMemberRole(
groupID: _groupID, userID: userID, role: GroupMemberRoleTypeEnum.V2TIM_GROUP_MEMBER_ROLE_ADMIN);
if (res.code == 0) {
final targetIndex = _groupMemberList!.indexWhere((e) => e!.userID == userID);
if (targetIndex != -1) {
final targetElem = _groupMemberList![targetIndex];
targetElem?.role = GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN;
_groupMemberList![targetIndex] = targetElem;
}
notifyListeners();
}
return res;
}
void onOwnerChanged(String? userID) {
if (userID == null) {
return;
}
// 把之前的群主更新为普通成员
final preOwnerIndex =
_groupMemberList!.indexWhere((e) => e!.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER);
if (preOwnerIndex != -1) {
final preOwnerElem = _groupMemberList![preOwnerIndex];
preOwnerElem?.role = GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_MEMBER;
print("preOwnerUserID: ${preOwnerElem?.userID}");
}
// 设置新的群主
final targetIndex = _groupMemberList!.indexWhere((e) => e!.userID == userID);
if (targetIndex != -1) {
final targetElem = _groupMemberList![targetIndex];
targetElem?.role = GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER;
_groupMemberList![targetIndex] = targetElem;
print("newOwnerUserID: ${targetElem?.userID}");
}
notifyListeners();
}
bool canInviteMember() {
final groupType = _groupInfo?.groupType;
return groupType == GroupType.Work || groupType == "Private";
}
bool canKickOffMember() {
final isGroupOwner = _groupInfo?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_OWNER;
final isAdmin = _groupInfo?.role == GroupMemberRoleType.V2TIM_GROUP_MEMBER_ROLE_ADMIN;
if (_groupInfo?.groupType == GroupType.Work) {
/// work 群主才能踢人
return isGroupOwner;
}
if (_groupInfo?.groupType == GroupType.Public || _groupInfo?.groupType == GroupType.Meeting) {
/// public || meeting 群主和管理员可以踢人
return isGroupOwner || isAdmin;
}
return false;
}
Future<V2TimCallback?> setMuteAll(bool muteAll) async {
if (_groupInfo != null) {
_groupInfo?.isAllMuted = muteAll;
V2TimGroupInfo v2timGroupInfo = V2TimGroupInfo(groupID: _groupID, groupType: _groupInfo!.groupType);
v2timGroupInfo.isAllMuted = muteAll;
final response = await _groupServices.setGroupInfo(info: v2timGroupInfo);
if (response.code != 0) {
_groupInfo?.isAllMuted = muteAll;
}
notifyListeners();
return response;
}
return null;
}
Future<V2TimCallback?> muteGroupMember(String userID, bool isMute, int? serverTime) async {
const muteTime = 315360000;
final res = await _groupServices.muteGroupMember(groupID: _groupID, userID: userID, seconds: isMute ? muteTime : 0);
if (res.code == 0) {
final targetIndex = _groupMemberList!.indexWhere((e) => e!.userID == userID);
if (targetIndex != -1) {
final targetElem = _groupMemberList![targetIndex];
targetElem?.muteUntil = isMute ? (serverTime ?? 0) + muteTime : 0;
_groupMemberList![targetIndex] = targetElem;
}
notifyListeners();
}
return null;
}
Future<V2TimCallback> kickOffMember(List<String> userIDs) async {
final res = await _groupServices.kickGroupMember(groupID: _groupID, memberList: userIDs);
return res;
}
Future<V2TimValueCallback<List<V2TimGroupMemberOperationResult>>> inviteUserToGroup(List<String> userIDS) async {
final res = await _groupServices.inviteUserToGroup(groupID: _groupID, userList: userIDS);
return res;
}
}
@@ -0,0 +1,243 @@
// ignore_for_file: avoid_print
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_sdk/enum/friend_type_enum.dart';
import 'package:tencent_cloud_chat_sdk/enum/receive_message_opt_enum.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_operation_result.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/profile_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/model/profile_model.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_friendship_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/core_services_implements.dart';
import 'package:tencent_cloud_chat_uikit/data_services/friendShip/friendship_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
class TUIProfileViewModel extends ChangeNotifier {
final ConversationService _conversationService = serviceLocator<ConversationService>();
final FriendshipServices _friendshipServices = serviceLocator<FriendshipServices>();
final TUIFriendShipViewModel _friendShipViewModel = serviceLocator<TUIFriendShipViewModel>();
final CoreServicesImpl _coreServices = serviceLocator<CoreServicesImpl>();
final MessageService _messageService = serviceLocator<MessageService>();
UserProfile? _userProfile;
ProfileLifeCycle? _lifeCycle;
bool? _shouldAddToBlackList;
int _friendType = 0;
bool? _isDisturb;
UserProfile? get userProfile {
return _userProfile;
}
set userProfile(UserProfile? value) {
_userProfile = value;
notifyListeners();
}
bool? get isDisturb {
return _isDisturb;
}
bool? get isAddToBlackList {
return _shouldAddToBlackList;
}
int get friendType {
return _friendType;
}
set lifeCycle(ProfileLifeCycle? value) {
_lifeCycle = value;
}
loadData({required String userID, bool isNeedConversation = true}) async {
if (userID.isEmpty) {
return;
}
V2TimFriendInfo? friendUserInfo;
V2TimConversation? conversation;
final userInfoList = await _friendshipServices.getFriendsInfo(userIDList: [userID]);
final checkFriend =
await _friendshipServices.checkFriend(userIDList: [userID], checkType: FriendTypeEnum.V2TIM_FRIEND_TYPE_SINGLE);
if (checkFriend != null) {
final res = checkFriend.first;
if (res.resultCode == 0) {
_friendType = res.resultType;
}
}
if (userInfoList != null) {
friendUserInfo = userInfoList[0].friendInfo;
}
if (isNeedConversation) {
conversation = await _conversationService.getConversation(conversationID: "c2c_$userID");
_isDisturb = conversation?.recvOpt == 2;
}
final friendInfo = await _lifeCycle?.didGetFriendInfo(friendUserInfo) ?? friendUserInfo;
_isDisturb = conversation?.recvOpt == 2;
_userProfile = UserProfile(friendInfo: friendInfo, conversation: conversation);
_shouldAddToBlackList = _friendShipViewModel.blockList.indexWhere((element) => element.userID == userID) > -1;
notifyListeners();
}
Future<V2TimCallback> pinedConversation(bool isPined, String convID) async {
final res = await _conversationService.pinConversation(conversationID: convID, isPinned: isPined);
_userProfile?.conversation!.isPinned = isPined;
notifyListeners();
return res;
}
Future<List<V2TimFriendOperationResult>?> addToBlackList(bool shouldAdd, String userID) async {
if (_lifeCycle?.shouldAddToBlockList != null && await _lifeCycle!.shouldAddToBlockList(userID) == false) {
return null;
}
if (shouldAdd) {
final res = await _friendshipServices.addToBlackList(userIDList: [userID]);
if (res != null && res.isNotEmpty) {
final result = res.first;
if (result.resultCode == 0) {
_shouldAddToBlackList = true;
_friendType = 0;
}
}
notifyListeners();
return res;
} else {
final res = await _friendshipServices.deleteFromBlackList(userIDList: [userID]);
if (res != null && res.isNotEmpty) {
final result = res.first;
if (result.resultCode == 0) {
_shouldAddToBlackList = false;
final checkFriend = await _friendshipServices
.checkFriend(userIDList: [userID], checkType: FriendTypeEnum.V2TIM_FRIEND_TYPE_SINGLE);
if (checkFriend != null) {
final res = checkFriend.first;
_friendType = res.resultType;
}
}
}
_friendShipViewModel.loadBlockListData();
notifyListeners();
return res;
}
}
Future<V2TimFriendOperationResult?> deleteFriend(String userID, {bool needUpdateData = true}) async {
if (_lifeCycle?.shouldDeleteFriend != null && await _lifeCycle!.shouldDeleteFriend(userID) == false) {
return null;
}
final res = await _friendshipServices
.deleteFromFriendList(userIDList: [userID], deleteType: FriendTypeEnum.V2TIM_FRIEND_TYPE_BOTH);
if (res != null) {
_conversationService.deleteConversation(conversationID: "c2c_$userID");
if (needUpdateData) {
loadData(userID: userID);
}
return res.first;
}
return null;
}
Future<V2TimCallback> changeFriendVerificationMethod(int allowType) async {
V2TimUserFullInfo userFullInfo = V2TimUserFullInfo();
userFullInfo.allowType = allowType;
final res = await _coreServices.setSelfInfo(userFullInfo: userFullInfo);
if (res.code == 0) {
_userProfile?.friendInfo!.userProfile!.allowType = allowType;
notifyListeners();
}
return res;
}
Future<V2TimFriendOperationResult?> addFriend(String userID) async {
if (_lifeCycle?.shouldAddFriend != null && await _lifeCycle!.shouldAddFriend(userID) == false) {
return null;
}
final res = await _friendshipServices.addFriend(userID: userID, addType: FriendTypeEnum.V2TIM_FRIEND_TYPE_BOTH);
if (res.code == 0) {
loadData(userID: userID);
return res.data;
}
return null;
}
Future<V2TimCallback> updateRemarks(String userID, String remark) async {
final res = await _friendshipServices.setFriendInfo(userID: userID, friendRemark: remark);
if (res.code == 0) {
_userProfile?.friendInfo!.friendRemark = remark;
notifyListeners();
}
return res;
}
Future<V2TimCallback> setMessageDisturb(String userID, bool isDisturb) async {
final res = await _messageService.setC2CReceiveMessageOpt(
userIDList: [userID],
opt: isDisturb ? ReceiveMsgOptEnum.V2TIM_RECEIVE_NOT_NOTIFY_MESSAGE : ReceiveMsgOptEnum.V2TIM_RECEIVE_MESSAGE);
if (res.code == 0) {
_isDisturb = isDisturb;
}
notifyListeners();
return res;
}
updateUserInfo(V2TimUserFullInfo userFullInfo) {
if (userFullInfo.nickName != null) {
_userProfile?.friendInfo!.userProfile?.nickName = userFullInfo.nickName;
}
if (userFullInfo.faceUrl != null) {
_userProfile?.friendInfo!.userProfile?.faceUrl = userFullInfo.faceUrl;
}
if (userFullInfo.selfSignature != null) {
_userProfile?.friendInfo!.userProfile?.selfSignature = userFullInfo.selfSignature;
}
if (userFullInfo.gender != null) {
_userProfile?.friendInfo!.userProfile?.gender = userFullInfo.gender;
}
if (userFullInfo.allowType != null) {
_userProfile?.friendInfo!.userProfile?.allowType = userFullInfo.allowType;
}
if (userFullInfo.customInfo != null) {
_userProfile?.friendInfo!.userProfile?.customInfo = userFullInfo.customInfo;
}
if (userFullInfo.role != null) {
_userProfile?.friendInfo!.userProfile?.role = userFullInfo.role;
}
if (userFullInfo.level != null) {
_userProfile?.friendInfo!.userProfile?.level = userFullInfo.level;
}
if (userFullInfo.birthday != null) {
_userProfile?.friendInfo!.userProfile?.birthday = userFullInfo.birthday;
}
}
Future<V2TimCallback> updateSelfInfo(V2TimUserFullInfo userFullInfo) async {
final res = await _coreServices.setSelfInfo(userFullInfo: userFullInfo);
if (res.code == 0) {
updateUserInfo(userFullInfo);
notifyListeners();
}
return res;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,335 @@
// ignore_for_file: unnecessary_getters_setters
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimConversationListener.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_callback.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_callback.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_search_param.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_search_param.dart';
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/conversation_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_chat_global_model.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/friendShip/friendship_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/tencent_cloud_chat_uikit.dart';
import 'package:tencent_cloud_chat_uikit/ui/utils/platform.dart';
List<T> removeDuplicates<T>(List<T> list, bool Function(T first, T second) isEqual) {
List<T> output = [];
for (var i = 0; i < list.length; i++) {
bool found = false;
for (var j = 0; j < output.length; j++) {
if (isEqual(list[i], output[j])) {
found = true;
}
}
if (!found) {
output.add(list[i]);
}
}
return output;
}
class TUIConversationViewModel extends ChangeNotifier {
static const String conversationC2CPrefix = "c2c_";
static const String conversationGroupPrefix = "group_";
final TUISelfInfoViewModel selfInfoViewModel = serviceLocator<TUISelfInfoViewModel>();
final ConversationService _conversationService = serviceLocator<ConversationService>();
final FriendshipServices _friendshipServices = serviceLocator<FriendshipServices>();
final TUIChatGlobalModel _chatGlobalModel = serviceLocator<TUIChatGlobalModel>();
final MessageService _messageService = serviceLocator<MessageService>();
late V2TimConversationListener _conversationListener;
List<V2TimConversation?> _conversationList = [];
static V2TimConversation? _selectedConversation;
Map<String, String> webDraftMap = {};
bool _haveMoreData = true;
int _totalUnReadCount = 0;
String? _scrollToConversation;
final TUIChatGlobalModel globalChatModel = serviceLocator<TUIChatGlobalModel>();
String _nextSeq = "0";
ConversationLifeCycle? _lifeCycle;
List<V2TimConversation?> get conversationList {
if (PlatformUtils().isWeb) {
try {
_conversationList.sort((a, b) {
return b!.lastMessage!.timestamp!.compareTo(a!.lastMessage!.timestamp!);
});
final pinnedConversation = _conversationList.where((element) => element?.isPinned == true).toList();
_conversationList.removeWhere((element) => element?.isPinned == true);
_conversationList = [...pinnedConversation, ..._conversationList];
// ignore: empty_catches
} catch (e) {}
} else {
_conversationList.sort((a, b) => b!.orderkey!.compareTo(a!.orderkey!));
}
return _conversationList;
}
V2TimConversation? getConversation(String conversationID) {
return _conversationList.firstWhereOrNull((element) => element?.conversationID == conversationID);
}
String? get scrollToConversation => _scrollToConversation;
set scrollToConversation(String? value) {
_scrollToConversation = value;
notifyListeners();
}
void clearScrollToConversation() {
_scrollToConversation = null;
}
bool get haveMoreData {
return _haveMoreData;
}
int get totalUnReadCount => _totalUnReadCount;
set totalUnReadCount(int value) {
_totalUnReadCount = value;
}
set lifeCycle(ConversationLifeCycle? value) {
_lifeCycle = value;
}
set conversationList(List<V2TimConversation?> conversationList) {
_conversationList = conversationList;
notifyListeners();
}
set selectedConversation(V2TimConversation? value) {
_selectedConversation = value;
notifyListeners();
}
V2TimConversation? get selectedConversation {
return _selectedConversation;
}
static V2TimConversation? of() {
return _selectedConversation;
}
TUIConversationViewModel() {
_conversationListener = V2TimConversationListener(onConversationChanged: (conversationList) {
_onConversationListChanged(conversationList);
}, onNewConversation: (conversationList) {
_addNewConversation(conversationList);
}, onTotalUnreadMessageCountChanged: (totalUnread) {
_totalUnReadCount = totalUnread;
_chatGlobalModel.totalUnReadCount = totalUnread;
notifyListeners();
}, onSyncServerFinish: () {
// Remove the process to load such a many of conversations after launching
if (!PlatformUtils().isWeb) {
loadInitConversation();
}
}, onConversationDeleted: (List<String> conversationIDList) {
_onConversationDeleted(conversationIDList);
for (var conversationID in conversationIDList) {
String resultID = "";
if (conversationID.startsWith(conversationC2CPrefix)) {
resultID = conversationID.replaceFirst(conversationC2CPrefix, "");
} else if (conversationID.startsWith(conversationGroupPrefix)) {
resultID = conversationID.replaceFirst(conversationGroupPrefix, "");
}
if (resultID != "") {
_chatGlobalModel.removeMessageList(resultID);
}
}
});
}
loadInitConversation() async {
await loadData(count: 40);
// Remove the process to load such a many of conversations after launching
// if (selfInfoViewModel.globalConfig?.isPreloadMessagesAfterInit ?? true) {
// _chatGlobalModel.initMessageMapFromLocalDatabase(_conversationList);
// }
}
initConversation() async {
clearData();
loadInitConversation();
}
Future<void> loadData({required int count}) async {
_haveMoreData = true;
final isRefresh = _nextSeq == "0";
final conversationResult = await _conversationService.getConversationList(nextSeq: _nextSeq, count: count);
_nextSeq = conversationResult?.nextSeq ?? "";
final conversationList = conversationResult?.conversationList;
if (conversationList != null) {
if (conversationList.isEmpty || conversationList.length < count) {
_haveMoreData = false;
}
List<V2TimConversation?> combinedConversationList = [];
if (isRefresh) {
combinedConversationList = conversationList;
} else {
combinedConversationList = [..._conversationList, ...conversationList];
}
final List<V2TimConversation?> finalConversationList =
await _lifeCycle?.conversationListWillMount(combinedConversationList) ?? combinedConversationList;
_conversationList = removeDuplicates<V2TimConversation?>(
finalConversationList, (item1, item2) => item1?.conversationID == item2?.conversationID);
notifyListeners();
}
_totalUnReadCount = await _conversationService.getTotalUnreadCount();
notifyListeners();
return;
}
void setSelectedConversation(V2TimConversation conversation) {
_selectedConversation = conversation;
notifyListeners();
}
Future<V2TimCallback> pinConversation({
required String conversationID,
required bool isPinned,
}) {
return _conversationService.pinConversation(conversationID: conversationID, isPinned: isPinned);
}
Future<V2TimCallback?> clearHistoryMessage({required String convID, required int convType}) async {
if (_lifeCycle?.shouldClearHistoricalMessageForConversation != null &&
await _lifeCycle!.shouldClearHistoricalMessageForConversation(convID) == false) {
return null;
}
globalChatModel.setMessageList(convID, []);
if (convType == 1) {
return _messageService.clearC2CHistoryMessage(userID: convID);
} else {
return _messageService.clearGroupHistoryMessage(groupID: convID);
}
}
searchFriends(String searchKey) async {
final res = await _friendshipServices.searchFriends(searchParam: V2TimFriendSearchParam(keywordList: [searchKey]));
return res;
}
Future<V2TimCallback?> deleteConversation({required String conversationID}) async {
if (_lifeCycle?.shouldDeleteConversation != null &&
await _lifeCycle!.shouldDeleteConversation(conversationID) == false) {
return null;
}
final res = await _conversationService.deleteConversation(conversationID: conversationID);
if (res.code == 0) {
_conversationList.removeWhere((element) => element?.conversationID == conversationID);
notifyListeners();
}
return res;
}
_onConversationListChanged(List<V2TimConversation> list) {
for (int element = 0; element < list.length; element++) {
int index = _conversationList.indexWhere((item) => item!.conversationID == list[element].conversationID);
if (index > -1) {
_conversationList.setAll(index, [list[element]] as List<V2TimConversation?>);
} else {
_conversationList.add(list[element]);
}
}
notifyListeners();
}
_onConversationDeleted(List<String> list) {
for (int i = 0; i < list.length; i++) {
int index = _conversationList.indexWhere((item) => item!.conversationID == list[i]);
if (index > -1) {
_conversationList.removeAt(index);
_conversationList = removeDuplicates<V2TimConversation?>(
_conversationList, (item1, item2) => item1?.conversationID == item2?.conversationID);
}
}
notifyListeners();
}
_addNewConversation(List<V2TimConversation> list) {
_conversationList.addAll(list);
_conversationList = removeDuplicates<V2TimConversation?>(
_conversationList, (item1, item2) => item1?.conversationID == item2?.conversationID);
notifyListeners();
}
setConversationListener() {
_conversationService.addConversationListener(listener: _conversationListener);
}
removeConversationListener() {
_conversationService.removeConversationListener(listener: _conversationListener);
}
Future<V2TimCallback> setConversationDraft({
required String conversationID,
String? draftText,
bool isTopic = false,
String? groupID,
bool isAllowWeb = true,
}) async {
assert(!isTopic || (groupID != null && groupID.isNotEmpty),
"When 'isTopic' is true, 'groupID' must not be null or empty.");
if (PlatformUtils().isWeb && isAllowWeb) {
webDraftMap[conversationID] = draftText ?? "";
return V2TimCallback(code: 0, desc: "");
} else {
if (isTopic) {
final topicInfoList = await TencentImSDKPlugin.v2TIMManager
.getGroupManager()
.getTopicInfoList(groupID: groupID!, topicIDList: [conversationID]);
final topicInfo = topicInfoList.data?.first.topicInfo;
topicInfo?.draftText = draftText;
final res = await TencentImSDKPlugin.v2TIMManager.getGroupManager().setTopicInfo(topicInfo: topicInfo!);
return res;
} else {
return _conversationService.setConversationDraft(conversationID: conversationID, draftText: draftText);
}
}
}
clearWebDraft({
required String conversationID,
}) {
webDraftMap[conversationID] = "";
}
String? getWebDraft({
required String conversationID,
}) {
return TencentUtils.checkString(webDraftMap[conversationID]);
}
clearData() {
_conversationList = [];
_selectedConversation = null;
_nextSeq = "0";
_haveMoreData = true;
notifyListeners();
}
refresh({int count = 100}) {
_nextSeq = "0";
_haveMoreData = true;
loadData(count: count);
}
}
@@ -0,0 +1,266 @@
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:tencent_cloud_chat_sdk/enum/V2TimFriendshipListener.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/models/v2_tim_friend_application.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_application.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_operation_result.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_operation_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_member_full_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_status.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_user_status.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/block_list_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/friend_list_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/life_cycle/new_contact_life_cycle.dart';
import 'package:tencent_cloud_chat_uikit/business_logic/view_models/tui_self_info_view_model.dart';
import 'package:tencent_cloud_chat_uikit/data_services/friendShip/friendship_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
class TUIFriendShipViewModel extends ChangeNotifier {
final FriendshipServices _friendshipServices = serviceLocator<FriendshipServices>();
final GroupServices _groupServices = serviceLocator<GroupServices>();
final TUISelfInfoViewModel selfInfoViewModel = serviceLocator<TUISelfInfoViewModel>();
late V2TimFriendshipListener friendShipListener;
List<V2TimFriendApplication?>? _friendApplicationList;
List<V2TimFriendInfo>? _friendList;
List<V2TimGroupInfo>? _groupList;
List<V2TimUserStatus>? _userStatusList;
int _friendApplicationAmount = 0;
List<V2TimFriendInfo>? _blockList;
NewContactLifeCycle? _newContactLifeCycle;
FriendListLifeCycle? _contactListLifeCycle;
BlockListLifeCycle? _blockListLifeCycle;
set newContactLifeCycle(NewContactLifeCycle? value) {
_newContactLifeCycle = value;
}
set contactListLifeCycle(FriendListLifeCycle? value) {
_contactListLifeCycle = value;
}
set blockListLifeCycle(BlockListLifeCycle? value) {
_blockListLifeCycle = value;
}
set userStatusList(List<V2TimUserStatus> value) {
_userStatusList = value;
notifyListeners();
}
List<V2TimUserStatus> get userStatusList => _userStatusList ?? [];
List<V2TimFriendInfo> get blockList {
return _blockList ?? [];
}
List<V2TimGroupInfo> get groupList {
return _groupList ?? [];
}
List<V2TimFriendInfo>? get friendList {
return _friendList;
}
int get friendApplicationAmount => _friendApplicationAmount;
List<V2TimFriendApplication?>? get friendApplicationList => _friendApplicationList;
TUIFriendShipViewModel() {
friendShipListener = V2TimFriendshipListener(
onFriendApplicationListAdded: (applicationList) {
loadContactApplicationData();
},
onFriendApplicationListDeleted: (userIDList) {
loadContactApplicationData();
},
onFriendApplicationListRead: () {
loadContactApplicationData();
},
onFriendInfoChanged: (infoList) {
loadContactListData();
},
onFriendListAdded: (users) async {
await loadContactListData();
loadUserStatus();
},
onFriendListDeleted: (userList) async {
await loadContactListData();
loadUserStatus();
},
onBlackListAdd: (infoList) async {
await loadBlockListData();
loadUserStatus();
},
onBlackListDeleted: (userList) async {
await loadBlockListData();
loadUserStatus();
},
);
}
initFriendShipModel() {
loadData();
}
loadData() async {
loadContactApplicationData();
loadBlockListData();
await loadContactListData();
loadUserStatus();
}
clearData() {
_friendApplicationList = [];
_friendApplicationAmount = 0;
_friendList = [];
_userStatusList = [];
_blockList = [];
notifyListeners();
}
loadUserStatus() async {
if (selfInfoViewModel.globalConfig?.isShowOnlineStatus == false || friendList == null || friendList!.isEmpty) {
return;
}
final List<List<String>> userIDSet = [];
final int needHowManyRequest = ((friendList!.length) / 500).ceil();
final int amountEachRequest = ((friendList!.length) / needHowManyRequest).ceil();
for (int i = 0; i < needHowManyRequest; i++) {
userIDSet.add(friendList!
.getRange(i * amountEachRequest, min(friendList!.length, (i + 1) * amountEachRequest))
.map((e) => e.userID)
.toList());
}
final List<List<V2TimUserStatus>> userStatus = await Future.wait([
...userIDSet.map((userIDList) async {
return await _friendshipServices.getUserStatus(userIDList: userIDList);
})
]);
final List<V2TimUserStatus> flatUserStatus = [];
for (var e in userStatus) {
flatUserStatus.addAll(e);
}
userStatusList = flatUserStatus;
}
loadContactApplicationData() async {
final newContactRes = await _friendshipServices.getFriendApplicationList();
// Only Received Application
_friendApplicationList = newContactRes?.friendApplicationList
?.where((item) => item!.type == FriendApplicationTypeEnum.V2TIM_FRIEND_APPLICATION_COME_IN.index)
.toList();
_friendApplicationAmount = _friendApplicationList?.length ?? 0;
notifyListeners();
}
Future<void> loadContactListData() async {
final List<V2TimFriendInfo> res = await _friendshipServices.getFriendList() ?? [];
final memberList = await _contactListLifeCycle?.friendListWillMount(res) ?? res;
_friendList = memberList;
notifyListeners();
return;
}
Future<bool> isFriend(String userID) async {
final List<V2TimFriendInfo> res = await _friendshipServices.getFriendList() ?? [];
for (V2TimFriendInfo info in res) {
if (info.userID == userID) {
return true;
}
}
return false;
}
Future<void> loadBlockListData() async {
final blockListRes = await _friendshipServices.getBlackList();
_blockList = blockListRes ?? [];
notifyListeners();
return;
}
loadGroupListData() async {
final groupListRes = await _groupServices.getJoinedGroupList();
_groupList = groupListRes ?? [];
if (_groupList != null && _groupList!.isNotEmpty) {
notifyListeners();
}
return;
}
Future<List<V2TimFriendOperationResult>?> deleteFromBlockList(List<String> userIDList) async {
if (_blockListLifeCycle?.shouldDeleteFromBlockList != null &&
await _blockListLifeCycle!.shouldDeleteFromBlockList(userIDList) == false) {
return null;
}
final res = await _friendshipServices.deleteFromBlackList(userIDList: userIDList);
if (res != null) {
return res;
}
return null;
}
Future<V2TimFriendOperationResult?> acceptFriendApplication(
String userID,
int type,
) async {
if (_newContactLifeCycle?.shouldAcceptContactApplication != null &&
await _newContactLifeCycle!.shouldAcceptContactApplication(userID) == false) {
return null;
}
final res = await _friendshipServices.acceptFriendApplication(
responseType: FriendResponseTypeEnum.V2TIM_FRIEND_ACCEPT_AGREE_AND_ADD,
type: FriendApplicationTypeEnum.values[type],
userID: userID,
);
if (res != null) {
return res;
}
return null;
}
Future<V2TimFriendOperationResult?> refuseFriendApplication(
String userID,
int type,
) async {
if (_newContactLifeCycle?.shouldRefuseContactApplication != null &&
await _newContactLifeCycle!.shouldRefuseContactApplication(userID) == false) {
return null;
}
final res = await _friendshipServices.refuseFriendApplication(
type: FriendApplicationTypeEnum.values[type],
userID: userID,
);
if (res != null) {
return res;
}
return null;
}
Future<List<V2TimGroupMemberFullInfo?>> getGroupMembersInfo(
{required String groupID, required List<String> memberList}) async {
final res = await _groupServices.getGroupMembersInfo(groupID: groupID, memberList: memberList);
return res.data ?? [];
}
addFriendListener({V2TimFriendshipListener? listener}) {
_friendshipServices.addFriendListener(listener: friendShipListener);
}
removeFriendshipListener({V2TimFriendshipListener? listener}) {
_friendshipServices.removeFriendListener(listener: friendShipListener);
}
}
@@ -0,0 +1,149 @@
// ignore_for_file: constant_identifier_names
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_conversation.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_info_result.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_info_result.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_friend_search_param.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_friend_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_info.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_search_param.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_param.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message_search_param.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_message_search_result_item.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_message_search_result_item.dart';
import 'package:tencent_cloud_chat_uikit/data_services/friendShip/friendship_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/services_locatar.dart';
import 'package:tencent_cloud_chat_uikit/data_services/message/message_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/conversation/conversation_services.dart';
import 'package:tencent_cloud_chat_uikit/data_services/group/group_services.dart';
enum KeywordListMatchType { V2TIM_KEYWORD_LIST_MATCH_TYPE_OR, V2TIM_KEYWORD_LIST_MATCH_TYPE_AND }
class TUISearchViewModel extends ChangeNotifier {
final FriendshipServices _friendshipServices = serviceLocator<FriendshipServices>();
final MessageService _messageService = serviceLocator<MessageService>();
final ConversationService _conversationService = serviceLocator<ConversationService>();
final GroupServices _groupServices = serviceLocator<GroupServices>();
List<V2TimFriendInfoResult>? friendList = [];
List<V2TimMessageSearchResultItem>? msgList = [];
int msgPage = 0;
int totalMsgCount = 0;
int totalMsgInConversationCount = 0;
List<V2TimMessage> currentMsgListForConversation = [];
List<V2TimGroupInfo>? groupList = [];
List<V2TimConversation?> conversationList = [];
Future<List<V2TimConversation?>?> initConversationMsg() async {
final conversationResult = await _conversationService.getConversationList(nextSeq: "0", count: 500);
final conversationListData = conversationResult?.conversationList;
conversationList = conversationListData ?? [];
notifyListeners();
return conversationListData;
}
void initSearch() {
friendList = [];
msgList = [];
groupList = [];
totalMsgCount = 0;
notifyListeners();
}
void searchFriendByKey(String searchKey) async {
final searchResult =
await _friendshipServices.searchFriends(searchParam: V2TimFriendSearchParam(keywordList: [searchKey]));
friendList = searchResult;
notifyListeners();
}
void searchGroupByKey(String searchKey) async {
final searchResult =
await _groupServices.searchGroups(searchParam: V2TimGroupSearchParam(keywordList: [searchKey]));
groupList = searchResult.data ?? [];
notifyListeners();
}
void getMsgForConversation(String keyword, String conversationId, int page) async {
void clearData() {
currentMsgListForConversation = [];
totalMsgInConversationCount = 0;
}
if (page == 0) {
clearData();
}
if (keyword.isEmpty) {
clearData();
return;
}
final searchResult = await _messageService.searchLocalMessages(
searchParam: V2TimMessageSearchParam(
keywordList: [keyword],
pageIndex: page,
pageSize: 30,
searchTimePeriod: 0,
searchTimePosition: 0,
conversationID: conversationId,
type: KeywordListMatchType.V2TIM_KEYWORD_LIST_MATCH_TYPE_OR.index,
));
if (searchResult.code == 0 && searchResult.data != null) {
final messageSearchResultItems = searchResult.data!.messageSearchResultItems!
.firstWhereOrNull((element) => element.conversationID == conversationId);
totalMsgInConversationCount = messageSearchResultItems?.messageCount ?? 0;
currentMsgListForConversation = [
...currentMsgListForConversation,
...(messageSearchResultItems?.messageList ?? [])
];
}
notifyListeners();
}
void searchMsgByKey(String searchKey, bool isFirst) async {
if (isFirst == true) {
msgPage = 0;
msgList = [];
totalMsgCount = 0;
}
final searchResult = await _messageService.searchLocalMessages(
searchParam: V2TimMessageSearchParam(
keywordList: [searchKey],
pageIndex: msgPage,
pageSize: 5,
searchTimePeriod: 0,
searchTimePosition: 0,
type: KeywordListMatchType.V2TIM_KEYWORD_LIST_MATCH_TYPE_OR.index,
));
if (searchResult.code == 0 && searchResult.data != null) {
msgPage++;
msgList = [...?msgList, ...?searchResult.data!.messageSearchResultItems];
totalMsgCount = searchResult.data!.totalCount ?? 0;
}
notifyListeners();
}
void searchByKey(String? searchKey) async {
if (searchKey == null || searchKey.isEmpty) {
friendList = [];
groupList = [];
msgList = [];
totalMsgCount = 0;
notifyListeners();
} else {
searchFriendByKey(searchKey);
searchMsgByKey(searchKey, true);
searchGroupByKey(searchKey);
}
}
}
@@ -0,0 +1,25 @@
import 'package:flutter/cupertino.dart';
import 'package:tencent_cloud_chat_sdk/models/v2_tim_user_full_info.dart'
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_user_full_info.dart';
import 'package:tencent_cloud_chat_uikit/data_services/core/tim_uikit_config.dart';
class TUISelfInfoViewModel extends ChangeNotifier {
V2TimUserFullInfo? _loginInfo;
TIMUIKitConfig? _globalConfig;
TIMUIKitConfig? get globalConfig => _globalConfig;
set globalConfig(TIMUIKitConfig? value) {
_globalConfig = value;
notifyListeners();
}
V2TimUserFullInfo? get loginInfo {
return _loginInfo;
}
setLoginInfo(V2TimUserFullInfo? value) {
_loginInfo = value;
notifyListeners();
}
}
@@ -0,0 +1,26 @@
import 'package:flutter/cupertino.dart';
import 'package:shared_preferences/shared_preferences.dart';
class TUISettingModel extends ChangeNotifier {
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
final String keyTitle = "tencent_chat_uikit_";
double? _keyboardHeight;
double get keyboardHeight => _keyboardHeight ?? 0;
set keyboardHeight(double value) {
if(value > 40 && _keyboardHeight != value){
_keyboardHeight = value;
updateLocalSetting("${keyTitle}keyboardHeight", value.toString());
}
}
updateLocalSetting(String key, String value) async {
SharedPreferences prefs = await _prefs;
prefs.setString(key, value);
}
init() async {
SharedPreferences prefs = await _prefs;
_keyboardHeight = double.parse(prefs.getString("${keyTitle}keyboardHeight") ?? "0");
}
}