2025-07-21 15:46:30 +08:00
|
|
|
|
import 'package:get/get.dart';
|
|
|
|
|
import 'package:loopin/IM/im_service.dart';
|
2025-08-21 10:50:38 +08:00
|
|
|
|
import 'package:loopin/models/conversation_type.dart' as myConversationType;
|
2025-07-21 15:46:30 +08:00
|
|
|
|
import 'package:loopin/models/conversation_view_model.dart';
|
2025-08-21 10:50:38 +08:00
|
|
|
|
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation.dart';
|
|
|
|
|
import 'package:tencent_cloud_chat_sdk/models/v2_tim_conversation_filter.dart';
|
2025-07-21 15:46:30 +08:00
|
|
|
|
|
|
|
|
|
class ChatController extends GetxController {
|
2025-08-21 10:50:38 +08:00
|
|
|
|
RxInt count = 20.obs; // 每页条数
|
2025-07-21 15:46:30 +08:00
|
|
|
|
RxString nextSeq = '0'.obs; // 页码
|
2025-08-21 10:50:38 +08:00
|
|
|
|
RxBool isFinished = false.obs; // 是否拉取完?默认未拉取完
|
2025-07-21 15:46:30 +08:00
|
|
|
|
|
|
|
|
|
final chatList = <ConversationViewModel>[].obs;
|
|
|
|
|
|
2025-08-21 10:50:38 +08:00
|
|
|
|
void initChatData() {
|
2025-08-26 17:38:59 +08:00
|
|
|
|
chatList.clear();
|
2025-08-21 10:50:38 +08:00
|
|
|
|
nextSeq.value = '0';
|
|
|
|
|
isFinished.value = false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-03 11:25:31 +08:00
|
|
|
|
/// 检测分组
|
|
|
|
|
Future<bool> handleGroup({required String conversationID}) async {
|
|
|
|
|
final isReal = await ImService.instance.getConversation(conversationID: conversationID);
|
|
|
|
|
final V2TimConversation conv = isReal.data;
|
|
|
|
|
if (conv.lastMessage != null) {
|
|
|
|
|
// 会话存在执行后续逻辑
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
// 会话不存在,结束
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 关注后移除陌生人会话
|
|
|
|
|
Future<void> removeNoFriend({required String conversationID}) async {
|
|
|
|
|
try {
|
|
|
|
|
final isContinue = await handleGroup(conversationID: conversationID);
|
|
|
|
|
if (isContinue) {
|
|
|
|
|
await ImService.instance.deleteConversationsFromGroup(
|
|
|
|
|
groupName: myConversationType.ConversationTypeStatic.noFriend,
|
|
|
|
|
conversationIDList: [conversationID],
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
logger.e('移除陌生人会话分组异常:$e');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 取关后将会话移入陌生人会话
|
|
|
|
|
Future<void> mergeNoFriend({required conversationID}) async {
|
|
|
|
|
try {
|
|
|
|
|
final isContinue = await handleGroup(conversationID: conversationID);
|
|
|
|
|
if (isContinue) {
|
|
|
|
|
final typeEnum = myConversationType.ConversationTypeStatic.noFriend;
|
|
|
|
|
final hasGroupRes = await ImService.instance.getConversationGroupList();
|
|
|
|
|
if (hasGroupRes.success) {
|
|
|
|
|
final exists = hasGroupRes.data?.any((item) => item == typeEnum) ?? false;
|
|
|
|
|
if (!exists) {
|
|
|
|
|
// 组不存在,创建组并把会话加入group中
|
|
|
|
|
await ImService.instance.createConversationGroup(
|
|
|
|
|
groupName: typeEnum,
|
|
|
|
|
conversationIDList: [conversationID],
|
|
|
|
|
);
|
|
|
|
|
logger.i('取关触发添加会话分组$typeEnum成功');
|
|
|
|
|
} else {
|
|
|
|
|
// 分组存在直接添加
|
|
|
|
|
await ImService.instance.addConversationsToGroup(
|
|
|
|
|
groupName: typeEnum,
|
|
|
|
|
conversationIDList: [conversationID],
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
final res = chatList.firstWhereOrNull((item) => item.conversation.conversationID == conversationID);
|
|
|
|
|
|
|
|
|
|
if (res != null) {
|
|
|
|
|
chatList.remove(res);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
logger.w('移除会话列表时发生错误: $e');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 关注后更新nofd菜单入口
|
|
|
|
|
Future<void> updateNoFriendMenu() async {
|
|
|
|
|
final res = await ImService.instance.getConversationListByFilter(
|
|
|
|
|
filter: V2TimConversationFilter(conversationGroup: myConversationType.ConversationType.noFriend.name),
|
|
|
|
|
nextSeq: 0,
|
|
|
|
|
count: 1,
|
|
|
|
|
);
|
|
|
|
|
if (res.success && res.data != null) {
|
|
|
|
|
final convList = res.data!.conversationList ?? [];
|
|
|
|
|
if (convList.isNotEmpty) {
|
|
|
|
|
// 只要有数据,入口一定存在,找到入口数据替换
|
|
|
|
|
final unread = await ImService.instance.getUnreadMessageCountByFilter(
|
|
|
|
|
filter: V2TimConversationFilter(
|
|
|
|
|
conversationGroup: myConversationType.ConversationType.noFriend.name,
|
|
|
|
|
hasUnreadCount: true,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (unread.success) {
|
|
|
|
|
var viewModelList = await ConversationViewModel.createConversationViewModel(convList: [convList.first]);
|
|
|
|
|
final conviewModel = viewModelList.first;
|
|
|
|
|
conviewModel.faceUrl = 'assets/images/notify/msr.png';
|
|
|
|
|
conviewModel.isCustomAdmin = myConversationType.ConversationTypeStatic.noFriend;
|
|
|
|
|
conviewModel.conversation.showName = '陌生人消息';
|
|
|
|
|
conviewModel.conversation.unreadCount = unread.data;
|
|
|
|
|
conviewModel.conversation.conversationID = myConversationType.ConversationTypeStatic.noFriend;
|
|
|
|
|
|
|
|
|
|
// final newList = List<ConversationViewModel>.from(chatList);
|
|
|
|
|
final index = chatList.indexWhere(
|
|
|
|
|
(item) => item.isCustomAdmin == myConversationType.ConversationTypeStatic.noFriend,
|
|
|
|
|
);
|
|
|
|
|
if (index != -1) {
|
|
|
|
|
chatList[index] = conviewModel;
|
|
|
|
|
// 排序
|
|
|
|
|
chatList.sort((a, b) {
|
|
|
|
|
final atime = a.conversation.lastMessage?.timestamp ?? 0;
|
|
|
|
|
final btime = b.conversation.lastMessage?.timestamp ?? 0;
|
|
|
|
|
return btime.compareTo(atime); // 降序
|
|
|
|
|
});
|
|
|
|
|
// 更新
|
|
|
|
|
chatList.refresh();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
logger.e('刷新入口失败-----${res.desc}');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-21 10:50:38 +08:00
|
|
|
|
// 获取所有会话列表
|
2025-08-26 21:21:59 +08:00
|
|
|
|
Future<void> getConversationList() async {
|
2025-08-26 17:38:59 +08:00
|
|
|
|
logger.e('开始获取会话列表数据');
|
2025-08-21 10:50:38 +08:00
|
|
|
|
if (isFinished.value) {
|
|
|
|
|
// 拉取完数据了,直接结束
|
2025-08-26 17:38:59 +08:00
|
|
|
|
logger.e('会话触底无数据');
|
2025-08-21 10:50:38 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
2025-08-26 17:38:59 +08:00
|
|
|
|
try {
|
|
|
|
|
final res = await ImService.instance.getConversationList(nextSeq.value, count.value);
|
2025-07-21 15:46:30 +08:00
|
|
|
|
|
2025-08-26 17:38:59 +08:00
|
|
|
|
if (!res.success || res.data == null) {
|
|
|
|
|
logger.e('获取会话失败::${res.desc}');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-07-21 15:46:30 +08:00
|
|
|
|
|
2025-08-26 17:38:59 +08:00
|
|
|
|
final List<ConversationViewModel> convList = res.data;
|
|
|
|
|
for (var conv in convList) {
|
2025-08-27 23:26:29 +08:00
|
|
|
|
logger.w('基本会话: ${conv.conversation.toJson()}');
|
2025-08-26 17:38:59 +08:00
|
|
|
|
}
|
2025-08-27 23:26:29 +08:00
|
|
|
|
// 去重
|
|
|
|
|
// 已有会话ID集合
|
|
|
|
|
final existingIds = chatList.map((e) => e.conversation.conversationID).where((id) => id.isNotEmpty).toSet();
|
|
|
|
|
// 过滤掉已存在的会话
|
|
|
|
|
final filtered = convList.where((c) => !existingIds.contains(c.conversation.conversationID)).toList();
|
2025-07-21 15:46:30 +08:00
|
|
|
|
|
2025-08-27 23:26:29 +08:00
|
|
|
|
chatList.addAll(filtered);
|
2025-08-26 17:38:59 +08:00
|
|
|
|
// 不包含noFriend才执行加载数据逻辑,分页加载时候过滤
|
|
|
|
|
final hasNoFriend = chatList.any((item) => item.conversation.conversationGroupList?.contains(myConversationType.ConversationType.noFriend.name) ?? false);
|
2025-08-26 21:21:59 +08:00
|
|
|
|
logger.e('开始构建陌生人入口是否包含noFriend?:$hasNoFriend');
|
2025-08-26 17:38:59 +08:00
|
|
|
|
if (!hasNoFriend) {
|
|
|
|
|
getNoFriendData();
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
logger.e('获取会话异常::$e');
|
2025-08-21 10:50:38 +08:00
|
|
|
|
}
|
2025-07-21 15:46:30 +08:00
|
|
|
|
}
|
2025-08-21 10:50:38 +08:00
|
|
|
|
|
2025-09-03 11:25:31 +08:00
|
|
|
|
///构建陌生人消息菜单入口(更新时候传入对应的会话)
|
|
|
|
|
Future<void> getNoFriendData({V2TimConversation? csion}) async {
|
2025-08-21 10:50:38 +08:00
|
|
|
|
// 检测会话列表是否已有陌生人消息菜单
|
2025-09-13 17:01:01 +08:00
|
|
|
|
final hasNoFriend = chatList
|
|
|
|
|
.where((item) => item.conversation.type == 1) // 只检测单聊天 type == 1 的会话
|
|
|
|
|
.any((item) => item.isCustomAdmin?.contains(myConversationType.ConversationType.noFriend.name) ?? false);
|
2025-08-26 21:21:59 +08:00
|
|
|
|
logger.w('检测是否存在nofriend入口:$hasNoFriend');
|
2025-08-21 10:50:38 +08:00
|
|
|
|
if (hasNoFriend) {
|
|
|
|
|
// 已经有了入口
|
2025-09-03 11:25:31 +08:00
|
|
|
|
// 先检测nofriend分组是否还有数据
|
|
|
|
|
final noFriendData = await ImService.instance.getConversationListByFilter(
|
2025-08-26 21:21:59 +08:00
|
|
|
|
filter: V2TimConversationFilter(conversationGroup: myConversationType.ConversationType.noFriend.name),
|
|
|
|
|
nextSeq: 0,
|
|
|
|
|
count: 1,
|
|
|
|
|
);
|
2025-09-03 11:25:31 +08:00
|
|
|
|
if (noFriendData.success && (noFriendData.data?.conversationList?.isNotEmpty == true)) {
|
|
|
|
|
// 还存在陌生人会话数据
|
|
|
|
|
final ConversationViewModel matchItem = chatList.firstWhere(
|
|
|
|
|
(item) => item.conversation.conversationGroupList?.contains(myConversationType.ConversationType.noFriend.name) ?? false,
|
|
|
|
|
orElse: () {
|
|
|
|
|
//赋在viewmodel会话上的分组被移除
|
|
|
|
|
logger.w("没有找到符合条件的元素,执行移除逻辑");
|
|
|
|
|
return ConversationViewModel(conversation: V2TimConversation(conversationID: ''));
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
// 获取陌生人未读总数
|
|
|
|
|
final unreadTotal = await ImService.instance.getUnreadMessageCountByFilter(
|
|
|
|
|
filter: V2TimConversationFilter(
|
|
|
|
|
conversationGroup: myConversationType.ConversationType.noFriend.name,
|
|
|
|
|
hasUnreadCount: true,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
// 如果上面没找到 就是移除nofriend分组
|
|
|
|
|
if (matchItem.conversation.conversationID.isEmpty) {
|
|
|
|
|
// 执行移除更新,用最新的一条会话数据,构建viewmodel
|
|
|
|
|
await ConversationViewModel.createConversationViewModel(convList: noFriendData.data!.conversationList!);
|
|
|
|
|
} else {
|
|
|
|
|
matchItem.conversation.lastMessage = csion!.lastMessage;
|
|
|
|
|
matchItem.conversation.unreadCount = unreadTotal.data;
|
2025-08-21 10:50:38 +08:00
|
|
|
|
}
|
2025-09-03 11:25:31 +08:00
|
|
|
|
} else {
|
|
|
|
|
// 没数据,移除入口
|
|
|
|
|
chatList.removeWhere((chatItem) => chatItem.isCustomAdmin == myConversationType.ConversationType.noFriend.name);
|
2025-08-21 10:50:38 +08:00
|
|
|
|
}
|
2025-09-03 11:25:31 +08:00
|
|
|
|
|
|
|
|
|
chatList.refresh();
|
|
|
|
|
} else {
|
|
|
|
|
logger.w('构建陌生人消息入口--开始');
|
|
|
|
|
await createNoFriendMenu();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建陌生人入口
|
|
|
|
|
Future<void> createNoFriendMenu() async {
|
|
|
|
|
// 没有则执行创建逻辑
|
|
|
|
|
final res = await ImService.instance.getConversationListByFilter(
|
|
|
|
|
filter: V2TimConversationFilter(conversationGroup: myConversationType.ConversationType.noFriend.name),
|
|
|
|
|
nextSeq: 0,
|
|
|
|
|
count: 1,
|
|
|
|
|
);
|
|
|
|
|
if (res.success && res.data != null) {
|
|
|
|
|
final convList = res.data!.conversationList ?? [];
|
|
|
|
|
if (convList.isNotEmpty) {
|
|
|
|
|
// logger.i(res.data!.toJson());
|
|
|
|
|
// 有陌生人消息,1.获取未读数,2.组装converstaionviewmodel
|
|
|
|
|
final unread = await ImService.instance.getUnreadMessageCountByFilter(
|
|
|
|
|
filter: V2TimConversationFilter(
|
|
|
|
|
conversationGroup: myConversationType.ConversationType.noFriend.name,
|
|
|
|
|
hasUnreadCount: true,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (unread.success) {
|
|
|
|
|
var viewModelList = await ConversationViewModel.createConversationViewModel(convList: [convList.first]);
|
|
|
|
|
final conviewModel = viewModelList.first;
|
|
|
|
|
conviewModel.faceUrl = 'assets/images/notify/msr.png';
|
|
|
|
|
conviewModel.isCustomAdmin = myConversationType.ConversationTypeStatic.noFriend;
|
|
|
|
|
conviewModel.conversation.showName = '陌生人消息';
|
|
|
|
|
conviewModel.conversation.unreadCount = unread.data;
|
|
|
|
|
conviewModel.conversation.conversationID = myConversationType.ConversationTypeStatic.noFriend;
|
|
|
|
|
// final createItem = ConversationViewModel(
|
|
|
|
|
// conversation: conv,
|
|
|
|
|
// faceUrl: faceUrl,
|
|
|
|
|
// );
|
|
|
|
|
final newList = List<ConversationViewModel>.from(chatList);
|
|
|
|
|
newList.add(conviewModel);
|
|
|
|
|
newList.sort((a, b) {
|
|
|
|
|
final atime = a.conversation.lastMessage?.timestamp ?? 0;
|
|
|
|
|
final btime = b.conversation.lastMessage?.timestamp ?? 0;
|
|
|
|
|
return btime.compareTo(atime); // 降序
|
|
|
|
|
});
|
|
|
|
|
chatList.value = newList;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
logger.e('构建失败-----${res.desc}\n${res.data!.toJson()}');
|
2025-08-21 10:50:38 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 按会话分组查询 getConversationListByFilter
|
2025-08-26 17:38:59 +08:00
|
|
|
|
// void filterConversationList() async {
|
2025-08-21 10:50:38 +08:00
|
|
|
|
// final res = await ImService.instance.getConversationListByFilter(
|
|
|
|
|
// filter: V2TimConversationFilter(conversationGroup: null),
|
|
|
|
|
// nextSeq: nextSeq.value,
|
|
|
|
|
// );
|
|
|
|
|
// final convList = res.data!.conversationList;
|
|
|
|
|
// logger.i(res.data!.toJson());
|
|
|
|
|
// chatList.value = convList;
|
|
|
|
|
// // for (var element in convList ?? []) {
|
|
|
|
|
// // logger.i(element.toJson());
|
|
|
|
|
// // // 你可以在这里继续处理 element
|
|
|
|
|
// // }
|
|
|
|
|
// }
|
2025-07-21 15:46:30 +08:00
|
|
|
|
}
|