From f5ecc0eb51dd537ef330e4fecd6da4511ecb82db Mon Sep 17 00:00:00 2001 From: fuenmao <980740792@qq.com> Date: Tue, 7 Jan 2025 17:09:17 +0800 Subject: [PATCH] =?UTF-8?q?1.7=E4=B8=8B=E5=8D=881?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/pages/metting/meeting_main_logic.dart | 467 +++++---- .../lib/pages/metting/meeting_main_state.dart | 2 +- .../lib/pages/metting/meeting_main_view.dart | 977 +++++++++--------- 3 files changed, 735 insertions(+), 711 deletions(-) diff --git a/wgshare/lib/pages/metting/meeting_main_logic.dart b/wgshare/lib/pages/metting/meeting_main_logic.dart index db8daa6..5a38319 100644 --- a/wgshare/lib/pages/metting/meeting_main_logic.dart +++ b/wgshare/lib/pages/metting/meeting_main_logic.dart @@ -27,11 +27,243 @@ import 'meeting_main_state.dart'; class MeetingMainLogic extends GetxController with RequestToolMixin { final MeetingMainState state = MeetingMainState(); + late RtcEngineEventHandler _rtcEngineEventHandler; @override void onInit() { super.onInit(); + _rtcEngineEventHandler = RtcEngineEventHandler( + // 错误回调 + onError: (ErrorCodeType err, String msg){ + debugPrint("wgs输出===:RTC-错误回调:${err}---${msg}"); + }, + // 成功加入会议室回调 + onJoinChannelSuccess: (RtcConnection connection, int elapsed) { + state.isJoinSuccess.value = true; + debugPrint("meeting流程====》3加入频道" ); + debugPrint("wgs输出===:RTC-自己加入会议室,ID:${connection.localUid}"); + }, + onRejoinChannelSuccess: (RtcConnection connection, int elapsed) { + state.isJoinSuccess.value = true; + debugPrint("meeting流程====》4加入频道" ); + debugPrint("wgs输出===:RTC-自己加入会议室,ID:${connection.localUid}"); + }, + // 成功离开会议室回调 + onLeaveChannel: (RtcConnection connection, RtcStats stats) { + debugPrint("wgs输出===:RTC-自己离开会议室,ID:${connection.localUid}"); + }, + + // 远端用户或主播加入当前会议室回调-主播角色才能接收该回调 + onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) { + debugPrint("wgs输出===:RTC-远端用户或主播加入会议室,用户或主机的ID:$remoteUid"); + }, + + // 远端用户或主播离开当前会议室回调-主播角色才能接收该回调 + onUserOffline: (RtcConnection connection, int remoteUid, + UserOfflineReasonType reason) async { + // 判断是否用户取消了共享 + if (remoteUid.toString().length == 9) { + for (var i = 0; i < state.cacheUsers.value.length; i++) { + if (remoteUid.toString() == + state.cacheUsers.value[i].screenShareId) { + state.cacheUsers.value[i].enableShare = false; + } + } + } + update(); + debugPrint("wgs输出===:RTC-远端用户或主播离开会议室,用户或主机的ID:$remoteUid"); + }, + + // 音频路由发生变化回调 + onAudioRoutingChanged: (int routing) { + debugPrint("wgs输出===:RTC-音频路由切换:$routing"); + state.communicationMode.value = routing; + if (routing == 1) { + debugPrint("wgs输出===:RTC-音频路由切换为听筒"); + } else if (routing == 3) { + debugPrint("wgs输出===:RTC-音频路由切换为扬声器"); + } else { + debugPrint("wgs输出===:RTC-音频路由切换为外接设备"); + } + }, + + // 音频采集开关回调 + onLocalAudioStateChanged: (RtcConnection connection, + LocalAudioStreamState state, LocalAudioStreamReason reason) { + debugPrint("wgs输出===:RTC-音频采集开关:$state"); + }, + + // 远端视频状态发生改变回调 + onRemoteVideoStateChanged: (RtcConnection connection, + int remoteUid, + RemoteVideoState remoteVideoState, + RemoteVideoStateReason remoteVideoStateReason, + int elapsed) { + debugPrint( + "wgs输出===:RTC-远端视频状态发生改变:ID-$remoteUid-状态-$remoteVideoStateReason"); + if (remoteVideoStateReason == + RemoteVideoStateReason.remoteVideoStateReasonRemoteMuted) { + // 远端用户停止发送视频流或远端用户禁用视频模块 + if (remoteUid.toString().length != 9) { + // 摄像头 + if (remoteUid.toString() == state.remoteUid.value) { + // 如果停止发送视频流或禁用视频模块的远端用户是当前全员观看主播 + doHttpGetTvAnchor(); + } + } else { + // 共享屏幕(此版本不做) + } + } + }, + + // 用户音量提示回调 + onAudioVolumeIndication: (RtcConnection connection, + List speakers, + int speakerNumber, + int totalVolume) { + if (speakers.isNotEmpty) { + for (AudioVolumeInfo avi in speakers) { + if (avi.uid == 0) { + // debugPrint("wgs输出===:RTC-本地用户音量提示:${avi.uid}--${avi.volume}"); + for (MeetingRoomUser mru in state.cacheUsers.value) { + if (UserStore.to.userInfoEntity.value!.uid == mru.uid) { + mru.volume = CountMicrophoneVolume.getVolume(avi.volume!); + state.microphoneVolume.value = + CountMicrophoneVolume.getVolume(avi.volume!); + } + } + } else { + // debugPrint("wgs输出===:RTC-远端用户音量提示:${avi.uid}--${avi.volume}"); + for (MeetingRoomUser mru in state.cacheUsers.value) { + mru.volume = CountMicrophoneVolume.getVolume(avi.volume!); + + if (avi.volume != 0) { + state.spokesman.value = mru.userName; + state.spokesmanVolume.value = + CountMicrophoneVolume.getVolume(avi.volume!); + } else { + state.spokesman.value = ""; + state.spokesmanVolume.value = 0; + } + } + } + /*for (MeetingRoomUser mru in state.cacheUsers.value) { + // 用于更改语音布局里的用户列表麦克风 + if (avi.uid == 0) { + // debugPrint("wgs输出===:RTC-用户音量提示(自己):${CountMicrophoneVolume.getVolume(avi.volume!)}"); + mru.volume = CountMicrophoneVolume.getVolume(avi.volume!); + state.microphoneVolume.value = + CountMicrophoneVolume.getVolume(avi.volume!); + } else { + debugPrint("wgs输出===:RTC-用户音量提示:${avi.uid}--${mru.uid}"); + if (avi.uid.toString() == mru.uid) { + debugPrint("wgs输出===:RTC-用户音量提示(远端用户):${speakers[0].uid}--${speakers[0].volume}"); + mru.volume = CountMicrophoneVolume.getVolume(avi.volume!); + + if (avi.volume != 0) { + state.spokesman.value = mru.userName; + state.spokesmanVolume.value = + CountMicrophoneVolume.getVolume(avi.volume!); + } else { + state.spokesman.value = ""; + state.spokesmanVolume.value = 0; + } + } + } + }*/ + } + } + }, + + // 切换用户角色回调 + onClientRoleChanged: (RtcConnection connection, + ClientRoleType oldRole, + ClientRoleType newRole, + ClientRoleOptions newRoleOptions) { + debugPrint( + "wgs输出===:RTC-切换用户角色为:${newRole == ClientRoleType.clientRoleBroadcaster ? "主播" : "观众"}"); + }, + + // token即将在30秒内过期回调 + onTokenPrivilegeWillExpire: (RtcConnection connection, String token) { + doHttpGetMeetingToken(false); + }, + + // 本地视频状态发生改变回调 + onLocalVideoStateChanged: (VideoSourceType source, + LocalVideoStreamState state, LocalVideoStreamReason reason) { + debugPrint("wgs输出===:RTC-本地视频状态发生改变:$source--$state--$reason"); + }, + + // 网络连接状态回调 + onConnectionStateChanged: (RtcConnection connection, + ConnectionStateType stateType, + ConnectionChangedReasonType reason) { + debugPrint("wgs输出===:RTC-网络连接状态发生改变:" + "会议室编号(${connection.channelId})," + "网络状态($stateType-${AgoraUtil.getConnectionStateChangedType(stateType)})," + "网络改变原因($reason-${AgoraUtil.getConnectionChangedReasonType(reason)})"); + if (stateType == ConnectionStateType.connectionStateReconnecting) { + if (EasyLoading.isShow == false) { + ToastUtils.showLoadingToMask( + "网络故障,正在重连...", EasyLoadingMaskType.black); + } + } else if (stateType == + ConnectionStateType.connectionStateConnected && + reason == + ConnectionChangedReasonType + .connectionChangedRejoinSuccess) { + ToastUtils.dismiss(); + if (EasyLoading.isShow == false) { + ToastUtils.showSuccessToMask( + "重连成功!", EasyLoadingMaskType.black); + } + } else if (reason == + ConnectionChangedReasonType.connectionChangedLost) { + // 和服务器失去连接后,再延迟15秒(和signalR Socket一致),让SDK继续重连,如果重连不上则告知用户需要重新加入 + Future.delayed(const Duration(milliseconds: 15000), () { + ToastUtils.dismiss(); + if (state.isShowOkAlertDialog.value == false) { + showOkAlertDialog( + context: Get.context!, + title: "提示", + message: "网络错误,请重新加入会议室", + okLabel: "确定", + barrierDismissible: false, + ).then((OkCancelResult value) { + Get.back(); + Get.back(); + }); + } + }); + } + }, + + // 渲染器已接收首帧远端视频回调 + onFirstRemoteVideoFrame: (RtcConnection connection, int remoteUid, + int width, int height, int elapsed) async { + debugPrint("wgs输出===:RTC-渲染器已接收首帧远端视频回调:${remoteUid}--${width}--${height}--${elapsed}"); + + + }, + + // 已接收到远端视频并完成解码回调 + onFirstRemoteVideoDecoded: (RtcConnection connection, int remoteUid, + int width, int height, int elapsed) { + debugPrint("wgs输出===:RTC-已接收到远端视频并完成解码回调:${remoteUid}--${width}--${height}--${elapsed}"); + } + + // 获取设备权限出错回调 + /*onPermissionError: (PermissionType permissionType){ + debugPrint("wgs输出===:RTC-获取设备权限出错:$permissionType"); + if(permissionType == PermissionType.screenCapture){ + // 获取共享屏幕出错(此版本不做) + state.isOpenShare.value = false; + stopScreenCapture(); + } + }*/ + ); // 接收参数 var data = Get.arguments; state.roomNumber.value = data["roomNumber"]; @@ -64,6 +296,8 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { await getClient().getMeetingToken(state.roomNumber.value); state.meetingToken.value = res.data!; + debugPrint("meeting流程====》1获取token成功" ); + if (isInit) { signalRSocket(); } else { @@ -379,6 +613,8 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { await state.hubConnection.value?.start(); + debugPrint("meeting流程====》2socket链接成功" ); + // 开始重新连接时回调 state.hubConnection.value?.onreconnecting((error) { debugPrint("wgs输出===:SignalR Socket-重连$error"); @@ -774,7 +1010,9 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { /// 初始化声网SDK Future initRtc() async { // 创建 RtcEngine 对象 - state.rctEngine.value = createAgoraRtcEngineEx(); + await leaveMeetingToRtc(); + + state.rctEngine.value = createAgoraRtcEngine(); // 初始化 RtcEngine,设置频道场景为 channelProfileLiveBroadcasting(直播场景) await state.rctEngine.value?.initialize(RtcEngineContext( @@ -782,8 +1020,10 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { channelProfile: ChannelProfileType.channelProfileLiveBroadcasting, // logConfig:const LogConfig() )); + state.rctEngine.value?.registerEventHandler(_rtcEngineEventHandler); // 音频模块默认启动,所以这里不再调用启动方法 + // 启用视频模块 await enableVideo(); // 设置默认音频路由为听筒 @@ -795,232 +1035,12 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { await state.rctEngine.value ?.setDualStreamMode(mode: SimulcastStreamMode.enableSimulcastStream); - // 回调 - state.rctEngine.value?.registerEventHandler( - RtcEngineEventHandler( - // 成功加入会议室回调 - onJoinChannelSuccess: (RtcConnection connection, int elapsed) { - state.isJoinSuccess.value = true; - debugPrint("wgs输出===:RTC-自己加入会议室,ID:${connection.localUid}"); - }, - - // 成功离开会议室回调 - onLeaveChannel: (RtcConnection connection, RtcStats stats) { - debugPrint("wgs输出===:RTC-自己离开会议室,ID:${connection.localUid}"); - }, - - // 远端用户或主播加入当前会议室回调-主播角色才能接收该回调 - onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) { - debugPrint("wgs输出===:RTC-远端用户或主播加入会议室,用户或主机的ID:$remoteUid"); - }, - - // 远端用户或主播离开当前会议室回调-主播角色才能接收该回调 - onUserOffline: (RtcConnection connection, int remoteUid, - UserOfflineReasonType reason) async { - // 判断是否用户取消了共享 - if (remoteUid.toString().length == 9) { - for (var i = 0; i < state.cacheUsers.value.length; i++) { - if (remoteUid.toString() == - state.cacheUsers.value[i].screenShareId) { - state.cacheUsers.value[i].enableShare = false; - } - } - } - update(); - debugPrint("wgs输出===:RTC-远端用户或主播离开会议室,用户或主机的ID:$remoteUid"); - }, - - // 音频路由发生变化回调 - onAudioRoutingChanged: (int routing) { - debugPrint("wgs输出===:RTC-音频路由切换:$routing"); - state.communicationMode.value = routing; - if (routing == 1) { - debugPrint("wgs输出===:RTC-音频路由切换为听筒"); - } else if (routing == 3) { - debugPrint("wgs输出===:RTC-音频路由切换为扬声器"); - } else { - debugPrint("wgs输出===:RTC-音频路由切换为外接设备"); - } - }, - - // 音频采集开关回调 - onLocalAudioStateChanged: (RtcConnection connection, - LocalAudioStreamState state, LocalAudioStreamReason reason) { - debugPrint("wgs输出===:RTC-音频采集开关:$state"); - }, - - // 远端视频状态发生改变回调 - onRemoteVideoStateChanged: (RtcConnection connection, - int remoteUid, - RemoteVideoState remoteVideoState, - RemoteVideoStateReason remoteVideoStateReason, - int elapsed) { - debugPrint( - "wgs输出===:RTC-远端视频状态发生改变:ID-$remoteUid-状态-$remoteVideoStateReason"); - if (remoteVideoStateReason == - RemoteVideoStateReason.remoteVideoStateReasonRemoteMuted) { - // 远端用户停止发送视频流或远端用户禁用视频模块 - if (remoteUid.toString().length != 9) { - // 摄像头 - if (remoteUid.toString() == state.remoteUid.value) { - // 如果停止发送视频流或禁用视频模块的远端用户是当前全员观看主播 - doHttpGetTvAnchor(); - } - } else { - // 共享屏幕(此版本不做) - } - } - }, - - // 用户音量提示回调 - onAudioVolumeIndication: (RtcConnection connection, - List speakers, - int speakerNumber, - int totalVolume) { - if (speakers.isNotEmpty) { - for (AudioVolumeInfo avi in speakers) { - if (avi.uid == 0) { - // debugPrint("wgs输出===:RTC-本地用户音量提示:${avi.uid}--${avi.volume}"); - for (MeetingRoomUser mru in state.cacheUsers.value) { - if (UserStore.to.userInfoEntity.value!.uid == mru.uid) { - mru.volume = CountMicrophoneVolume.getVolume(avi.volume!); - state.microphoneVolume.value = - CountMicrophoneVolume.getVolume(avi.volume!); - } - } - } else { - // debugPrint("wgs输出===:RTC-远端用户音量提示:${avi.uid}--${avi.volume}"); - for (MeetingRoomUser mru in state.cacheUsers.value) { - mru.volume = CountMicrophoneVolume.getVolume(avi.volume!); - - if (avi.volume != 0) { - state.spokesman.value = mru.userName; - state.spokesmanVolume.value = - CountMicrophoneVolume.getVolume(avi.volume!); - } else { - state.spokesman.value = ""; - state.spokesmanVolume.value = 0; - } - } - } - /*for (MeetingRoomUser mru in state.cacheUsers.value) { - // 用于更改语音布局里的用户列表麦克风 - if (avi.uid == 0) { - // debugPrint("wgs输出===:RTC-用户音量提示(自己):${CountMicrophoneVolume.getVolume(avi.volume!)}"); - mru.volume = CountMicrophoneVolume.getVolume(avi.volume!); - state.microphoneVolume.value = - CountMicrophoneVolume.getVolume(avi.volume!); - } else { - debugPrint("wgs输出===:RTC-用户音量提示:${avi.uid}--${mru.uid}"); - if (avi.uid.toString() == mru.uid) { - debugPrint("wgs输出===:RTC-用户音量提示(远端用户):${speakers[0].uid}--${speakers[0].volume}"); - mru.volume = CountMicrophoneVolume.getVolume(avi.volume!); - - if (avi.volume != 0) { - state.spokesman.value = mru.userName; - state.spokesmanVolume.value = - CountMicrophoneVolume.getVolume(avi.volume!); - } else { - state.spokesman.value = ""; - state.spokesmanVolume.value = 0; - } - } - } - }*/ - } - } - }, - - // 切换用户角色回调 - onClientRoleChanged: (RtcConnection connection, - ClientRoleType oldRole, - ClientRoleType newRole, - ClientRoleOptions newRoleOptions) { - debugPrint( - "wgs输出===:RTC-切换用户角色为:${newRole == ClientRoleType.clientRoleBroadcaster ? "主播" : "观众"}"); - }, - - // token即将在30秒内过期回调 - onTokenPrivilegeWillExpire: (RtcConnection connection, String token) { - doHttpGetMeetingToken(false); - }, - - // 本地视频状态发生改变回调 - onLocalVideoStateChanged: (VideoSourceType source, - LocalVideoStreamState state, LocalVideoStreamReason reason) { - debugPrint("wgs输出===:RTC-本地视频状态发生改变:$source--$state--$reason"); - }, - - // 网络连接状态回调 - onConnectionStateChanged: (RtcConnection connection, - ConnectionStateType stateType, - ConnectionChangedReasonType reason) { - debugPrint("wgs输出===:RTC-网络连接状态发生改变:" - "会议室编号(${connection.channelId})," - "网络状态($stateType-${AgoraUtil.getConnectionStateChangedType(stateType)})," - "网络改变原因($reason-${AgoraUtil.getConnectionChangedReasonType(reason)})"); - if (stateType == ConnectionStateType.connectionStateReconnecting) { - if (EasyLoading.isShow == false) { - ToastUtils.showLoadingToMask( - "网络故障,正在重连...", EasyLoadingMaskType.black); - } - } else if (stateType == - ConnectionStateType.connectionStateConnected && - reason == - ConnectionChangedReasonType - .connectionChangedRejoinSuccess) { - ToastUtils.dismiss(); - if (EasyLoading.isShow == false) { - ToastUtils.showSuccessToMask( - "重连成功!", EasyLoadingMaskType.black); - } - } else if (reason == - ConnectionChangedReasonType.connectionChangedLost) { - // 和服务器失去连接后,再延迟15秒(和signalR Socket一致),让SDK继续重连,如果重连不上则告知用户需要重新加入 - Future.delayed(const Duration(milliseconds: 15000), () { - ToastUtils.dismiss(); - if (state.isShowOkAlertDialog.value == false) { - showOkAlertDialog( - context: Get.context!, - title: "提示", - message: "网络错误,请重新加入会议室", - okLabel: "确定", - barrierDismissible: false, - ).then((OkCancelResult value) { - Get.back(); - Get.back(); - }); - } - }); - } - }, - - // 渲染器已接收首帧远端视频回调 - onFirstRemoteVideoFrame: (RtcConnection connection, int remoteUid, - int width, int height, int elapsed) async { - debugPrint("wgs输出===:RTC-渲染器已接收首帧远端视频回调:${remoteUid}--${width}--${height}--${elapsed}"); + WidgetsBinding.instance.addPostFrameCallback((_)=>joinMeetingToRtc()); - }, + // await joinMeetingToRtc(); - // 已接收到远端视频并完成解码回调 - onFirstRemoteVideoDecoded: (RtcConnection connection, int remoteUid, - int width, int height, int elapsed) { - debugPrint("wgs输出===:RTC-已接收到远端视频并完成解码回调:${remoteUid}--${width}--${height}--${elapsed}"); - } - // 获取设备权限出错回调 - /*onPermissionError: (PermissionType permissionType){ - debugPrint("wgs输出===:RTC-获取设备权限出错:$permissionType"); - if(permissionType == PermissionType.screenCapture){ - // 获取共享屏幕出错(此版本不做) - state.isOpenShare.value = false; - stopScreenCapture(); - } - }*/ - ), - ); - await joinMeetingToRtc(); } /// 加入会议室 @@ -1048,6 +1068,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { /// 离开会议室 Future leaveMeetingToRtc() async { + state.rctEngine.value?.unregisterEventHandler(_rtcEngineEventHandler); // 离开 await state.rctEngine.value?.leaveChannel(); // 释放资源 diff --git a/wgshare/lib/pages/metting/meeting_main_state.dart b/wgshare/lib/pages/metting/meeting_main_state.dart index e41538b..afccc5d 100644 --- a/wgshare/lib/pages/metting/meeting_main_state.dart +++ b/wgshare/lib/pages/metting/meeting_main_state.dart @@ -101,7 +101,7 @@ class MeetingMainState { /// 声网相关 final String appId = "4a4f7be64fa1404ebda74784fe9ac381"; - Rx rctEngine = Rx(null); + Rx rctEngine = Rx(null); /// 是否自动订阅所有视频流 late RxBool isAutoSubscribeVideo = false.obs; /// 是否自动订阅所有音频流 diff --git a/wgshare/lib/pages/metting/meeting_main_view.dart b/wgshare/lib/pages/metting/meeting_main_view.dart index 57a05f6..b90c534 100644 --- a/wgshare/lib/pages/metting/meeting_main_view.dart +++ b/wgshare/lib/pages/metting/meeting_main_view.dart @@ -68,25 +68,27 @@ class MeetingMainPageState extends State { ), backgroundColor: ColorUtil.Color_41_41_41, ), - body: Obx(() => Stack( - children: [ - Column( - children: [ - /// 顶部布局 - Container( - width: double.infinity, - height: 100.h, - alignment: Alignment.center, - color: ColorUtil.Color_41_41_41, - padding: const EdgeInsets.only(left: 16, right: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - width: 92.w, - child: Row( - children: [ - /*GestureDetector( + body: Obx((){ + + return Stack( + children: [ + Column( + children: [ + /// 顶部布局 + Container( + width: double.infinity, + height: 100.h, + alignment: Alignment.center, + color: ColorUtil.Color_41_41_41, + padding: const EdgeInsets.only(left: 16, right: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + width: 92.w, + child: Row( + children: [ + /*GestureDetector( child: Image.asset( 'assets/images/meeting_main_narrow.png', width: 20.w, @@ -95,471 +97,471 @@ class MeetingMainPageState extends State { onTap: () {}, ), SizedBox(width: 16.w),*/ - GestureDetector( - child: Container( - color: ColorUtil.Color_0_0_0_0, - padding: const EdgeInsets.only(top: 10, bottom: 10, right: 12), - child: Image.asset( - state.communicationMode.value == 1 - ? 'assets/images/meeting_main_receiver.png' - : 'assets/images/meeting_main_speaker.png', - width: 20.w, - height: 20.h, - ), + GestureDetector( + child: Container( + color: ColorUtil.Color_0_0_0_0, + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 12), + child: Image.asset( + state.communicationMode.value == 1 + ? 'assets/images/meeting_main_receiver.png' + : 'assets/images/meeting_main_speaker.png', + width: 20.w, + height: 20.h, + ), + ), + onTap: () { + if (state.communicationMode.value == + 1 || + state.communicationMode.value == + 3) { + logic.changeMeetingAudioState(true); + } + }, + ), + Visibility( + visible: state.isOpenCamera.value, + child: GestureDetector( + child: Row( + children: [ + SizedBox(width: 16.w), + Image.asset( + 'assets/images/meeting_main_rotate_camera.png', + width: 20.w, + height: 20.h, + ) + ], ), onTap: () { - if (state.communicationMode.value == - 1 || - state.communicationMode.value == - 3) { - logic.changeMeetingAudioState(true); - } + logic.switchCamera(); }, ), - Visibility( - visible: state.isOpenCamera.value, - child: GestureDetector( - child: Row( - children: [ - SizedBox(width: 16.w), - Image.asset( - 'assets/images/meeting_main_rotate_camera.png', - width: 20.w, - height: 20.h, - ) - ], - ), - onTap: () { - logic.switchCamera(); - }, - ), - ) - ], - ), + ) + ], ), - GestureDetector( - child: Container( - color: ColorUtil.Color_0_0_0_0, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - children: [ - Text( - state.meetingRoomInfo.value - ?.roomName ?? - '', - style: TextStyle( - color: Colors.white, - fontSize: 14.sp, - fontWeight: FontWeight.w500), - ), - SizedBox(width: 4.w), - Image.asset( - 'assets/images/meeting_main_down.png', - width: 16.w, - height: 16.h, - ) - ], - ), - SizedBox(height: 4.h), - Text( - state.duration.value, - style: TextStyle( - color: Colors.white, - fontSize: 12.sp, - ), - ) - ], - ), - ), - onTap: () { - logic.changeMeetingInfoState(true); - }, - ), - Container( - width: 92.w, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, + ), + GestureDetector( + child: Container( + color: ColorUtil.Color_0_0_0_0, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, children: [ - /// 退出会议 - GestureDetector( - child: Container( - color: ColorUtil.Color_0_0_0_0, - padding: const EdgeInsets.only(top: 10, bottom: 10, left: 20), - child: Image.asset( - 'assets/images/meeting_leave.png', - width: 20.w, - height: 20.h, + Row( + children: [ + Text( + state.meetingRoomInfo.value + ?.roomName ?? + '', + style: TextStyle( + color: Colors.white, + fontSize: 14.sp, + fontWeight: FontWeight.w500), ), + SizedBox(width: 4.w), + Image.asset( + 'assets/images/meeting_main_down.png', + width: 16.w, + height: 16.h, + ) + ], + ), + SizedBox(height: 4.h), + Text( + state.duration.value, + style: TextStyle( + color: Colors.white, + fontSize: 12.sp, ), - onTap: () { - Get.bottomSheet( - isScrollControlled: true, - leaveBottomSheet(context)); - }, ) ], ), - ) - ], - ), - ), - - /// 中间布局 - Expanded( - child: Stack( - alignment: Alignment.bottomLeft, - children: [ - // 语音 - Visibility( - visible: state.pageState.value == 0, - child: MeetingMainVoiceComponent( - users: state.cacheUsers.value)), - - // 视频-共享 - Visibility( - visible: state.pageState.value == 1, - child: state.isJoinSuccess.value == true && - null != state.rctEngine.value && - state.users.isNotEmpty - ? Stack( - alignment: Alignment.center, - children: [ - PreloadPageView.builder( - preloadPagesCount: 2, - itemCount: 2, - itemBuilder: - (BuildContext context, - int position) => - returnPage(position), - controller: - PreloadPageController( - initialPage: 0), - onPageChanged: (int position) { - state.pageIndex.value = - position; - if (state.isSpeak.value == - true && - state.isOpenCamera - .value == - true && - state.remoteUid.value != - "0") { - if (position == 0) { - state.floating.value - ?.open(context); - } else { - state.floating.value - ?.close(); - } - } - }, - ), - - /// pageview 指示器 - Positioned( - bottom: 16, - child: Row( - children: [ - Container( - width: 8.w, - height: 8.h, - margin: - const EdgeInsets.only( - right: 6), - decoration: BoxDecoration( - borderRadius: - BorderRadius - .circular(8), - color: state.pageIndex - .value == - 0 - ? ColorUtil - .Color_255_255_255 - : ColorUtil - .Color_108_108_108), - ), - Container( - width: 8.w, - height: 8.h, - margin: - const EdgeInsets.only( - left: 6), - decoration: BoxDecoration( - borderRadius: - BorderRadius - .circular(8), - color: state.pageIndex - .value == - 1 - ? ColorUtil - .Color_255_255_255 - : ColorUtil - .Color_108_108_108), - ) - ], - ), - ), - ], - ) - : Container( - color: Colors.red, - /*child: Text('加载反馈:是否成功加入会议室${state.isJoinSuccess.value}-会议室对象${state.rctEngine.value}-成员列表${state.users.value.length}-全员观看ID${state.remoteUid.value}'),*/ - )), - - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + ), + onTap: () { + logic.changeMeetingInfoState(true); + }, + ), + Container( + width: 92.w, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, children: [ + /// 退出会议 GestureDetector( - child: Container( - width: 200.w, - height: 40.h, - margin: const EdgeInsets.only( - left: 20, bottom: 40), - padding: - const EdgeInsets.only(left: 20), - decoration: BoxDecoration( - borderRadius: const BorderRadius.only( - bottomLeft: Radius.circular(56), - topRight: Radius.circular(50), - bottomRight: Radius.circular(50)), - color: ColorUtil.Color_35_35_35_07, - border: Border.all( - width: 1.w, - color: - ColorUtil.Color_99_111_158), - ), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.center, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Image.asset( - 'assets/images/meeting_main_chat.png', - width: 18.w, - height: 18.h, - ), - SizedBox(width: 6.w), - Text( - '说点什么...', - style: TextStyle( - fontSize: 14.sp, - color: ColorUtil - .Color_156_156_156), - ) - ], - ), - Visibility( - visible: state.msgNum.value > 0 ? true : false, - child: Container( - width: 18.w, - height: 18.h, - alignment: Alignment.center, - margin: const EdgeInsets.only(right: 12), - decoration: const BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(20)), - color: ColorUtil.Color_255_69_69, - ), - child: Text( - "${state.msgNum.value}", - style: TextStyle( - fontSize: 12.sp, - color: ColorUtil - .Color_255_255_255), - ) - ), - ) - ], + child: Container( + color: ColorUtil.Color_0_0_0_0, + padding: const EdgeInsets.only(top: 10, bottom: 10, left: 20), + child: Image.asset( + 'assets/images/meeting_leave.png', + width: 20.w, + height: 20.h, ), ), onTap: () { Get.bottomSheet( isScrollControlled: true, - chatBottomSheet(context)); - - state.msgNum.value = 0; - - Future.delayed( - const Duration(milliseconds: 100), - () { - state.chatController.jumpTo(state - .chatController - .position - .maxScrollExtent); - }); + leaveBottomSheet(context)); }, - ), - Visibility( - visible: state.isSpeak.value, - child: GestureDetector( - child: Container( - width: 82.w, - height: 40.h, - margin: const EdgeInsets.only( - left: 12, bottom: 40, right: 20), - alignment: Alignment.center, - decoration: const BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(99)), - color: ColorUtil.Color_255_69_69), - child: Text( - '结束发言', - style: TextStyle( - fontSize: 14.sp, - color: ColorUtil - .Color_255_255_255), - ), - ), - onTap: () { - logic.cancelSpeak(); - }, - ), ) ], - ) - ], - ), + ), + ) + ], ), + ), - /// 底部布局 - Container( - width: double.infinity, - height: 84.h, - color: ColorUtil.Color_35_35_35, - padding: const EdgeInsets.only(left: 26, right: 26), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - /// 音频 - GestureDetector( - child: Container( - padding: const EdgeInsets.only(left: 6,right: 6), - color: ColorUtil.Color_0_0_0_0, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - state.isSpeak.value == false - ? Image.asset( - state.isSpeak.value == false - ? 'assets/images/meeting_main_sqfy.png' - : state.isOpenMicrophone - .value == - true - ? 'assets/images/meeting_main_microphone_default.png' - : 'assets/images/meeting_main_sqfy.png', - width: 20.w, - height: 20.h, - ) - : state.isOpenMicrophone.value == true - ? Container( - width: 20.w, - height: 20.h, - child: LiquidCustomProgressIndicator( - value: state - .microphoneVolume - .value, - valueColor: - const AlwaysStoppedAnimation( - ColorUtil - .Color_2_177_136), - backgroundColor: ColorUtil - .Color_255_255_255, - direction: Axis.vertical, - shapePath: ViewSvgPath - .getMicrpphonePath()), - ) - : Image.asset( - 'assets/images/meeting_main_sqfy.png', - width: 20.w, - height: 20.h, + /// 中间布局 + Expanded( + child: Stack( + alignment: Alignment.bottomLeft, + children: [ + // 语音 + Visibility( + visible: state.pageState.value == 0, + child: MeetingMainVoiceComponent( + users: state.cacheUsers.value)), + + // 视频-共享 + Visibility( + visible: state.pageState.value == 1, + child: state.isJoinSuccess.value == true && + null != state.rctEngine.value && + state.users.isNotEmpty + ? Stack( + alignment: Alignment.center, + children: [ + PreloadPageView.builder( + preloadPagesCount: 2, + itemCount: 2, + itemBuilder: + (BuildContext context, + int position) => + returnPage(position), + controller: + PreloadPageController( + initialPage: 0), + onPageChanged: (int position) { + state.pageIndex.value = + position; + if (state.isSpeak.value == + true && + state.isOpenCamera + .value == + true && + state.remoteUid.value != + "0") { + if (position == 0) { + state.floating.value + ?.open(context); + } else { + state.floating.value + ?.close(); + } + } + }, + ), + + /// pageview 指示器 + Positioned( + bottom: 16, + child: Row( + children: [ + Container( + width: 8.w, + height: 8.h, + margin: + const EdgeInsets.only( + right: 6), + decoration: BoxDecoration( + borderRadius: + BorderRadius + .circular(8), + color: state.pageIndex + .value == + 0 + ? ColorUtil + .Color_255_255_255 + : ColorUtil + .Color_108_108_108), + ), + Container( + width: 8.w, + height: 8.h, + margin: + const EdgeInsets.only( + left: 6), + decoration: BoxDecoration( + borderRadius: + BorderRadius + .circular(8), + color: state.pageIndex + .value == + 1 + ? ColorUtil + .Color_255_255_255 + : ColorUtil + .Color_108_108_108), + ) + ], ), - SizedBox(height: 4.h), - Text( - state.isSpeak.value == false - ? '申请发言' - : state.isOpenMicrophone.value == - true - ? "手动静音" - : "解除静音", - style: TextStyle( - fontSize: 12.sp, - color: ColorUtil.Color_202_202_202), - ) - ], + ), + ], + ) + : Container( + color: Colors.red, + /*child: Text('加载反馈:是否成功加入会议室${state.isJoinSuccess.value}-会议室对象${state.rctEngine.value}-成员列表${state.users.value.length}-全员观看ID${state.remoteUid.value}'),*/ + )), + + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + child: Container( + width: 200.w, + height: 40.h, + margin: const EdgeInsets.only( + left: 20, bottom: 40), + padding: + const EdgeInsets.only(left: 20), + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(56), + topRight: Radius.circular(50), + bottomRight: Radius.circular(50)), + color: ColorUtil.Color_35_35_35_07, + border: Border.all( + width: 1.w, + color: + ColorUtil.Color_99_111_158), + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.center, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Image.asset( + 'assets/images/meeting_main_chat.png', + width: 18.w, + height: 18.h, + ), + SizedBox(width: 6.w), + Text( + '说点什么...', + style: TextStyle( + fontSize: 14.sp, + color: ColorUtil + .Color_156_156_156), + ) + ], + ), + Visibility( + visible: state.msgNum.value > 0 ? true : false, + child: Container( + width: 18.w, + height: 18.h, + alignment: Alignment.center, + margin: const EdgeInsets.only(right: 12), + decoration: const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20)), + color: ColorUtil.Color_255_69_69, + ), + child: Text( + "${state.msgNum.value}", + style: TextStyle( + fontSize: 12.sp, + color: ColorUtil + .Color_255_255_255), + ) + ), + ) + ], + ), ), - ), - onTap: () { - if (state.isSpeak.value == false) { + onTap: () { Get.bottomSheet( isScrollControlled: true, - applySpeakPermissionBottomSheet( - context, 1)); - } else { - if (state.isOpenMicrophone.value == - false) { - logic.doHttpSetMicr(true); - } else { - logic.doHttpSetMicr(false); - } - } - }, - ), + chatBottomSheet(context)); - /// 视频 - GestureDetector( - child: Container( - padding: const EdgeInsets.only(left: 6,right: 6), - color: ColorUtil.Color_0_0_0_0, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - state.isSpeak.value == true - ? state.isOpenCamera.value == true - ? 'assets/images/meeting_main_camera_open.png' - : 'assets/images/meeting_main_camera_default.png' - : 'assets/images/meeting_main_sp.png', - width: 22.w, - height: 22.h, + state.msgNum.value = 0; + + Future.delayed( + const Duration(milliseconds: 100), + () { + state.chatController.jumpTo(state + .chatController + .position + .maxScrollExtent); + }); + }, + ), + Visibility( + visible: state.isSpeak.value, + child: GestureDetector( + child: Container( + width: 82.w, + height: 40.h, + margin: const EdgeInsets.only( + left: 12, bottom: 40, right: 20), + alignment: Alignment.center, + decoration: const BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(99)), + color: ColorUtil.Color_255_69_69), + child: Text( + '结束发言', + style: TextStyle( + fontSize: 14.sp, + color: ColorUtil + .Color_255_255_255), ), - SizedBox(height: 4.h), - Text( - /*state.isSpeak.value == false + ), + onTap: () { + logic.cancelSpeak(); + }, + ), + ) + ], + ) + ], + ), + ), + + /// 底部布局 + Container( + width: double.infinity, + height: 84.h, + color: ColorUtil.Color_35_35_35, + padding: const EdgeInsets.only(left: 26, right: 26), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + /// 音频 + GestureDetector( + child: Container( + padding: const EdgeInsets.only(left: 6,right: 6), + color: ColorUtil.Color_0_0_0_0, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + state.isSpeak.value == false + ? Image.asset( + state.isSpeak.value == false + ? 'assets/images/meeting_main_sqfy.png' + : state.isOpenMicrophone + .value == + true + ? 'assets/images/meeting_main_microphone_default.png' + : 'assets/images/meeting_main_sqfy.png', + width: 20.w, + height: 20.h, + ) + : state.isOpenMicrophone.value == true + ? Container( + width: 20.w, + height: 20.h, + child: LiquidCustomProgressIndicator( + value: state + .microphoneVolume + .value, + valueColor: + const AlwaysStoppedAnimation( + ColorUtil + .Color_2_177_136), + backgroundColor: ColorUtil + .Color_255_255_255, + direction: Axis.vertical, + shapePath: ViewSvgPath + .getMicrpphonePath()), + ) + : Image.asset( + 'assets/images/meeting_main_sqfy.png', + width: 20.w, + height: 20.h, + ), + SizedBox(height: 4.h), + Text( + state.isSpeak.value == false + ? '申请发言' + : state.isOpenMicrophone.value == + true + ? "手动静音" + : "解除静音", + style: TextStyle( + fontSize: 12.sp, + color: ColorUtil.Color_202_202_202), + ) + ], + ), + ), + onTap: () { + if (state.isSpeak.value == false) { + Get.bottomSheet( + isScrollControlled: true, + applySpeakPermissionBottomSheet( + context, 1)); + } else { + if (state.isOpenMicrophone.value == + false) { + logic.doHttpSetMicr(true); + } else { + logic.doHttpSetMicr(false); + } + } + }, + ), + + /// 视频 + GestureDetector( + child: Container( + padding: const EdgeInsets.only(left: 6,right: 6), + color: ColorUtil.Color_0_0_0_0, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + state.isSpeak.value == true + ? state.isOpenCamera.value == true + ? 'assets/images/meeting_main_camera_open.png' + : 'assets/images/meeting_main_camera_default.png' + : 'assets/images/meeting_main_sp.png', + width: 22.w, + height: 22.h, + ), + SizedBox(height: 4.h), + Text( + /*state.isSpeak.value == false ? '申请发言' : */ - state.isOpenCamera.value == true - ? "关闭视频" - : "开启视频", - style: TextStyle( - fontSize: 12.sp, - color: ColorUtil.Color_202_202_202), - ) - ], - ), + state.isOpenCamera.value == true + ? "关闭视频" + : "开启视频", + style: TextStyle( + fontSize: 12.sp, + color: ColorUtil.Color_202_202_202), + ) + ], ), - onTap: () { - if (state.isSpeak.value == false) { - Get.bottomSheet( - isScrollControlled: true, - applySpeakPermissionBottomSheet( - context, 2)); - } else { - if (state.isOpenCamera.value == true) { - logic.doHttpSetCamer(false); - } else { - logic.doHttpSetCamer(true); - } - } - }, ), + onTap: () { + if (state.isSpeak.value == false) { + Get.bottomSheet( + isScrollControlled: true, + applySpeakPermissionBottomSheet( + context, 2)); + } else { + if (state.isOpenCamera.value == true) { + logic.doHttpSetCamer(false); + } else { + logic.doHttpSetCamer(true); + } + } + }, + ), - /// 共享(此版本不做) - /*GestureDetector( + /// 共享(此版本不做) + /*GestureDetector( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -592,45 +594,46 @@ class MeetingMainPageState extends State { }, ),*/ - /// 成员 - GestureDetector( - child: Container( - padding: const EdgeInsets.only(left: 6,right: 6), - color: ColorUtil.Color_0_0_0_0, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'assets/images/meeting_main_member_default.png', - width: 22.w, - height: 22.h, - ), - SizedBox(height: 4.h), - Text( - ' 成员 ', - style: TextStyle( - fontSize: 12.sp, - color: ColorUtil.Color_202_202_202), - ) - ], - ), + /// 成员 + GestureDetector( + child: Container( + padding: const EdgeInsets.only(left: 6,right: 6), + color: ColorUtil.Color_0_0_0_0, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/meeting_main_member_default.png', + width: 22.w, + height: 22.h, + ), + SizedBox(height: 4.h), + Text( + ' 成员 ', + style: TextStyle( + fontSize: 12.sp, + color: ColorUtil.Color_202_202_202), + ) + ], ), - onTap: () { - Get.bottomSheet( - isScrollControlled: true, - queryMemberFloatingLayer(context), - ); - }, ), - ], - ), - ) - ], - ), - meetingInfoFloatingLayer(), - meetingAudioFloatingLayer(), - ], - ))), + onTap: () { + Get.bottomSheet( + isScrollControlled: true, + queryMemberFloatingLayer(context), + ); + }, + ), + ], + ), + ) + ], + ), + meetingInfoFloatingLayer(), + meetingAudioFloatingLayer(), + ], + ); + }),), )); }