diff --git a/lib/im/im_manager.dart b/lib/im/im_manager.dart index 59a6050..18a7587 100644 --- a/lib/im/im_manager.dart +++ b/lib/im/im_manager.dart @@ -1743,7 +1743,7 @@ class IMManager { } // 检查是否是GIFT消息 - if (content.startsWith('[GIFT:]')) { + if (content != null && content.startsWith('[GIFT:]')) { return '[礼物]'; } @@ -1823,6 +1823,98 @@ class IMManager { } } + /// 修改消息(可同时修改消息体和消息扩展属性) + /// [messageId] 要修改的消息ID + /// [msgBody] 新的消息体(可选,如果为null则不修改消息体) + /// [attributes] 新的消息扩展属性(可选,如果为null则不修改扩展属性) + Future modifyMessage({ + required String messageId, + EMMessageBody? msgBody, + Map? attributes, + }) async { + try { + if (messageId.isEmpty) { + if (Get.isLogEnable) { + Get.log('❌ [IMManager] 消息ID为空,无法修改'); + } + return false; + } + + // 如果既没有提供消息体也没有提供扩展属性,则无法修改 + if (msgBody == null && attributes == null) { + if (Get.isLogEnable) { + Get.log('❌ [IMManager] 消息体和扩展属性都为空,无法修改'); + } + return false; + } + + // 调用SDK的修改消息方法 + await EMClient.getInstance.chatManager.modifyMessage( + messageId: messageId, + msgBody: msgBody, + attributes: attributes, + ); + + // 刷新会话列表 + _refreshConversationList(); + + // 通知对应的 ChatController 更新消息 + _notifyMessageModified(messageId, msgBody, attributes); + + return true; + } catch (e) { + if (Get.isLogEnable) { + Get.log('❌ [IMManager] 消息修改失败: messageId=$messageId, 错误: $e'); + } + return false; + } + } + + /// 通知 ChatController 消息已被修改 + void _notifyMessageModified( + String messageId, + EMMessageBody? msgBody, + Map? attributes, + ) { + try { + // 遍历所有活跃的 ChatController,查找包含该消息的控制器 + for (var entry in _activeChatControllers.entries) { + final controller = entry.value; + final index = controller.messages.indexWhere((msg) => msg.msgId == messageId); + if (index != -1) { + // 找到消息,更新它 + final message = controller.messages[index]; + + // 如果提供了新的消息体,更新消息体 + if (msgBody != null) { + // 注意:EMMessage 的 body 是只读的,需要通过重新获取消息来更新 + // 这里我们更新消息的扩展属性,消息体需要通过重新获取消息来更新 + if (Get.isLogEnable) { + Get.log('⚠️ [IMManager] 消息体修改需要重新获取消息: messageId=$messageId'); + } + } + + // 如果提供了新的扩展属性,更新扩展属性 + if (attributes != null) { + message.attributes ??= {}; + message.attributes!.addAll(attributes); + } + + // 通知UI更新 + controller.update(); + + if (Get.isLogEnable) { + Get.log('✅ [IMManager] 已通知ChatController更新消息: userId=${entry.key}, messageId=$messageId'); + } + } + } + } catch (e) { + if (Get.isLogEnable) { + Get.log('⚠️ [IMManager] 通知ChatController消息修改失败: $e'); + } + } + } + /// 撤回消息 Future recallMessage(EMMessage message) async { try { diff --git a/lib/main.dart b/lib/main.dart index a3e2bc0..15a5e4b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,6 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:fluwx/fluwx.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; -import 'package:ota_update/ota_update.dart'; import 'extension/my_cupertino_localizations.dart'; @@ -206,27 +205,36 @@ class _MyAppState extends State { } - /// 检查是否已同意用户协议 + /// 检查是否已同意用户协议(只在第一次安装时显示) void _checkAgreement() { final storage = GetStorage(); + // 检查是否已经同意过协议,如果已同意则不显示弹框 final hasAgreed = storage.read('hasAgreedUserAgreement') ?? false; if (!hasAgreed) { - // 延迟显示弹框,确保UI已初始化 + // 第一次安装,延迟显示弹框,确保UI已初始化 WidgetsBinding.instance.addPostFrameCallback((_) { - setState(() { - _showAgreementDialog = true; - }); + if (mounted) { + setState(() { + _showAgreementDialog = true; + }); + } }); + } else { + // 已经同意过协议,不显示弹框 + _showAgreementDialog = false; } } - /// 处理同意协议 + /// 处理同意协议(保存同意状态,确保下次不再显示) void _onAgreeAgreement() { final storage = GetStorage(); + // 保存用户已同意协议的状态,确保只在第一次安装时显示 storage.write('hasAgreedUserAgreement', true); - setState(() { - _showAgreementDialog = false; - }); + if (mounted) { + setState(() { + _showAgreementDialog = false; + }); + } } /// 处理不同意协议 - 退出应用 diff --git a/lib/pages/discover/live_room_page.dart b/lib/pages/discover/live_room_page.dart index bfaa61b..edb665a 100644 --- a/lib/pages/discover/live_room_page.dart +++ b/lib/pages/discover/live_room_page.dart @@ -46,8 +46,10 @@ class _LiveRoomPageState extends State { ? Get.find() : Get.put(RoomController()); _overlayController = Get.find(); - // 进入直播间时,确保隐藏小窗口 - _overlayController.hide(); + // 进入直播间时,确保隐藏小窗口(延迟到 build 完成后执行,避免在 build 过程中触发 setState) + WidgetsBinding.instance.addPostFrameCallback((_) { + _overlayController.hide(); + }); // 启用屏幕常亮 WakelockPlus.enable(); // 如果当前用户是男性,请求连麦卡片信息