From ed9e68e73a0a18ee699377aeb6916bb8099134f4 Mon Sep 17 00:00:00 2001 From: fuenmao <980740792@qq.com> Date: Mon, 9 Dec 2024 15:22:34 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=86=E9=A2=91=E4=BC=98=E5=8C=961?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/pages/metting/meeting_main_logic.dart | 62 ++-- .../lib/pages/metting/meeting_main_state.dart | 6 +- .../lib/pages/metting/meeting_main_view.dart | 269 ++++++++++++++++-- 3 files changed, 273 insertions(+), 64 deletions(-) diff --git a/wgshare/lib/pages/metting/meeting_main_logic.dart b/wgshare/lib/pages/metting/meeting_main_logic.dart index ca1e7b3..8d27613 100644 --- a/wgshare/lib/pages/metting/meeting_main_logic.dart +++ b/wgshare/lib/pages/metting/meeting_main_logic.dart @@ -193,37 +193,27 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{ Future doHttpGetTvAnchor() async { BaseStructureResult res = await getClient().getTvAnchor(state.roomNumber.value); state.remoteUid.value = res.data!.toString(); - - MeetingRoomUser? temporaryMru; - for(MeetingRoomUser mru in state.cacheUsers.value){ - if(mru.uid == res.data!.toString()){ - temporaryMru = mru; - } - } - - var isExist = false; - for(MeetingRoomUser mru in state.videoUsers.value){ - if(temporaryMru!.uid == mru.uid){ - isExist = true; - } - } - if(isExist == false){ - state.videoUsers.value.add(temporaryMru!); - } - if(res.data!.toString().length != 9){ if(state.remoteUid.value != UserStore.to.userInfoEntity.value!.uid) { - Future.delayed(const Duration(milliseconds: 1000), () { - changePageState(1); - }); + state.isSelf.value = false; + }else{ + state.isSelf.value = true; } }else{ if(state.remoteUid.value != UserStore.to.userInfoEntity.value!.screenShareId){ - Future.delayed(const Duration(milliseconds: 1000), () { - changePageState(2); - }); + if(state.remoteUid.value != UserStore.to.userInfoEntity.value!.uid) { + state.isSelf.value = false; + }else{ + state.isSelf.value = true; + } } } + if(state.isSelf.value == true){ + state.floating.value?.close(); + } + Future.delayed(const Duration(milliseconds: 1000), () { + changePageState(1); + }); } /// 设置屏幕共享是否打开 @@ -307,6 +297,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{ state.isOpenMicrophone.value = false; state.isOpenCamera.value = false; setClientRole("观众"); + changePageState(0); debugPrint("wgs输出===:Socket-关闭发言权限:观众"); } } @@ -434,25 +425,19 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{ MeetingRoomUser meetingRoomUser = MeetingRoomUser.fromJson(listDynamic); if(meetingRoomUser.enableCamera == true){ debugPrint("wgs输出===:Socket-用户单独开摄像头"); - - var isExist = false; - for(MeetingRoomUser mru in state.videoUsers.value){ + for(MeetingRoomUser mru in state.cacheUsers.value){ if(mru.uid == meetingRoomUser.uid){ - isExist = true; + mru.enableCamera = true; } } - if(isExist == false){ - state.videoUsers.value.add(meetingRoomUser); - } - if(meetingRoomUser.uid == UserStore.to.userInfoEntity.value!.uid){ state.isOpenCamera.value = true; // 恢复发布视频流 muteLocalVideoStream(false); // 开始本地预览 startPreview(); - // 只有在视频大屏的时候 - if(state.pageIndex.value == 0){ + // 只有在视频大屏,并且全员观看不是自己的时候 + if(state.pageIndex.value == 0 && state.isSelf.value == false){ // 打开本地预览悬浮窗 state.floating.value?.open(state.context.value!); } @@ -460,13 +445,11 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{ } }else{ debugPrint("wgs输出===:Socket-用户单独闭摄像头"); - - for(var i = 0; i < state.videoUsers.value.length; i++){ - if(state.videoUsers.value[i].uid == meetingRoomUser.uid){ - state.videoUsers.value.removeAt(i); + for(MeetingRoomUser mru in state.cacheUsers.value){ + if(mru.uid == meetingRoomUser.uid){ + mru.enableCamera = false; } } - if(meetingRoomUser.uid == UserStore.to.userInfoEntity.value!.uid){ state.isOpenCamera.value = false; @@ -476,7 +459,6 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{ stopPreview(); // 关闭本地预览悬浮窗 state.floating.value?.close(); - state.floating.value?.hideFloating(); } } }); diff --git a/wgshare/lib/pages/metting/meeting_main_state.dart b/wgshare/lib/pages/metting/meeting_main_state.dart index 39949ab..0531ad1 100644 --- a/wgshare/lib/pages/metting/meeting_main_state.dart +++ b/wgshare/lib/pages/metting/meeting_main_state.dart @@ -34,7 +34,7 @@ class MeetingMainState { /// 当前页面状态,0:语音,1:视频,2,共享 late RxInt pageState = 0.obs; /// 视频页面状态时,pageview指示器 - late RxInt pageIndex = 1.obs; + late RxInt pageIndex = 0.obs; /// 会议室编号 late RxString roomNumber = "".obs; @@ -56,8 +56,6 @@ class MeetingMainState { /// 搜索用户时,缓存会议室所有用户原始数据 late RxList cacheUsers = RxList([]); - late RxList videoUsers = RxList([]); - /// 是否被允许发言 late RxBool isSpeak = false.obs; /// 是否打开麦克风 @@ -68,6 +66,8 @@ class MeetingMainState { late RxBool isOpenCamera = false.obs; /// 当前视频主播ID late RxString remoteUid = "".obs; + /// 当前主播是否是自己 + late RxBool isSelf = false.obs; /// 是否启动屏幕共享摄像头 late RxBool isOpenShare = false.obs; diff --git a/wgshare/lib/pages/metting/meeting_main_view.dart b/wgshare/lib/pages/metting/meeting_main_view.dart index a4c7bee..707e612 100644 --- a/wgshare/lib/pages/metting/meeting_main_view.dart +++ b/wgshare/lib/pages/metting/meeting_main_view.dart @@ -87,12 +87,6 @@ class MeetingMainPageState extends State { height: 20.h, ), onTap: () { - if (state.floating.value?.isShowing == - true) { - state.floating.value?.close(); - } else { - state.floating.value?.open(context); - } }, ), SizedBox(width: 16.w), @@ -220,9 +214,9 @@ class MeetingMainPageState extends State { child: MeetingMainVoiceComponent( users: state.cacheUsers.value)), - // 视频 + // 视频-别人是主播时 Visibility( - visible: state.pageState.value == 1, + visible: state.pageState.value == 1 && state.isSelf.value == false, child: null != state.rctEngine.value ? Stack( alignment: Alignment.center, @@ -230,11 +224,11 @@ class MeetingMainPageState extends State { PreloadPageView.builder( preloadPagesCount: 2, itemCount: 2, - itemBuilder: (BuildContext context, int position) => returnPage(position), - controller: PreloadPageController(initialPage: 1), + itemBuilder: (BuildContext context, int position) => returnPageToOther(position), + controller: PreloadPageController(initialPage: 0), onPageChanged: (int position) { state.pageIndex.value = position; - if(state.isSpeak.value == true && state.isOpenCamera.value == true){ + if(state.isSpeak.value == true && state.isOpenCamera.value == true && state.isSelf.value == false){ if(position == 0){ state.floating.value?.open(context); }else{ @@ -276,6 +270,55 @@ class MeetingMainPageState extends State { ) : Container()), + // 视频-自己时主播时 + Visibility( + visible: state.pageState.value == 1 && state.isSelf.value == true, + child: null != state.rctEngine.value + ? Stack( + alignment: Alignment.center, + children: [ + PreloadPageView.builder( + preloadPagesCount: 2, + itemCount: 2, + itemBuilder: (BuildContext context, int position) => returnPageSelf(position), + controller: PreloadPageController(initialPage: 0), + onPageChanged: (int position) { + state.pageIndex.value = position; + }, + ), + + /// 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()), + // 共享屏幕 Visibility( visible: state.pageState.value == 2, @@ -1472,8 +1515,8 @@ class MeetingMainPageState extends State { ); } - /// 然后对应页数的界面 - Widget returnPage(int position){ + /// 对应页数的界面-全员观看是别人时 + Widget returnPageToOther(int position){ var pageList = []; /// 大屏 pageList.add(Stack( @@ -1542,11 +1585,11 @@ class MeetingMainPageState extends State { crossAxisCount: 2, childAspectRatio: 0.8, crossAxisSpacing: 0), - itemCount: state.videoUsers.value.length, + itemCount: state.cacheUsers.value.length, itemBuilder: (BuildContext ctx, index) { return Stack( children: [ - state.videoUsers.value[index].uid == + state.cacheUsers.value[index].enableCamera == true ? state.cacheUsers.value[index].uid == UserStore.to.userInfoEntity.value!.uid ? AgoraVideoView( controller: VideoViewController( @@ -1559,10 +1602,14 @@ class MeetingMainPageState extends State { rtcEngine: state.rctEngine.value!, canvas: VideoCanvas( uid: int.tryParse( - state.videoUsers.value[index].uid), setupMode: VideoViewSetupMode.videoViewSetupAdd), + state.cacheUsers.value[index].uid), setupMode: VideoViewSetupMode.videoViewSetupAdd), connection: RtcConnection( channelId: state.roomNumber.value), ), + ) + : + Container( + color: Colors.amber, ), Positioned( left: 4, @@ -1570,7 +1617,7 @@ class MeetingMainPageState extends State { child: Row( children: [ Visibility( - visible: state.videoUsers.value[index].uid == UserStore.to.userInfoEntity.value!.uid, + visible: state.cacheUsers.value[index].uid == UserStore.to.userInfoEntity.value!.uid, child: Image.asset( 'assets/images/meeting_main_own.png', width: 24.w, @@ -1585,7 +1632,7 @@ class MeetingMainPageState extends State { decoration: BoxDecoration( borderRadius: BorderRadius.circular(2), color: ColorUtil.Color_0_0_0_96), - child: state.videoUsers.value[index].enableMicr == true + child: state.cacheUsers.value[index].enableMicr == true ? Row( mainAxisAlignment: MainAxisAlignment.center, @@ -1597,7 +1644,7 @@ class MeetingMainPageState extends State { height: 20.h, child: LiquidCustomProgressIndicator( value: - state.videoUsers.value[index] + state.cacheUsers.value[index] .volume ?? 0.0, valueColor: @@ -1611,7 +1658,7 @@ class MeetingMainPageState extends State { .getMicrpphonePath()), ), Text( - state.videoUsers.value[index].userName, + state.cacheUsers.value[index].userName, style: TextStyle( fontSize: 12.sp, color: ColorUtil @@ -1631,7 +1678,187 @@ class MeetingMainPageState extends State { height: 20.h, ), Text( - state.videoUsers.value[index].userName, + state.cacheUsers.value[index].userName, + style: TextStyle( + fontSize: 12.sp, + color: ColorUtil + .Color_255_255_255), + ) + ], + ), + ) + ], + ), + ) + ], + ); + }), + )); + return pageList[position]; + } + + /// 对应页数的界面-全员观看是自己时 + Widget returnPageSelf(int position){ + var pageList = []; + /// 大屏 + pageList.add(Stack( + alignment: Alignment.center, + children: [ + AgoraVideoView( + controller: VideoViewController( + rtcEngine: state.rctEngine.value!, + canvas: const VideoCanvas(uid: 0, setupMode: VideoViewSetupMode.videoViewSetupAdd), + ), + ), + Positioned( + bottom: 110, + child: GestureDetector( + child: Image.asset( + 'assets/images/meeting_main_hang_up.png', + width: 50.w, + height: 50.h, + ), + onTap: () { + + }, + ), + ), + Positioned( + top: 16, + right: 16, + child: Container( + height: 30, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + color: ColorUtil.Color_0_0_0_96), + padding: const EdgeInsets.only(left: 12, right: 12), + child: Row( + children: [ + Text( + '正在讲话:', + style: TextStyle( + fontSize: 10.sp, + color: ColorUtil.Color_185_184_184), + ), + Image.asset( + 'assets/images/meeting_main_speak2.png', + width: 20.w, + height: 20.h, + ), + Text( + '晓晓', + style: TextStyle( + fontSize: 10.sp, + color: ColorUtil.Color_185_184_184), + ) + ], + ), + ), + ), + ], + )); + /// gridview + pageList.add(Container( + color: ColorUtil.Color_57_57_57, + child: GridView.builder( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: 0.8, + crossAxisSpacing: 0), + itemCount: state.cacheUsers.value.length, + itemBuilder: (BuildContext ctx, index) { + return Stack( + children: [ + state.cacheUsers.value[index].enableCamera == true ? state.cacheUsers.value[index].uid == + UserStore.to.userInfoEntity.value!.uid + ? AgoraVideoView( + controller: VideoViewController( + rtcEngine: state.rctEngine.value!, + canvas: const VideoCanvas(uid: 0, setupMode: VideoViewSetupMode.videoViewSetupAdd) + ), + ) + : AgoraVideoView( + controller: VideoViewController.remote( + rtcEngine: state.rctEngine.value!, + canvas: VideoCanvas( + uid: int.tryParse( + state.cacheUsers.value[index].uid), setupMode: VideoViewSetupMode.videoViewSetupAdd), + connection: RtcConnection( + channelId: state.roomNumber.value), + ), + ) + : + Container( + color: Colors.amber, + ), + Positioned( + left: 4, + bottom: 4, + child: Row( + children: [ + Visibility( + visible: state.cacheUsers.value[index].uid == UserStore.to.userInfoEntity.value!.uid, + child: Image.asset( + 'assets/images/meeting_main_own.png', + width: 24.w, + height: 24.h, + ), + ), + Container( + height: 20, + margin: const EdgeInsets.only(left: 4), + padding: + const EdgeInsets.only(left: 4, right: 4), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(2), + color: ColorUtil.Color_0_0_0_96), + child: state.cacheUsers.value[index].enableMicr == true + ? Row( + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + SizedBox( + width: 20.w, + height: 20.h, + child: LiquidCustomProgressIndicator( + value: + state.cacheUsers.value[index] + .volume ?? + 0.0, + valueColor: + const AlwaysStoppedAnimation( + ColorUtil + .Color_2_177_136), + backgroundColor: + ColorUtil.Color_255_255_255, + direction: Axis.vertical, + shapePath: ViewSvgPath + .getMicrpphonePath()), + ), + Text( + state.cacheUsers.value[index].userName, + style: TextStyle( + fontSize: 12.sp, + color: ColorUtil + .Color_255_255_255), + ) + ], + ) + : Row( + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/meeting_main_microphone_open.png', + width: 20.w, + height: 20.h, + ), + Text( + state.cacheUsers.value[index].userName, style: TextStyle( fontSize: 12.sp, color: ColorUtil