diff --git a/lib/controller/discover/room_controller.dart b/lib/controller/discover/room_controller.dart index 7fd2931..d70e2b0 100644 --- a/lib/controller/discover/room_controller.dart +++ b/lib/controller/discover/room_controller.dart @@ -25,6 +25,7 @@ class RoomController extends GetxController { final NetworkService _networkService; CurrentRole currentRole = CurrentRole.normalUser; + bool isLive = false; /// 当前频道信息 final Rxn rtcChannel = Rxn(); final Rxn rtcChannelDetail = Rxn(); @@ -98,6 +99,7 @@ class RoomController extends GetxController { if (base.isSuccess && base.data != null) { rtcChannel.value = base.data; currentRole = CurrentRole.broadcaster; + isLive = true; await _joinRtcChannel( base.data!.token, base.data!.channelId, @@ -169,6 +171,17 @@ class RoomController extends GetxController { }else{ await RTCManager.instance.publishAudio(); } + isLive = true; + } + + Future leaveChat() async { + final data = { + 'channelId': rtcChannel.value?.channelId + }; + final response = await _networkService.rtcApi.disconnectRtcChannel(data); + if(response.data.isSuccess){ + await RTCManager.instance.unpublish(); + } } Future _fetchRtcChannelDetail(String channelName) async { diff --git a/lib/rtc/rtc_manager.dart b/lib/rtc/rtc_manager.dart index 4607895..ad99562 100644 --- a/lib/rtc/rtc_manager.dart +++ b/lib/rtc/rtc_manager.dart @@ -497,6 +497,7 @@ class RTCManager { ); } + /// 发布音频 Future publishAudio() async { await _engine?.setClientRole(role: ClientRoleType.clientRoleBroadcaster); await _engine?.muteLocalAudioStream(false); @@ -510,4 +511,18 @@ class RTCManager { }), ); } + + /// 取消发布视频 + Future unpublish() async { + await _engine?.setClientRole(role: ClientRoleType.clientRoleAudience); + await _engine?.muteLocalAudioStream(true); + await _engine?.muteLocalVideoStream(true); + await RTMManager.instance.publishChannelMessage( + channelName: _currentChannelId ?? '', + message: json.encode({ + 'type': 'leave_chat', + 'uid': _currentUid, + }), + ); + } } diff --git a/lib/widget/live/live_room_anchor_showcase.dart b/lib/widget/live/live_room_anchor_showcase.dart index 90bc023..4073fa1 100644 --- a/lib/widget/live/live_room_anchor_showcase.dart +++ b/lib/widget/live/live_room_anchor_showcase.dart @@ -1,8 +1,12 @@ import 'package:agora_rtc_engine/agora_rtc_engine.dart'; +import 'package:dating_touchme_app/controller/discover/room_controller.dart'; +import 'package:dating_touchme_app/controller/global.dart'; import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:dating_touchme_app/model/rtc/rtc_channel_detail.dart'; import 'package:dating_touchme_app/rtc/rtc_manager.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; class LiveRoomAnchorShowcase extends StatefulWidget { const LiveRoomAnchorShowcase({super.key}); @@ -13,6 +17,7 @@ class LiveRoomAnchorShowcase extends StatefulWidget { class _LiveRoomAnchorShowcaseState extends State { final RTCManager _rtcManager = RTCManager.instance; + final RoomController _roomController = Get.find(); @override Widget build(BuildContext context) { @@ -94,19 +99,23 @@ class _LiveRoomAnchorShowcaseState extends State { ], ), SizedBox(height: 5.w), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - _buildSideAnchorCard( - isLeft: true, - micIcon: Assets.imagesMicClose, - ), - _buildSideAnchorCard( - isLeft: false, - micIcon: Assets.imagesMicOpen, - ), - ], - ), + Obx(() { + final rtcChannelDetail = + _roomController.rtcChannelDetail.value; + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _buildSideAnchorCard( + isLeft: true, + userInfo: rtcChannelDetail?.maleInfo, + ), + _buildSideAnchorCard( + isLeft: false, + userInfo: rtcChannelDetail?.femaleInfo, + ), + ], + ); + }), ], ); }, @@ -139,7 +148,9 @@ class _LiveRoomAnchorShowcaseState extends State { : AgoraVideoView( controller: VideoViewController.remote( rtcEngine: engine, - canvas: VideoCanvas(uid: _rtcManager.remoteUserIds.first), + canvas: VideoCanvas( + uid: _rtcManager.remoteUserIds.first, + ), connection: RtcConnection( channelId: _rtcManager.currentChannelId!, ), @@ -169,17 +180,63 @@ class _LiveRoomAnchorShowcaseState extends State { ); } - Widget _buildSideAnchorCard({required bool isLeft, required String micIcon}) { + Widget _buildSideAnchorCard({ + required bool isLeft, + RtcSeatUserInfo? userInfo, + }) { + final engine = _rtcManager.engine; + final joined = _rtcManager.channelJoinedNotifier.value; + + // 判断是否是当前用户 + final bool isCurrentUser = _roomController.currentRole == CurrentRole.maleAudience || _roomController.currentRole == CurrentRole.femaleAudience; + return Stack( children: [ - Container( - width: 177.w, - height: 175.w, - decoration: BoxDecoration( - borderRadius: isLeft - ? BorderRadius.horizontal(left: Radius.circular(18.w)) - : BorderRadius.horizontal(right: Radius.circular(18.w)), - color: const Color.fromRGBO(47, 10, 94, 1), + ClipRRect( + borderRadius: isLeft + ? BorderRadius.horizontal(left: Radius.circular(18.w)) + : BorderRadius.horizontal(right: Radius.circular(18.w)), + child: SizedBox( + width: 177.w, + height: 175.w, + child: + userInfo != null && + userInfo.uid != null && + joined && + engine != null + ? AgoraVideoView( + controller: isCurrentUser + ? VideoViewController( + rtcEngine: engine, + canvas: const VideoCanvas(uid: 0), + ) + : VideoViewController.remote( + rtcEngine: engine, + canvas: VideoCanvas(uid: userInfo.uid!), + connection: RtcConnection( + channelId: _rtcManager.currentChannelId ?? '', + ), + ), + ) + : Container( + decoration: BoxDecoration( + borderRadius: isLeft + ? BorderRadius.horizontal(left: Radius.circular(18.w)) + : BorderRadius.horizontal( + right: Radius.circular(18.w), + ), + color: const Color.fromRGBO(47, 10, 94, 1), + ), + child: Center( + child: Text( + '等待${isLeft ? "男" : "女"}嘉宾', + style: TextStyle( + color: Colors.white.withOpacity(0.8), + fontSize: 12.w, + ), + ), + ), + ), ), ), Positioned( @@ -222,34 +279,41 @@ class _LiveRoomAnchorShowcaseState extends State { ), ), ), - Positioned( - left: 5.w, - bottom: 5.w, - child: Row( - children: [ - Container( - width: 20.w, - height: 20.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4.w)), - color: const Color.fromRGBO(0, 0, 0, .65), + if (userInfo != null) + Positioned( + left: 5.w, + bottom: 5.w, + child: Row( + children: [ + Container( + width: 20.w, + height: 20.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(4.w)), + color: const Color.fromRGBO(0, 0, 0, .65), + ), + child: Center( + child: Image.asset( + userInfo.isMicrophoneOn + ? Assets.imagesMicOpen + : Assets.imagesMicClose, + width: 10.w, + height: 11.w, + ), + ), ), - child: Center( - child: Image.asset(micIcon, width: 10.w, height: 11.w), + SizedBox(width: 5.w), + Text( + userInfo.nickName, + style: TextStyle( + fontSize: 11.w, + color: Colors.white, + fontWeight: FontWeight.w500, + ), ), - ), - SizedBox(width: 5.w), - Text( - "飞翔的企鹅", - style: TextStyle( - fontSize: 11.w, - color: Colors.white, - fontWeight: FontWeight.w500, - ), - ), - ], + ], + ), ), - ), ], ); } diff --git a/lib/widget/live/live_room_notice_chat_panel.dart b/lib/widget/live/live_room_notice_chat_panel.dart index bf574f5..f5171ee 100644 --- a/lib/widget/live/live_room_notice_chat_panel.dart +++ b/lib/widget/live/live_room_notice_chat_panel.dart @@ -122,7 +122,11 @@ class _LiveRoomNoticeChatPanelState extends State { ], ), ).onTap(() async{ - await controller.joinChat(GlobalData().userData?.genderCode == 1 ? CurrentRole.maleAudience : CurrentRole.femaleAudience); + if(controller.isLive){ + await controller.leaveChat(); + }else{ + await controller.joinChat(GlobalData().userData?.genderCode == 1 ? CurrentRole.maleAudience : CurrentRole.femaleAudience); + } }); } return const SizedBox();