2025-07-21 15:46:30 +08:00
|
|
|
|
import 'package:get/get.dart';
|
|
|
|
|
import 'package:loopin/IM/controller/chat_controller.dart';
|
|
|
|
|
import 'package:loopin/IM/controller/tab_bar_controller.dart';
|
2025-08-21 10:50:38 +08:00
|
|
|
|
import 'package:loopin/IM/im_service.dart';
|
|
|
|
|
import 'package:loopin/models/conversation_type.dart';
|
2025-08-27 23:26:29 +08:00
|
|
|
|
import 'package:loopin/models/conversation_view_model.dart';
|
2025-07-21 15:46:30 +08:00
|
|
|
|
import 'package:loopin/models/tab_type.dart';
|
2025-08-27 23:26:29 +08:00
|
|
|
|
import 'package:loopin/pages/chat/notify_controller/notify_no_friend_controller.dart';
|
2025-07-21 15:46:30 +08:00
|
|
|
|
import 'package:tencent_cloud_chat_sdk/enum/V2TimConversationListener.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
|
|
|
|
import 'package:tencent_cloud_chat_sdk/tencent_im_sdk_plugin.dart';
|
|
|
|
|
|
|
|
|
|
class GlobalBadge extends GetxController {
|
|
|
|
|
/// 全局未读消息总数
|
|
|
|
|
RxInt totalUnread = 0.obs;
|
|
|
|
|
|
|
|
|
|
/// 监听器对象(用于 add/remove)
|
|
|
|
|
late final V2TimConversationListener _listener;
|
|
|
|
|
|
2025-08-26 17:38:59 +08:00
|
|
|
|
void rest() {
|
|
|
|
|
totalUnread.value = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-21 15:46:30 +08:00
|
|
|
|
@override
|
|
|
|
|
void onInit() {
|
|
|
|
|
super.onInit();
|
|
|
|
|
_listener = V2TimConversationListener(
|
|
|
|
|
onTotalUnreadMessageCountChanged: (int count) {
|
|
|
|
|
logger.i('未读数发生变化$count');
|
|
|
|
|
totalUnread.value = count;
|
|
|
|
|
Get.find<TabBarController>().setBadge(TabType.chat, totalUnread.value);
|
2025-08-21 10:50:38 +08:00
|
|
|
|
},
|
|
|
|
|
onNewConversation: (List<V2TimConversation> conversationList) {
|
|
|
|
|
for (var conv in conversationList) {
|
2025-08-27 23:26:29 +08:00
|
|
|
|
logger.e('新创建会话:${conv.toLogString()}');
|
|
|
|
|
logger.i("新会话分组类型:${conv.conversationGroupList}");
|
2025-08-21 10:50:38 +08:00
|
|
|
|
handleCoverstion(conv);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onConversationChanged: (List<V2TimConversation> conversationList) async {
|
|
|
|
|
logger.w('会话变更:会话分组:${conversationList.first.conversationGroupList},会话内容${conversationList.first.toLogString()}');
|
|
|
|
|
final ctl = Get.find<ChatController>();
|
2025-08-26 21:21:59 +08:00
|
|
|
|
logger.w('当前会话列表内容:${ctl.chatList.length}');
|
2025-08-26 17:38:59 +08:00
|
|
|
|
|
2025-08-21 10:50:38 +08:00
|
|
|
|
final updatedIds = conversationList.map((e) => e.conversationID).toSet();
|
|
|
|
|
logger.w('要变更的会话id:$updatedIds');
|
2025-08-27 23:26:29 +08:00
|
|
|
|
// 收集可能存在后续分页的会话
|
|
|
|
|
final List<V2TimConversation> willInsert = <V2TimConversation>[];
|
2025-08-21 10:50:38 +08:00
|
|
|
|
for (int i = 0; i < ctl.chatList.length; i++) {
|
|
|
|
|
final chatItem = ctl.chatList[i];
|
|
|
|
|
logger.w('需要更新的ID:${chatItem.conversation.conversationID}');
|
|
|
|
|
if (updatedIds.contains(chatItem.conversation.conversationID)) {
|
2025-08-26 17:38:59 +08:00
|
|
|
|
logger.w('找到的chatList的ID:${chatItem.conversation.conversationID}');
|
|
|
|
|
|
2025-08-21 10:50:38 +08:00
|
|
|
|
final updatedConv = conversationList.firstWhere(
|
|
|
|
|
(c) => c.conversationID == chatItem.conversation.conversationID,
|
|
|
|
|
orElse: () => V2TimConversation(conversationID: ''),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (updatedConv.conversationID != '' && (updatedConv.conversationGroupList?.contains(ConversationType.noFriend.name) ?? false)) {
|
|
|
|
|
// 单独处理陌生人会话
|
|
|
|
|
final unread = await ImService.instance.getUnreadMessageCountByFilter(
|
|
|
|
|
filter: V2TimConversationFilter(
|
|
|
|
|
conversationGroup: ConversationType.noFriend.name,
|
|
|
|
|
hasUnreadCount: true,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
chatItem.conversation.lastMessage = updatedConv.lastMessage;
|
|
|
|
|
chatItem.conversation.unreadCount = unread.data; // 获取陌生人未读总数
|
|
|
|
|
} else {
|
|
|
|
|
// 其他类型统一更新处理
|
2025-08-26 17:38:59 +08:00
|
|
|
|
logger.w('不需要分组的会话,正常更新');
|
2025-08-21 10:50:38 +08:00
|
|
|
|
chatItem.conversation = updatedConv;
|
2025-08-26 17:38:59 +08:00
|
|
|
|
update();
|
2025-08-21 10:50:38 +08:00
|
|
|
|
}
|
2025-08-27 23:26:29 +08:00
|
|
|
|
} else {
|
|
|
|
|
logger.e('会话列表中不包含的会话:$updatedIds');
|
|
|
|
|
for (var cvID in updatedIds) {
|
|
|
|
|
// 检测这条会话数据是否存在,如果存在说明在后面的分页中,不存在则是被删除不处理
|
|
|
|
|
final isReal = await ImService.instance.getConversation(conversationID: cvID);
|
|
|
|
|
final V2TimConversation realConv = isReal.data;
|
|
|
|
|
if (isReal.success) {
|
|
|
|
|
if (realConv.conversationID.isNotEmpty) {
|
|
|
|
|
// 陌生人会话列表单独处理
|
|
|
|
|
if (Get.isRegistered<NotifyNoFriendController>()) {
|
|
|
|
|
final notifyCtl = Get.find<NotifyNoFriendController>();
|
|
|
|
|
notifyCtl.updateLastMsg(conversation: realConv);
|
|
|
|
|
} else {
|
|
|
|
|
// 收集要插入的数据
|
|
|
|
|
if (realConv.conversationGroupList?.isEmpty ?? false) {
|
|
|
|
|
willInsert.add(realConv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-21 10:50:38 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-27 23:26:29 +08:00
|
|
|
|
// 添加收集的数据,别忘了分页获取的去重
|
|
|
|
|
if (willInsert.isNotEmpty) {
|
|
|
|
|
var viewModelList = await ConversationViewModel.createConversationViewModel(convList: willInsert);
|
|
|
|
|
ctl.chatList.insertAll(0, viewModelList);
|
|
|
|
|
}
|
2025-08-26 17:38:59 +08:00
|
|
|
|
// 如果没当前会话列表为空
|
|
|
|
|
if (ctl.chatList.isEmpty) {
|
|
|
|
|
// 重新获取一次
|
|
|
|
|
logger.w('重新获取会话');
|
|
|
|
|
ctl.initChatData();
|
|
|
|
|
ctl.getConversationList();
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-21 10:50:38 +08:00
|
|
|
|
//重新排序
|
|
|
|
|
ctl.chatList.sort((a, b) {
|
|
|
|
|
final atime = a.conversation.lastMessage?.timestamp ?? 0;
|
|
|
|
|
final btime = b.conversation.lastMessage?.timestamp ?? 0;
|
|
|
|
|
return btime.compareTo(atime); // 降序
|
|
|
|
|
});
|
|
|
|
|
ctl.chatList.refresh();
|
2025-07-21 15:46:30 +08:00
|
|
|
|
},
|
|
|
|
|
);
|
2025-08-26 21:21:59 +08:00
|
|
|
|
// final ctl = Get.find<ChatController>();
|
|
|
|
|
// ctl.getConversationList();
|
2025-07-21 15:46:30 +08:00
|
|
|
|
_initUnreadCount();
|
|
|
|
|
_addListener();
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-21 10:50:38 +08:00
|
|
|
|
// final rr = await ImService.instance.deleteConversationsFromGroup(
|
|
|
|
|
// conversationIDList: [cov.conversationID],
|
|
|
|
|
// groupName: 'noFriend',
|
|
|
|
|
// );
|
|
|
|
|
// logger.w(rr.desc);
|
|
|
|
|
|
|
|
|
|
/// 新建会话时候,根据消息的自定义属性给会话分组
|
|
|
|
|
void handleCoverstion(V2TimConversation cov) async {
|
|
|
|
|
final message = cov.lastMessage;
|
|
|
|
|
final isSelfSend = message!.isSelf; // 是否本人发送的消息
|
|
|
|
|
final typeEnum = conversationTypeFromString(message.cloudCustomData); // 会话类型
|
|
|
|
|
final needAdd = cov.conversationGroupList!.isEmpty == true; // 当前会话是否已加入了分组中
|
|
|
|
|
if (typeEnum != null && needAdd && isSelfSend == false) {
|
|
|
|
|
logger.i('当前会话的类型要加入的组是:$typeEnum');
|
|
|
|
|
// 当前会话需要进行分组,检测 组 是否存在
|
|
|
|
|
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: ['c2c_${message.sender}'],
|
|
|
|
|
);
|
|
|
|
|
logger.i('首次创建会话分组$typeEnum');
|
|
|
|
|
} else {
|
|
|
|
|
// 分组存在直接添加
|
|
|
|
|
await ImService.instance.addConversationsToGroup(
|
|
|
|
|
groupName: typeEnum,
|
|
|
|
|
conversationIDList: ['c2c_${message.sender}'],
|
|
|
|
|
);
|
|
|
|
|
logger.i('添加会话分组$typeEnum成功');
|
|
|
|
|
}
|
|
|
|
|
if (typeEnum == ConversationType.noFriend.name) {
|
|
|
|
|
//陌生人分组特殊处理 满足分组条件且已经有分组,
|
|
|
|
|
final ctl = Get.find<ChatController>();
|
|
|
|
|
// 这个方法执行的逻辑:已有则刷新菜单入口数据,没有则创建菜单入口
|
|
|
|
|
ctl.getNoFriendData(csion: cov);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2025-08-26 17:38:59 +08:00
|
|
|
|
logger.w('新会话不需分组');
|
2025-08-21 10:50:38 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-21 15:46:30 +08:00
|
|
|
|
/// 初始化时获取一次未读总数
|
|
|
|
|
void _initUnreadCount() async {
|
|
|
|
|
final res = await TencentImSDKPlugin.v2TIMManager.getConversationManager().getTotalUnreadMessageCount();
|
|
|
|
|
if (res.code == 0) {
|
|
|
|
|
totalUnread.value = res.data ?? 0;
|
|
|
|
|
Get.find<TabBarController>().setBadge(TabType.chat, totalUnread.value);
|
|
|
|
|
final to = res.data;
|
|
|
|
|
logger.i('初始化未读消息数$to');
|
2025-08-26 17:38:59 +08:00
|
|
|
|
} else {
|
|
|
|
|
//处理安卓端重新登录后获取未读数量失败的问题
|
|
|
|
|
logger.e('获取初始化未读数失败:${res.desc},重新补偿获取');
|
|
|
|
|
Future.delayed(Duration(seconds: 1), handAndroid);
|
2025-07-21 15:46:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-26 17:38:59 +08:00
|
|
|
|
/// 处理安卓端异常的问题
|
|
|
|
|
handAndroid() {
|
|
|
|
|
_initUnreadCount();
|
|
|
|
|
final ctl = Get.find<ChatController>();
|
|
|
|
|
ctl.initChatData();
|
|
|
|
|
ctl.getConversationList();
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-21 15:46:30 +08:00
|
|
|
|
/// 添加会话未读数监听器
|
|
|
|
|
void _addListener() {
|
|
|
|
|
TencentImSDKPlugin.v2TIMManager.getConversationManager().addConversationListener(listener: _listener);
|
|
|
|
|
logger.i('未读数监听器注册成功');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 手动更新total
|
|
|
|
|
Future<void> refreshUnreadCount() async {
|
|
|
|
|
_initUnreadCount();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 移除监听器,防止重复注册
|
|
|
|
|
@override
|
|
|
|
|
void onClose() {
|
2025-08-26 17:38:59 +08:00
|
|
|
|
logger.i(_listener);
|
|
|
|
|
logger.i('移除global未读监听器');
|
2025-07-21 15:46:30 +08:00
|
|
|
|
TencentImSDKPlugin.v2TIMManager.getConversationManager().removeConversationListener(listener: _listener);
|
|
|
|
|
super.onClose();
|
|
|
|
|
}
|
|
|
|
|
}
|