diff --git a/lib/controller/discover/room_controller.dart b/lib/controller/discover/room_controller.dart index f790ad5..5e31248 100644 --- a/lib/controller/discover/room_controller.dart +++ b/lib/controller/discover/room_controller.dart @@ -79,6 +79,8 @@ class RoomController extends GetxController with WidgetsBindingObserver { WidgetsBinding.instance.removeObserver(this); // 移除消息监听 _messageService.unregisterMessageListener(); + // 清空RTM消息列表 + chatMessages.clear(); } /// 注册消息监听 @@ -348,6 +350,8 @@ class RoomController extends GetxController with WidgetsBindingObserver { } currentRole = CurrentRole.normalUser; await RTCManager.instance.leaveChannel(); + // 清空RTM消息列表 + chatMessages.clear(); } /// 加载礼物产品列表 diff --git a/lib/controller/message/conversation_controller.dart b/lib/controller/message/conversation_controller.dart index 34a6c3d..73b414c 100644 --- a/lib/controller/message/conversation_controller.dart +++ b/lib/controller/message/conversation_controller.dart @@ -411,6 +411,11 @@ class ConversationController extends GetxController { } } + // 检查是否是GIFT消息 + if (content != null && content.startsWith('[GIFT:]')) { + return '[礼物]'; + } + return content ?? ''; }else if(message.body.type == MessageType.IMAGE){ return '[图片]'; diff --git a/lib/im/im_manager.dart b/lib/im/im_manager.dart index b2b56ed..1940974 100644 --- a/lib/im/im_manager.dart +++ b/lib/im/im_manager.dart @@ -1569,6 +1569,11 @@ class IMManager { } } + // 检查是否是GIFT消息 + if (content != null && content.startsWith('[GIFT:]')) { + return '[礼物]'; + } + return content ?? ''; } else if (message.body.type == MessageType.IMAGE) { return '[图片]'; diff --git a/lib/pages/discover/live_room_page.dart b/lib/pages/discover/live_room_page.dart index 4626d73..301e7de 100644 --- a/lib/pages/discover/live_room_page.dart +++ b/lib/pages/discover/live_room_page.dart @@ -54,6 +54,11 @@ class _LiveRoomPageState extends State { // 禁用屏幕常亮 WakelockPlus.disable(); _messageController.dispose(); + // 退出房间时清空RTM消息 + if (Get.isRegistered()) { + final roomController = Get.find(); + roomController.chatMessages.clear(); + } super.dispose(); } @@ -108,6 +113,11 @@ class _LiveRoomPageState extends State { return PopScope( onPopInvokedWithResult: (bool didPop, Object? result) async { SmartDialog.dismiss(); + // 退出房间时清空RTM消息 + if (Get.isRegistered()) { + final roomController = Get.find(); + roomController.chatMessages.clear(); + } _overlayController.show(); Get.back(); }, diff --git a/lib/pages/main/main_page.dart b/lib/pages/main/main_page.dart index 8a60f11..61f874c 100644 --- a/lib/pages/main/main_page.dart +++ b/lib/pages/main/main_page.dart @@ -103,17 +103,17 @@ class _MainPageState extends State { final unreadCount = controller.totalUnreadCount.value; return TDBottomTabBar( - currentIndex: currentIndex, - TDBottomTabBarBasicType.iconText, - componentType: TDBottomTabBarComponentType.normal, - useVerticalDivider: false, - navigationTabs: [ - tabItem('首页', Assets.imagesHomePre, Assets.imagesHomeNol, 0), - tabItem('找对象', Assets.imagesDiscoverPre, Assets.imagesDiscoverNol, 1), + currentIndex: currentIndex, + TDBottomTabBarBasicType.iconText, + componentType: TDBottomTabBarComponentType.normal, + useVerticalDivider: false, + navigationTabs: [ + tabItem('首页', Assets.imagesHomePre, Assets.imagesHomeNol, 0), + tabItem('找对象', Assets.imagesDiscoverPre, Assets.imagesDiscoverNol, 1), tabItemWithBadge('消息', Assets.imagesMessagePre, Assets.imagesMessageNol, 2, unreadCount), - tabItem('我的', Assets.imagesMinePre, Assets.imagesMineNol, 3), - ] - ); + tabItem('我的', Assets.imagesMinePre, Assets.imagesMineNol, 3), + ] + ); }); } diff --git a/lib/widget/live/live_gift_popup.dart b/lib/widget/live/live_gift_popup.dart index e5eebd9..1e6c37b 100644 --- a/lib/widget/live/live_gift_popup.dart +++ b/lib/widget/live/live_gift_popup.dart @@ -76,11 +76,18 @@ class _LiveGiftPopupState extends State { } // 检查是否选中了接收用户(如果showHeader为false,则必须有targetUserId) - if (_selectedUserId == 0) { - if (widget.showHeader) { + if (widget.showHeader) { + // 如果显示头部,需要检查是否选中了用户 + if (_selectedUserId == null || _selectedUserId == 0) { SmartDialog.showToast('请先选择接收礼物的用户'); + return; + } + } else { + // 如果不显示头部,应该使用targetUserId,但如果targetUserId也没有,则检查_selectedUserId + if (widget.targetUserId == null && (_selectedUserId == null || _selectedUserId == 0)) { + SmartDialog.showToast('请先选择接收礼物的用户'); + return; } - return; } // 获取选中的礼物 @@ -133,7 +140,6 @@ class _LiveGiftPopupState extends State { ), child: Column( children: [ - _buildTab(), _buildGiftSwiper(), _buildBottomBar(), ], @@ -303,33 +309,6 @@ class _LiveGiftPopupState extends State { }); } - Widget _buildTab() { - return Container( - height: 47.w, - padding: EdgeInsets.only(left: 29.w), - child: Row( - children: [ - Text( - "互动", - style: TextStyle( - fontSize: 13.w, - color: const Color.fromRGBO(144, 144, 144, 1), - ), - ), - SizedBox(width: 40.w), - Text( - "礼物", - style: TextStyle( - fontSize: 13.w, - color: Colors.white, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ); - } - Widget _buildGiftSwiper() { if (widget.giftList.isEmpty) { return Expanded( @@ -370,57 +349,77 @@ class _LiveGiftPopupState extends State { } Widget _buildBottomBar() { - return Container( - padding: EdgeInsets.symmetric(horizontal: 10.w), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Image.asset(Assets.imagesRoseGift, width: 21.w, height: 21.w), - SizedBox(width: 8.w), - Text( - "9", - style: TextStyle(fontSize: 13.w, color: Colors.white), - ), - SizedBox(width: 12.w), - Image.asset(Assets.imagesRoseGift, width: 68.w, height: 33.w), - ], - ), - ValueListenableBuilder( - valueListenable: widget.giftNum, - builder: (context, num, _) { - return Row( - children: [ - GestureDetector( - onTap: () => _handleSendGift(widget.type ?? 0), - child: Container( - width: 63.w, - height: 30.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(30.w)), - gradient: const LinearGradient( - begin: Alignment.centerLeft, - end: Alignment.centerRight, - colors: [ - Color.fromRGBO(61, 138, 224, 1), - Color.fromRGBO(131, 89, 255, 1), - ], - ), - ), - child: Center( - child: Text( - "赠送", - style: TextStyle(fontSize: 13.w, color: Colors.white), + return SafeArea( + top: false, + child: Container( + padding: EdgeInsets.only( + left: 10.w, + right: 10.w, + bottom: MediaQuery.of(context).padding.bottom > 0 + ? MediaQuery.of(context).padding.bottom + : 10.h, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Image.asset(Assets.imagesRoseGift, width: 21.w, height: 21.w), + SizedBox(width: 8.w), + Text( + "9", + style: TextStyle(fontSize: 13.w, color: Colors.white), + ), + SizedBox(width: 12.w), + ], + ), + // 判断是否可以选择赠送(如果showHeader为true,需要选中用户;如果为false,直接使用targetUserId) + Builder( + builder: (context) { + final bool canSend = widget.showHeader + ? (_selectedUserId != null && _selectedUserId! > 0) + : (widget.targetUserId != null || _selectedUserId != null); + + return Row( + children: [ + GestureDetector( + onTap: canSend ? () => _handleSendGift(widget.type ?? 0) : null, + child: Opacity( + opacity: canSend ? 1.0 : 0.5, + child: Container( + width: 63.w, + height: 30.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(30.w)), + gradient: canSend + ? const LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color.fromRGBO(61, 138, 224, 1), + Color.fromRGBO(131, 89, 255, 1), + ], + ) + : null, + color: canSend + ? null + : Colors.grey.withOpacity(0.5), + ), + child: Center( + child: Text( + "赠送", + style: TextStyle(fontSize: 13.w, color: Colors.white), + ), + ), ), ), ), - ), - ], - ); - }, - ), - ], + ], + ); + }, + ), + ], + ), ), ); } diff --git a/lib/widget/live/live_room_action_bar.dart b/lib/widget/live/live_room_action_bar.dart index 459691d..05d01c9 100644 --- a/lib/widget/live/live_room_action_bar.dart +++ b/lib/widget/live/live_room_action_bar.dart @@ -79,25 +79,25 @@ class LiveRoomActionBar extends StatelessWidget { ), ), SizedBox(width: 8.w), - InkWell( - onTap: onSendTap, - child: Container( - width: 38.w, - height: 38.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(38.w)), - color: const Color.fromRGBO(0, 0, 0, .3), - ), - child: Center( - child: Image.asset( - Assets.imagesArrowR, - width: 16.w, - height: 16.w, - ), - ), - ), - ), - SizedBox(width: 8.w), + // InkWell( + // onTap: onSendTap, + // child: Container( + // width: 38.w, + // height: 38.w, + // decoration: BoxDecoration( + // borderRadius: BorderRadius.all(Radius.circular(38.w)), + // color: const Color.fromRGBO(0, 0, 0, .3), + // ), + // child: Center( + // child: Image.asset( + // Assets.imagesArrowR, + // width: 16.w, + // height: 16.w, + // ), + // ), + // ), + // ), + // SizedBox(width: 8.w), InkWell( onTap: onChargeTap, child: Container( diff --git a/lib/widget/live/live_room_guest_list_dialog.dart b/lib/widget/live/live_room_guest_list_dialog.dart index 4fbd570..116644c 100644 --- a/lib/widget/live/live_room_guest_list_dialog.dart +++ b/lib/widget/live/live_room_guest_list_dialog.dart @@ -626,13 +626,15 @@ class _LiveRoomGuestListDialogState extends State { // 获取房间详情 final channelDetail = roomController.rtcChannelDetail.value; final anchorName = channelDetail?.anchorInfo?.nickName ?? '主持人'; + final anchorAvatar = channelDetail?.anchorInfo?.profilePhoto ?? ''; // 构建消息体,包含房间信息 final messageData = { 'type': 'live_room_invite', 'channelId': channelId, - 'anchorAvatar': channelDetail?.anchorInfo?.profilePhoto ?? '', + 'anchorAvatar': anchorAvatar, 'anchorName': anchorName, + 'coverImage': anchorAvatar, // 封面使用主持人头像 }; // 发送自定义消息 diff --git a/lib/widget/message/chat_gift_popup.dart b/lib/widget/message/chat_gift_popup.dart index cf96214..f000fea 100644 --- a/lib/widget/message/chat_gift_popup.dart +++ b/lib/widget/message/chat_gift_popup.dart @@ -136,47 +136,56 @@ class _ChatGiftPopupState extends State { } Widget _buildBottomBar() { - return Container( - padding: EdgeInsets.symmetric(horizontal: 10.w), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - // 数量选择(暂时不实现,固定为1) - SizedBox(width: 1.w), - ValueListenableBuilder( - valueListenable: widget.giftNum, - builder: (context, num, _) { - return Row( - children: [ - GestureDetector( - onTap: () => _handleSendGift(), - child: Container( - width: 63.w, - height: 30.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(30.w)), - gradient: const LinearGradient( - begin: Alignment.centerLeft, - end: Alignment.centerRight, - colors: [ - Color.fromRGBO(61, 138, 224, 1), - Color.fromRGBO(131, 89, 255, 1), - ], + return SafeArea( + top: false, + child: Container( + padding: EdgeInsets.only( + left: 10.w, + right: 10.w, + bottom: MediaQuery.of(context).padding.bottom > 0 + ? MediaQuery.of(context).padding.bottom + : 10.h, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // 数量选择(暂时不实现,固定为1) + SizedBox(width: 1.w), + ValueListenableBuilder( + valueListenable: widget.giftNum, + builder: (context, num, _) { + return Row( + children: [ + GestureDetector( + onTap: () => _handleSendGift(), + child: Container( + width: 63.w, + height: 30.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(30.w)), + gradient: const LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color.fromRGBO(61, 138, 224, 1), + Color.fromRGBO(131, 89, 255, 1), + ], + ), ), - ), - child: Center( - child: Text( - "赠送", - style: TextStyle(fontSize: 13.w, color: Colors.white), + child: Center( + child: Text( + "赠送", + style: TextStyle(fontSize: 13.w, color: Colors.white), + ), ), ), ), - ), - ], - ); - }, - ), - ], + ], + ); + }, + ), + ], + ), ), ); } diff --git a/lib/widget/message/room_item.dart b/lib/widget/message/room_item.dart index b38c693..4c63705 100644 --- a/lib/widget/message/room_item.dart +++ b/lib/widget/message/room_item.dart @@ -8,6 +8,9 @@ import '../../generated/assets.dart'; import '../../controller/discover/room_controller.dart'; import '../../controller/global.dart'; import '../../controller/message/chat_controller.dart'; +import '../../controller/overlay_controller.dart'; +import '../../rtc/rtc_manager.dart'; +import '../../pages/discover/live_room_page.dart'; class RoomItem extends StatelessWidget { final EMMessage message; @@ -32,11 +35,13 @@ class RoomItem extends StatelessWidget { final customBody = message.body as EMCustomMessageBody; // 检查是否是直播间邀请消息 if (customBody.event == 'live_room_invite') { - return customBody.params; + final params = customBody.params; + print('📋 [RoomItem] 解析到的房间信息: $params'); + return params; } } } catch (e) { - print('解析房间信息失败: $e'); + print('❌ [RoomItem] 解析房间信息失败: $e'); } return null; } @@ -56,21 +61,58 @@ class RoomItem extends StatelessWidget { /// 获取主持人头像 String _getAnchorAvatar() { final roomInfo = _parseRoomInfo(); - return roomInfo?['anchorAvatar'] ?? ''; + final avatar = roomInfo?['anchorAvatar'] ?? ''; + // 清理头像URL(移除反引号) + return avatar.trim().replaceAll('`', ''); + } + + /// 获取封面图片(如果有的话,否则使用头像) + String _getCoverImage() { + final roomInfo = _parseRoomInfo(); + // 优先使用封面图片,如果没有则使用头像 + final coverImage = roomInfo?['anchorAvatar'] ?? ''; + return coverImage.trim().replaceAll('`', ''); } /// 处理点击事件 - void _handleTap() async{ + void _handleTap() async { final channelId = _getChannelId(); - if (channelId.isNotEmpty) { - // 获取 RoomController 并加入频道 - final roomController = Get.isRegistered() - ? Get.find() - : Get.put(RoomController()); - - // 加入频道并跳转 - await roomController.joinChannel(channelId); + if (channelId.isEmpty) { + return; + } + + // 获取当前直播间ID + final currentChannelId = RTCManager.instance.currentChannelId; + + // 隐藏小窗口 + if (Get.isRegistered()) { + final overlayController = Get.find(); + overlayController.hide(); + } + + // 获取 RoomController + final roomController = Get.isRegistered() + ? Get.find() + : Get.put(RoomController()); + + // 如果频道ID一致,取消小窗口并进入直播间 + if (currentChannelId != null && currentChannelId == channelId) { + // 如果当前不在 LiveRoomPage,则导航到 LiveRoomPage + final currentRoute = Get.currentRoute; + if (currentRoute != '/LiveRoomPage' && !currentRoute.contains('LiveRoomPage')) { + Get.to(() => const LiveRoomPage(id: 0)); + } + return; + } + + // 如果不一致,退出当前直播间并进入新的直播间 + if (currentChannelId != null && currentChannelId.isNotEmpty) { + // 退出当前直播间 + await roomController.leaveChannel(); } + + // 加入新的直播间 + await roomController.joinChannel(channelId); } @override @@ -82,6 +124,7 @@ class RoomItem extends StatelessWidget { final anchorName = _getAnchorName(); final anchorAvatar = _getAnchorAvatar(); + final coverImage = _getAnchorAvatar(); return Column( children: [ @@ -134,11 +177,15 @@ class RoomItem extends StatelessWidget { width: 150.w, height: 150.w, color: Colors.grey[200], - child: anchorAvatar.isNotEmpty + child: coverImage.isNotEmpty ? CachedNetworkImage( - imageUrl: anchorAvatar, + imageUrl: coverImage, + width: 150.w, + height: 150.w, fit: BoxFit.cover, placeholder: (context, url) => Container( + width: 150.w, + height: 150.w, color: Colors.grey[200], child: Center( child: CircularProgressIndicator( @@ -147,15 +194,19 @@ class RoomItem extends StatelessWidget { ), ), ), - errorWidget: (context, url, error) => - Container( - color: Colors.grey[200], - child: Icon( - Icons.live_tv, - size: 40.w, - color: Colors.grey[400], - ), - ), + errorWidget: (context, url, error) { + print('❌ [RoomItem] 封面图片加载失败: $url, error: $error'); + return Container( + width: 150.w, + height: 150.w, + color: Colors.grey[200], + child: Icon( + Icons.live_tv, + size: 40.w, + color: Colors.grey[400], + ), + ); + }, ) : Container( color: Colors.grey[200], @@ -189,7 +240,7 @@ class RoomItem extends StatelessWidget { ), SizedBox(width: 4.w), Text( - '直播中', + '直播间', style: TextStyle( fontSize: 11.sp, color: Colors.white, @@ -214,36 +265,38 @@ class RoomItem extends StatelessWidget { color: Colors.grey[300], child: anchorAvatar.isNotEmpty ? CachedNetworkImage( - imageUrl: anchorAvatar, - width: 24.w, - height: 24.w, - fit: BoxFit.cover, - placeholder: (context, url) => - Container( - color: Colors.grey[300], - child: Center( - child: SizedBox( - width: 12.w, - height: 12.w, - child: CircularProgressIndicator( - strokeWidth: 2, - color: Colors.grey[600], + imageUrl: anchorAvatar, + width: 24.w, + height: 24.w, + fit: BoxFit.cover, + placeholder: (context, url) => + Container( + color: Colors.grey[300], + child: Center( + child: SizedBox( + width: 12.w, + height: 12.w, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.grey[600], + ), + ), + ), ), - ), - ), - ), - errorWidget: (context, url, error) => - Icon( - Icons.person, - size: 16.w, - color: Colors.grey[600], + errorWidget: (context, url, error) => + Image.asset( + Assets.imagesUserAvatar, + width: 24.w, + height: 24.w, + fit: BoxFit.cover, + ), + ) + : Image.asset( + Assets.imagesUserAvatar, + width: 24.w, + height: 24.w, + fit: BoxFit.cover, ), - ) - : Icon( - Icons.person, - size: 16.w, - color: Colors.grey[600], - ), ), ), SizedBox(width: 5.w),