From 1938e022077d842906c220f54c30cce17d88de62 Mon Sep 17 00:00:00 2001 From: fuenmao <980740792@qq.com> Date: Mon, 6 Jan 2025 17:41:54 +0800 Subject: [PATCH] =?UTF-8?q?1.6=E6=97=A52-8=E6=9D=A1=E3=80=819=E6=9D=A1BUG?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=EF=BC=8C=E5=88=B7=E6=96=B0token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wgshare/lib/common/api/retrofit_client.dart | 6 + wgshare/lib/common/request/rest_dio.dart | 55 +- wgshare/lib/common/store/app_storage_key.dart | 1 + wgshare/lib/common/store/user_store.dart | 12 + wgshare/lib/pages/loginPage/login_logic.dart | 2 + .../lib/pages/metting/meeting_main_logic.dart | 73 ++- .../lib/pages/metting/meeting_main_state.dart | 5 + .../lib/pages/metting/meeting_main_view.dart | 518 ++++++++++-------- wgshare/lib/pages/userPage/user_logic.dart | 6 - .../Flutter/GeneratedPluginRegistrant.swift | 2 + wgshare/pubspec.lock | 44 +- wgshare/pubspec.yaml | 3 + 12 files changed, 458 insertions(+), 269 deletions(-) diff --git a/wgshare/lib/common/api/retrofit_client.dart b/wgshare/lib/common/api/retrofit_client.dart index c2ed57c..e7e934e 100644 --- a/wgshare/lib/common/api/retrofit_client.dart +++ b/wgshare/lib/common/api/retrofit_client.dart @@ -103,4 +103,10 @@ abstract class RetrofitClient { @Query("enableCamera") bool enableCamera, @Query("uid") String uid, ); + + /// 刷新登录Token + @POST("/auth/refresh") + Future> refreshToken( + @Query("refreshToken") String refreshToken, + ); } diff --git a/wgshare/lib/common/request/rest_dio.dart b/wgshare/lib/common/request/rest_dio.dart index 43c3cb7..0c451a3 100644 --- a/wgshare/lib/common/request/rest_dio.dart +++ b/wgshare/lib/common/request/rest_dio.dart @@ -11,8 +11,13 @@ import 'package:wgshare/utils/toast_utils.dart'; import 'package:wgshare/routes/app_routes.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import '../mixins/request_tool_mixin.dart'; +import '../models/common/base_structure_result.dart'; +import '../models/user_info_entity.dart'; + class RequestTool { static late Dio _dio; + // 初始化请求配置 static _init() { // 自定义 HttpClient @@ -20,16 +25,21 @@ class RequestTool { BaseOptions options = BaseOptions( baseUrl: RequestConfig().baseUrl, - connectTimeout: const Duration(milliseconds: RequestConfig.connectTimeout), - receiveTimeout: const Duration(milliseconds: RequestConfig.receiveTimeout), + connectTimeout: + const Duration(milliseconds: RequestConfig.connectTimeout), + receiveTimeout: + const Duration(milliseconds: RequestConfig.receiveTimeout), ); - _dio = Dio(options)..httpClientAdapter = IOHttpClientAdapter(createHttpClient: () => httpClient); + _dio = Dio(options) + ..httpClientAdapter = + IOHttpClientAdapter(createHttpClient: () => httpClient); _dio.interceptors.add(AuthInterceptor()); // 添加 token _dio.interceptors.add(ResponseHandle()); // 添加 数据返回拦截 _dio.interceptors.add(TheError()); // 添加 数据返回拦截 const isProd = bool.fromEnvironment('dart.vm.product'); if (!isProd && RequestConfig.requestDataPrinting) { - _dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true)); //添加日志 + _dio.interceptors + .add(LogInterceptor(responseBody: true, requestBody: true)); //添加日志 } return RetrofitClient(_dio, baseUrl: RequestConfig().baseUrl); @@ -108,8 +118,10 @@ class ResponseHandle extends Interceptor { var data = response.data; var flag = data != null && - ((data['code'] != null && (data['code'] == 401 || data['code'] == '401')) || - (data['Code'] != null && (data['Code'] == 401 || data['Code'] == '401'))); + ((data['code'] != null && + (data['code'] == 401 || data['code'] == '401')) || + (data['Code'] != null && + (data['Code'] == 401 || data['Code'] == '401'))); if (statusCode == 401 || flag) { Future.delayed(const Duration(seconds: 2), () { @@ -118,7 +130,7 @@ class ResponseHandle extends Interceptor { }); } - if(data['code'] != 200){ + if (data['code'] != 200) { ToastUtils.showError(data['message']); } @@ -126,12 +138,14 @@ class ResponseHandle extends Interceptor { } } -class TheError extends Interceptor { +class TheError extends Interceptor with RequestToolMixin { // late getx.Rx userInfo = UserStore.to.userDetailInfo; @override - void onError(DioException err, ErrorInterceptorHandler handler) { + Future onError( + DioException err, ErrorInterceptorHandler handler) async { var message = '请求错误,请重试'; + int? statusCode; switch (err.type) { case DioExceptionType.connectionTimeout: @@ -152,7 +166,7 @@ class TheError extends Interceptor { } else { Response? response = err.response; if (response != null) { - int? statusCode = response.statusCode; + statusCode = response.statusCode; var errorMap = response.data; // var runtimeType = errorMap.runtimeType; @@ -163,12 +177,11 @@ class TheError extends Interceptor { switch (statusCode) { case 401: message = '用户登录失效,请重新登录'; - - Future.delayed(const Duration(seconds: 2), () { + /*Future.delayed(const Duration(seconds: 2), () { // UserStore.to.erase(); StorageService.to.erase(); getx.Get.offAllNamed(Routes.loginPage); - }); + });*/ break; case 404: message = '无效地址'; @@ -190,11 +203,17 @@ class TheError extends Interceptor { default: message = '请求错误'; } - /* if (message == '用户登录失效,请重新登录' && userInfo.value?.id == null) { - return handler.next(error); - }*/ - - ToastUtils.showError(message); + if (statusCode == 401) { + BaseStructureResult res = await getClient() + .refreshToken(UserStore.to.userInfoEntity.value!.refreshToken); + if (null != res.data) { + UserStore.to.setToken(res.data!.token); + UserStore.to.setRefreshToken(res.data!.refreshToken); + UserStore.to.setUserDetailInfo(res.data!); + } + } else { + ToastUtils.showError(message); + } return handler.next(err); } } diff --git a/wgshare/lib/common/store/app_storage_key.dart b/wgshare/lib/common/store/app_storage_key.dart index 91efc89..9ea9276 100644 --- a/wgshare/lib/common/store/app_storage_key.dart +++ b/wgshare/lib/common/store/app_storage_key.dart @@ -2,6 +2,7 @@ enum AppStorageKey { token(value: 'TOKEN', label: "登录用户的token"), + refreshToken(value: 'REFRESHTOKEN', label: "刷新用的token"), userInfo(value: 'USERINFO', label: "登录用户的基本信息"), account(value: 'ACCOUNT', label: "用户名"), pwd(value: 'PWD', label: "密码"), diff --git a/wgshare/lib/common/store/user_store.dart b/wgshare/lib/common/store/user_store.dart index 908762d..38c9e69 100644 --- a/wgshare/lib/common/store/user_store.dart +++ b/wgshare/lib/common/store/user_store.dart @@ -14,6 +14,9 @@ class UserStore extends GetxController with RequestToolMixin { /// 是否登录 String? token; + /// 刷新用的token + String? refreshToken; + /// 登录类型 String? loginType; @@ -23,6 +26,7 @@ class UserStore extends GetxController with RequestToolMixin { UserStore init() { loginType = StorageService.to.read(AppStorageKey.loginType.value); token = StorageService.to.read(AppStorageKey.token.value); + refreshToken = StorageService.to.read(AppStorageKey.refreshToken.value); try { var userDetail = StorageService.to.read(AppStorageKey.userInfo.value); if (userDetail != null) { @@ -45,6 +49,12 @@ class UserStore extends GetxController with RequestToolMixin { StorageService.to.write(AppStorageKey.token.value, token); } + /// 保存refreshToken + void setRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + StorageService.to.write(AppStorageKey.refreshToken.value, refreshToken); + } + /// 保存登录类型 void setLoginType(String loginType) { this.loginType = loginType; @@ -61,10 +71,12 @@ class UserStore extends GetxController with RequestToolMixin { void erase() { userInfoEntity.value = null; token = null; + refreshToken = null; loginType = null; StorageService.to.write(AppStorageKey.userInfo.value, null); StorageService.to.write(AppStorageKey.token.value, null); + StorageService.to.write(AppStorageKey.refreshToken.value, null); StorageService.to.write(AppStorageKey.loginType.value, null); // StorageService.to.erase(); } diff --git a/wgshare/lib/pages/loginPage/login_logic.dart b/wgshare/lib/pages/loginPage/login_logic.dart index 3b5c9c5..cb4980a 100644 --- a/wgshare/lib/pages/loginPage/login_logic.dart +++ b/wgshare/lib/pages/loginPage/login_logic.dart @@ -60,6 +60,7 @@ class LoginLogic extends GetxController with RequestToolMixin { BaseStructureResult res = await getClient().login(state.userNameController.text, md5.convert(utf8.encode(state.passwordController.text)).toString()); if (null != res.data) { UserStore.to.setToken(res.data!.token); + UserStore.to.setRefreshToken(res.data!.refreshToken); UserStore.to.setUserDetailInfo(res.data!); UserStore.to.setLoginType(AppConfig.NORMAL_LOGIN); Get.offAllNamed(Routes.startPage); @@ -86,6 +87,7 @@ class LoginLogic extends GetxController with RequestToolMixin { BaseStructureResult res = await getClient().anonLogin(await DeviceInfo.getDeviceId(),state.nickNameCodeController.text, state.meetingCodeController.text); if (null != res.data) { UserStore.to.setToken(res.data!.token); + UserStore.to.setRefreshToken(res.data!.refreshToken); UserStore.to.setUserDetailInfo(res.data!); UserStore.to.setLoginType(AppConfig.ANONYMOUS_LOGIN); Get.toNamed(Routes.meetingMainPage, arguments: {"roomNumber": state.meetingCodeController.text}); diff --git a/wgshare/lib/pages/metting/meeting_main_logic.dart b/wgshare/lib/pages/metting/meeting_main_logic.dart index c45b704..662ab29 100644 --- a/wgshare/lib/pages/metting/meeting_main_logic.dart +++ b/wgshare/lib/pages/metting/meeting_main_logic.dart @@ -9,6 +9,7 @@ import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:get/get.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:signalr_core/signalr_core.dart'; +import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:wgshare/common/store/user_store.dart'; import 'package:wgshare/utils/count_microphone_volume.dart'; import '../../common/config/request_config.dart'; @@ -18,6 +19,7 @@ import '../../common/models/meeting_room_info.dart'; import '../../common/models/meeting_room_msg.dart'; import '../../common/models/meeting_room_user.dart'; import '../../common/store/business_store.dart'; +import '../../routes/app_routes.dart'; import '../../utils/agora/AgoraUtil.dart'; import '../../utils/permission/PermissionService.dart'; import '../../utils/toast_utils.dart'; @@ -34,6 +36,9 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { var data = Get.arguments; state.roomNumber.value = data["roomNumber"]; + // 开启屏幕常亮 + WakelockPlus.enable(); + doHttpGetMeetingToken(true); } @@ -45,6 +50,10 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { state.sendMsgController.dispose(); state.pageController.dispose(); stopTime(); + + // 关闭屏幕常亮 + WakelockPlus.disable(); + leaveMeetingToRtc(); leaveMeetingToSocket(); } @@ -152,6 +161,24 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { update(); } + /// 点击grid切换大屏 + void checkLargeScreen(String uid){ + ToastUtils.showSuccess("切换用户成功"); + if(uid == UserStore.to.userInfoEntity.value!.uid) { + state.remoteUid.value = "0"; + }else{ + if(state.isSpeak.value == true && state.isOpenCamera.value == true){ + state.floating.value?.open(Get.context!); + } + state.remoteUid.value = uid; + } + changePageState(0); + Future.delayed(const Duration(milliseconds: 200), () { + changePageState(1); + }); + update(); + } + /// ------------------------------------------------------------------------------发言权限 /// 申请发言权限 Future doHttpApplySpeak() async { @@ -181,6 +208,10 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { /// ------------------------------------------------------------------------------麦克风相关(操作) /// 用户开闭麦 Future doHttpSetMicr(bool isOpenMicrophone) async { + if(isOpenMicrophone == false){ + state.spokesman.value = ""; + state.spokesmanVolume.value = 0; + } await getClient().setMicr(state.roomNumber.value, isOpenMicrophone, UserStore.to.userInfoEntity.value!.uid); } @@ -202,6 +233,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { BaseStructureResult res = await getClient().getTvAnchor(state.roomNumber.value); state.remoteUid.value = res.data!.toString(); + state.remoteAssistantUid.value = res.data!.toString(); debugPrint("wgs输出===:获取当前全员观看主播${res.data}"); if (res.data!.toString().length != 9) { @@ -238,8 +270,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { // 判断当前会议室是否存在全员观看主播 var isCurrentUserIsCamera = false; for (var i = 0; i < state.cacheUsers.value.length; i++) { - if (state.remoteUid.value == state.cacheUsers.value[i].uid && - state.cacheUsers.value[i].enableCamera == true) { + if (state.remoteUid.value == state.cacheUsers.value[i].uid && state.cacheUsers.value[i].enableCamera == true) { isCurrentUserIsCamera = true; } } @@ -254,11 +285,13 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { } else { // 当前会议室不存在全员观看主播时,设置主播ID为空并切换页面到视频状态 debugPrint("wgs输出===:当前会议室不存在全员观看主播时,设置主播ID为空并切换页面到视频状态"); - state.remoteUid.value = ""; + // state.remoteUid.value = ""; + state.remoteAssistantUid.value = ""; changePageState(1); } } } else { + debugPrint("wgs输出===:当前全员观看是共享类型"); if (state.remoteUid.value == UserStore.to.userInfoEntity.value!.screenShareId) { // 如果是自己在共享 @@ -270,6 +303,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { state.cacheUsers.value[i].enableShare = true; } } + changePageState(1); } } update(); @@ -538,7 +572,9 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { } state.users.value = state.cacheUsers.value; update(); - doHttpGetTvAnchor(); + if(listDynamic[0] != UserStore.to.userInfoEntity.value!.uid){ + doHttpGetTvAnchor(); + } debugPrint("wgs输出===:Socket-远端用户或主播离开会议室:$jsonStr"); }); @@ -564,6 +600,20 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { }); }); + /// 强制退出 + state.hubConnection.value?.on("ForceLogout", (e) { + // var jsonStr = const Utf8Decoder().convert(json.encode(uid).runes.toList()); + var jsonStr = json.encode(e); + List listDynamic = jsonDecode(jsonStr); + debugPrint("wgs输出===:Socket-强制退出:${listDynamic[0]}"); + state.isNormaExit.value = true; + ToastUtils.showSuccess("${listDynamic[0]}"); + Future.delayed(const Duration(seconds: 1), () { + UserStore.to.erase(); + Get.offAllNamed(Routes.loginPage); + }); + }); + /// ------------------------------------------------------------------------------会议室聊天相关回调 /// 会议室接收消息回调 state.hubConnection.value?.on("ReceiveMessage", (e) { @@ -574,10 +624,12 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { MeetingRoomMsg meetingRoomMsg = MeetingRoomMsg(list[0], list[1], list[2], 0, formatDate(dateTime, [HH, ':', nn, ':', ss])); state.meetingRoomMsgs.value.add(meetingRoomMsg); + state.msgNum.value = state.msgNum.value += 1; update(); Future.delayed(const Duration(milliseconds: 100), () { state.chatController .jumpTo(state.chatController.position.maxScrollExtent); + state.msgNum.value = 0; }); debugPrint("wgs输出===:Socket-会议室接收消息:$jsonStr"); }); @@ -590,13 +642,17 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { var listDynamic = jsonDecode(jsonStr); MeetingRoomUser meetingRoomUser = MeetingRoomUser.fromJson(listDynamic); if (meetingRoomUser.enableCamera == true) { - debugPrint("wgs输出===:Socket-用户单独开摄像头"); + debugPrint("wgs输出===:Socket-用户单独开摄像头${jsonStr}"); // 遍历会议室用户列表,更改摄像头状态 for (MeetingRoomUser mru in state.cacheUsers.value) { if (mru.uid == meetingRoomUser.uid) { mru.enableCamera = true; } + debugPrint("wgs输出===:Socket-用户单独开摄像头---${state.remoteUid.value}--${meetingRoomUser.uid}"); + if(state.remoteUid.value == meetingRoomUser.uid){ + doHttpGetTvAnchor(); + } } if (meetingRoomUser.uid == UserStore.to.userInfoEntity.value!.uid) { @@ -659,7 +715,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { /// isAgain:是否重新加入 Future joinMeetingToSocket(bool isAgain) async { await state.hubConnection.value?.invoke("joinChannel", - args: [state.roomNumber.value, false, false, false]); + args: [state.roomNumber.value, state.isOpenMicrophone.value, state.isOpenCamera.value, state.isSpeak.value]); mergeFetch(isAgain); /*if(isAgain == false){ mergeFetch(isAgain); @@ -809,13 +865,14 @@ class MeetingMainLogic extends GetxController with RequestToolMixin { for (MeetingRoomUser mru in state.cacheUsers.value) { // 用于更改语音布局里的用户列表麦克风 if (avi.uid == 0) { - //debugPrint("wgs输出===:RTC-用户音量提示(自己):${CountMicrophoneVolume.getVolume(avi.volume!)}"); + // 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}"); + debugPrint("wgs输出===:RTC-用户音量提示(远端用户):${speakers[0].uid}--${speakers[0].volume}"); mru.volume = CountMicrophoneVolume.getVolume(avi.volume!); if (avi.volume != 0) { diff --git a/wgshare/lib/pages/metting/meeting_main_state.dart b/wgshare/lib/pages/metting/meeting_main_state.dart index c8d6d6b..bdfd7b9 100644 --- a/wgshare/lib/pages/metting/meeting_main_state.dart +++ b/wgshare/lib/pages/metting/meeting_main_state.dart @@ -79,6 +79,8 @@ class MeetingMainState { late RxBool isOpenShare = false.obs; /// 当前视频主播ID late RxString remoteUid = "".obs; + /// 当前视频主播ID-辅助判断用 + late RxString remoteAssistantUid = "".obs; /// 是否成功加入会议室 late RxBool isJoinSuccess = false.obs; @@ -90,6 +92,9 @@ class MeetingMainState { /// 聊天数据 late RxList meetingRoomMsgs = RxList([]); + /// 聊天消息未读数量 + late RxInt msgNum = 0.obs; + /// signalR 长连接相关 late RxString serviceUrl = "http://192.168.2.9:5192/session-manage".obs; late Rx hubConnection = Rx(null); diff --git a/wgshare/lib/pages/metting/meeting_main_view.dart b/wgshare/lib/pages/metting/meeting_main_view.dart index c5eff3c..0104662 100644 --- a/wgshare/lib/pages/metting/meeting_main_view.dart +++ b/wgshare/lib/pages/metting/meeting_main_view.dart @@ -303,13 +303,13 @@ class MeetingMainPageState extends State { MainAxisAlignment.spaceBetween, children: [ GestureDetector( - child: Container( + child: Container( width: 200.w, height: 40.h, margin: const EdgeInsets.only( left: 20, bottom: 40), padding: - const EdgeInsets.only(left: 20), + const EdgeInsets.only(left: 20), decoration: BoxDecoration( borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(56), @@ -319,26 +319,50 @@ class MeetingMainPageState extends State { border: Border.all( width: 1.w, color: - ColorUtil.Color_99_111_158), + ColorUtil.Color_99_111_158), ), child: Row( crossAxisAlignment: - CrossAxisAlignment.center, + CrossAxisAlignment.center, mainAxisAlignment: - MainAxisAlignment.start, + MainAxisAlignment.spaceBetween, children: [ - Image.asset( - 'assets/images/meeting_main_chat.png', - width: 18.w, - height: 18.h, + 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), + ) + ], ), - 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), + ) + ), ) ], ), @@ -347,6 +371,9 @@ class MeetingMainPageState extends State { Get.bottomSheet( isScrollControlled: true, chatBottomSheet(context)); + + state.msgNum.value = 0; + Future.delayed( const Duration(milliseconds: 100), () { @@ -400,57 +427,61 @@ class MeetingMainPageState extends State { children: [ /// 音频 GestureDetector( - 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( + 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 - ? '申请发言' - : state.isOpenMicrophone.value == - true - ? "手动静音" - : "解除静音", - style: TextStyle( - fontSize: 12.sp, - color: ColorUtil.Color_202_202_202), - ) - ], + ? 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) { @@ -471,31 +502,35 @@ class MeetingMainPageState extends State { /// 视频 GestureDetector( - 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 + 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) { @@ -549,22 +584,26 @@ class MeetingMainPageState extends State { /// 成员 GestureDetector( - 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), - ) - ], + 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( @@ -1626,7 +1665,7 @@ class MeetingMainPageState extends State { return Stack( alignment: Alignment.center, children: [ - state.remoteUid.value != "" + state.remoteAssistantUid.value != "" ? AgoraVideoView( controller: VideoViewController( rtcEngine: state.rctEngine.value!, @@ -1708,139 +1747,148 @@ class MeetingMainPageState extends State { 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)), + return GestureDetector( + child: 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: ColorUtil.Color_16_19_13, + child: SizedBox( + width: double.infinity, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/metting_main_no_person.png', + width: 78.w, + height: 84.h, + ), + const SizedBox(height: 12), + Text( + '该用户未开启摄像头...', + style: TextStyle( + color: ColorUtil.Color_255_255_255, + fontSize: 10.sp), ) - : 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: ColorUtil.Color_16_19_13, - child: SizedBox( - width: double.infinity, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - 'assets/images/metting_main_no_person.png', - width: 78.w, - height: 84.h, - ), - const SizedBox(height: 12), - Text( - '该用户未开启摄像头...', - style: TextStyle( - color: ColorUtil.Color_255_255_255, - fontSize: 10.sp), - ) - ], + ], + ), + ), + ), + 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, ), ), - ), - 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()), - ), - SizedBox( - width: 70, - child: Text( - state - .cacheUsers.value[index].userName, - maxLines: 1, - overflow: TextOverflow.ellipsis, - 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, - ), - SizedBox( - width: 70, - child: Text( - state - .cacheUsers.value[index].userName, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 12.sp, - color: - ColorUtil.Color_255_255_255), - )) - ], + 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()), ), - ) - ], - ), - ) - ], + SizedBox( + width: 70, + child: Text( + state + .cacheUsers.value[index].userName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + 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, + ), + SizedBox( + width: 70, + child: Text( + state + .cacheUsers.value[index].userName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 12.sp, + color: + ColorUtil.Color_255_255_255), + )) + ], + ), + ) + ], + ), + ) + ], + ), + onTap: (){ + if(state.cacheUsers.value[index].enableCamera == true){ + logic.checkLargeScreen(state.cacheUsers.value[index].uid); + }else{ + ToastUtils.showError("该用户暂未开启摄像头"); + } + }, ); }), ); diff --git a/wgshare/lib/pages/userPage/user_logic.dart b/wgshare/lib/pages/userPage/user_logic.dart index 41b1b09..04063cd 100644 --- a/wgshare/lib/pages/userPage/user_logic.dart +++ b/wgshare/lib/pages/userPage/user_logic.dart @@ -7,10 +7,4 @@ import 'user_state.dart'; class UserLogic extends GetxController with RequestToolMixin { final UserState state = UserState(); - - /// 退出登录 - void logout(){ - UserStore.to.erase(); - Get.toNamed(Routes.loginPage); - } } diff --git a/wgshare/macos/Flutter/GeneratedPluginRegistrant.swift b/wgshare/macos/Flutter/GeneratedPluginRegistrant.swift index 0210b80..88d3da2 100644 --- a/wgshare/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/wgshare/macos/Flutter/GeneratedPluginRegistrant.swift @@ -17,6 +17,7 @@ import macos_window_utils import package_info_plus import path_provider_foundation import sqflite_darwin +import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { AgoraRtcNgPlugin.register(with: registry.registrar(forPlugin: "AgoraRtcNgPlugin")) @@ -31,4 +32,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) } diff --git a/wgshare/pubspec.lock b/wgshare/pubspec.lock index 6a0ee48..63eab2e 100644 --- a/wgshare/pubspec.lock +++ b/wgshare/pubspec.lock @@ -254,6 +254,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.9" + dbus: + dependency: transitive + description: + name: dbus + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.7.10" device_info_plus: dependency: "direct main" description: @@ -694,10 +702,10 @@ packages: dependency: transitive description: name: js - sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.flutter-io.cn" source: hosted - version: "0.7.1" + version: "0.6.7" json_annotation: dependency: "direct main" description: @@ -962,6 +970,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.0.2" photo_view: dependency: "direct main" description: @@ -1295,6 +1311,22 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "14.2.5" + wakelock_plus: + dependency: "direct main" + description: + name: wakelock_plus + sha256: "36c88af0b930121941345306d259ec4cc4ecca3b151c02e3a9e71aede83c615e" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.10" + wakelock_plus_platform_interface: + dependency: transitive + description: + name: wakelock_plus_platform_interface + sha256: "70e780bc99796e1db82fe764b1e7dcb89a86f1e5b3afb1db354de50f2e41eb7a" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.2" watcher: dependency: transitive description: @@ -1343,6 +1375,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.5.0" yaml: dependency: transitive description: diff --git a/wgshare/pubspec.yaml b/wgshare/pubspec.yaml index f65eaa4..b4c2228 100644 --- a/wgshare/pubspec.yaml +++ b/wgshare/pubspec.yaml @@ -101,6 +101,9 @@ dependencies: # 后台下载 al_downloader: ^1.8.2 + # 屏幕常亮 + wakelock_plus: ^1.2.10 + dev_dependencies: flutter_test: sdk: flutter