Compare commits

...

2 Commits

Author SHA1 Message Date
fuenmao 363fd0b77c Merge branch 'master' of https://gitea.23544.com/marking/WGShare.Mobile.Flutter
# Conflicts:
#	wgshare/pubspec.lock
2025-01-06 17:42:25 +08:00
fuenmao 1938e02207 1.6日2-8条、9条BUG解决,刷新token 2025-01-06 17:41:54 +08:00
12 changed files with 705 additions and 516 deletions

View File

@ -103,4 +103,10 @@ abstract class RetrofitClient {
@Query("enableCamera") bool enableCamera, @Query("enableCamera") bool enableCamera,
@Query("uid") String uid, @Query("uid") String uid,
); );
/// Token
@POST("/auth/refresh")
Future<BaseStructureResult<UserInfoEntity>> refreshToken(
@Query("refreshToken") String refreshToken,
);
} }

View File

@ -11,8 +11,13 @@ import 'package:wgshare/utils/toast_utils.dart';
import 'package:wgshare/routes/app_routes.dart'; import 'package:wgshare/routes/app_routes.dart';
import 'package:package_info_plus/package_info_plus.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 { class RequestTool {
static late Dio _dio; static late Dio _dio;
// //
static _init() { static _init() {
// HttpClient // HttpClient
@ -20,16 +25,21 @@ class RequestTool {
BaseOptions options = BaseOptions( BaseOptions options = BaseOptions(
baseUrl: RequestConfig().baseUrl, baseUrl: RequestConfig().baseUrl,
connectTimeout: const Duration(milliseconds: RequestConfig.connectTimeout), connectTimeout:
receiveTimeout: const Duration(milliseconds: RequestConfig.receiveTimeout), 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(AuthInterceptor()); // token
_dio.interceptors.add(ResponseHandle()); // _dio.interceptors.add(ResponseHandle()); //
_dio.interceptors.add(TheError()); // _dio.interceptors.add(TheError()); //
const isProd = bool.fromEnvironment('dart.vm.product'); const isProd = bool.fromEnvironment('dart.vm.product');
if (!isProd && RequestConfig.requestDataPrinting) { 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); return RetrofitClient(_dio, baseUrl: RequestConfig().baseUrl);
@ -108,8 +118,10 @@ class ResponseHandle extends Interceptor {
var data = response.data; var data = response.data;
var flag = data != null && var flag = data != null &&
((data['code'] != null && (data['code'] == 401 || data['code'] == '401')) || ((data['code'] != null &&
(data['Code'] != null && (data['Code'] == 401 || data['Code'] == '401'))); (data['code'] == 401 || data['code'] == '401')) ||
(data['Code'] != null &&
(data['Code'] == 401 || data['Code'] == '401')));
if (statusCode == 401 || flag) { if (statusCode == 401 || flag) {
Future.delayed(const Duration(seconds: 2), () { 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']); 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<UserInfoDetail?> userInfo = UserStore.to.userDetailInfo; // late getx.Rx<UserInfoDetail?> userInfo = UserStore.to.userDetailInfo;
@override @override
void onError(DioException err, ErrorInterceptorHandler handler) { Future<void> onError(
DioException err, ErrorInterceptorHandler handler) async {
var message = '请求错误,请重试'; var message = '请求错误,请重试';
int? statusCode;
switch (err.type) { switch (err.type) {
case DioExceptionType.connectionTimeout: case DioExceptionType.connectionTimeout:
@ -152,7 +166,7 @@ class TheError extends Interceptor {
} else { } else {
Response? response = err.response; Response? response = err.response;
if (response != null) { if (response != null) {
int? statusCode = response.statusCode; statusCode = response.statusCode;
var errorMap = response.data; var errorMap = response.data;
// var runtimeType = errorMap.runtimeType; // var runtimeType = errorMap.runtimeType;
@ -163,12 +177,11 @@ class TheError extends Interceptor {
switch (statusCode) { switch (statusCode) {
case 401: case 401:
message = '用户登录失效,请重新登录'; message = '用户登录失效,请重新登录';
/*Future.delayed(const Duration(seconds: 2), () {
Future.delayed(const Duration(seconds: 2), () {
// UserStore.to.erase(); // UserStore.to.erase();
StorageService.to.erase(); StorageService.to.erase();
getx.Get.offAllNamed(Routes.loginPage); getx.Get.offAllNamed(Routes.loginPage);
}); });*/
break; break;
case 404: case 404:
message = '无效地址'; message = '无效地址';
@ -190,11 +203,17 @@ class TheError extends Interceptor {
default: default:
message = '请求错误'; message = '请求错误';
} }
/* if (message == '用户登录失效,请重新登录' && userInfo.value?.id == null) { if (statusCode == 401) {
return handler.next(error); BaseStructureResult<UserInfoEntity> res = await getClient()
}*/ .refreshToken(UserStore.to.userInfoEntity.value!.refreshToken);
if (null != res.data) {
ToastUtils.showError(message); 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); return handler.next(err);
} }
} }

View File

@ -2,6 +2,7 @@
enum AppStorageKey { enum AppStorageKey {
token(value: 'TOKEN', label: "登录用户的token"), token(value: 'TOKEN', label: "登录用户的token"),
refreshToken(value: 'REFRESHTOKEN', label: "刷新用的token"),
userInfo(value: 'USERINFO', label: "登录用户的基本信息"), userInfo(value: 'USERINFO', label: "登录用户的基本信息"),
account(value: 'ACCOUNT', label: "用户名"), account(value: 'ACCOUNT', label: "用户名"),
pwd(value: 'PWD', label: "密码"), pwd(value: 'PWD', label: "密码"),

View File

@ -14,6 +14,9 @@ class UserStore extends GetxController with RequestToolMixin {
/// ///
String? token; String? token;
/// token
String? refreshToken;
/// ///
String? loginType; String? loginType;
@ -23,6 +26,7 @@ class UserStore extends GetxController with RequestToolMixin {
UserStore init() { UserStore init() {
loginType = StorageService.to.read(AppStorageKey.loginType.value); loginType = StorageService.to.read(AppStorageKey.loginType.value);
token = StorageService.to.read(AppStorageKey.token.value); token = StorageService.to.read(AppStorageKey.token.value);
refreshToken = StorageService.to.read(AppStorageKey.refreshToken.value);
try { try {
var userDetail = StorageService.to.read(AppStorageKey.userInfo.value); var userDetail = StorageService.to.read(AppStorageKey.userInfo.value);
if (userDetail != null) { if (userDetail != null) {
@ -45,6 +49,12 @@ class UserStore extends GetxController with RequestToolMixin {
StorageService.to.write(AppStorageKey.token.value, token); 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) { void setLoginType(String loginType) {
this.loginType = loginType; this.loginType = loginType;
@ -61,10 +71,12 @@ class UserStore extends GetxController with RequestToolMixin {
void erase() { void erase() {
userInfoEntity.value = null; userInfoEntity.value = null;
token = null; token = null;
refreshToken = null;
loginType = null; loginType = null;
StorageService.to.write(AppStorageKey.userInfo.value, null); StorageService.to.write(AppStorageKey.userInfo.value, null);
StorageService.to.write(AppStorageKey.token.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.write(AppStorageKey.loginType.value, null);
// StorageService.to.erase(); // StorageService.to.erase();
} }

View File

@ -60,6 +60,7 @@ class LoginLogic extends GetxController with RequestToolMixin {
BaseStructureResult<UserInfoEntity> res = await getClient().login(state.userNameController.text, md5.convert(utf8.encode(state.passwordController.text)).toString()); BaseStructureResult<UserInfoEntity> res = await getClient().login(state.userNameController.text, md5.convert(utf8.encode(state.passwordController.text)).toString());
if (null != res.data) { if (null != res.data) {
UserStore.to.setToken(res.data!.token); UserStore.to.setToken(res.data!.token);
UserStore.to.setRefreshToken(res.data!.refreshToken);
UserStore.to.setUserDetailInfo(res.data!); UserStore.to.setUserDetailInfo(res.data!);
UserStore.to.setLoginType(AppConfig.NORMAL_LOGIN); UserStore.to.setLoginType(AppConfig.NORMAL_LOGIN);
Get.offAllNamed(Routes.startPage); Get.offAllNamed(Routes.startPage);
@ -86,6 +87,7 @@ class LoginLogic extends GetxController with RequestToolMixin {
BaseStructureResult<UserInfoEntity> res = await getClient().anonLogin(await DeviceInfo.getDeviceId(),state.nickNameCodeController.text, state.meetingCodeController.text); BaseStructureResult<UserInfoEntity> res = await getClient().anonLogin(await DeviceInfo.getDeviceId(),state.nickNameCodeController.text, state.meetingCodeController.text);
if (null != res.data) { if (null != res.data) {
UserStore.to.setToken(res.data!.token); UserStore.to.setToken(res.data!.token);
UserStore.to.setRefreshToken(res.data!.refreshToken);
UserStore.to.setUserDetailInfo(res.data!); UserStore.to.setUserDetailInfo(res.data!);
UserStore.to.setLoginType(AppConfig.ANONYMOUS_LOGIN); UserStore.to.setLoginType(AppConfig.ANONYMOUS_LOGIN);
Get.toNamed(Routes.meetingMainPage, arguments: {"roomNumber": state.meetingCodeController.text}); Get.toNamed(Routes.meetingMainPage, arguments: {"roomNumber": state.meetingCodeController.text});

View File

@ -9,6 +9,7 @@ import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:signalr_core/signalr_core.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/common/store/user_store.dart';
import 'package:wgshare/utils/count_microphone_volume.dart'; import 'package:wgshare/utils/count_microphone_volume.dart';
import '../../common/config/request_config.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_msg.dart';
import '../../common/models/meeting_room_user.dart'; import '../../common/models/meeting_room_user.dart';
import '../../common/store/business_store.dart'; import '../../common/store/business_store.dart';
import '../../routes/app_routes.dart';
import '../../utils/agora/AgoraUtil.dart'; import '../../utils/agora/AgoraUtil.dart';
import '../../utils/permission/PermissionService.dart'; import '../../utils/permission/PermissionService.dart';
import '../../utils/toast_utils.dart'; import '../../utils/toast_utils.dart';
@ -34,6 +36,9 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
var data = Get.arguments; var data = Get.arguments;
state.roomNumber.value = data["roomNumber"]; state.roomNumber.value = data["roomNumber"];
//
WakelockPlus.enable();
doHttpGetMeetingToken(true); doHttpGetMeetingToken(true);
} }
@ -45,6 +50,10 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
state.sendMsgController.dispose(); state.sendMsgController.dispose();
state.pageController.dispose(); state.pageController.dispose();
stopTime(); stopTime();
//
WakelockPlus.disable();
leaveMeetingToRtc(); leaveMeetingToRtc();
leaveMeetingToSocket(); leaveMeetingToSocket();
} }
@ -152,6 +161,24 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
update(); 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<void> doHttpApplySpeak() async { Future<void> doHttpApplySpeak() async {
@ -181,6 +208,10 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
/// ------------------------------------------------------------------------------ /// ------------------------------------------------------------------------------
/// ///
Future<void> doHttpSetMicr(bool isOpenMicrophone) async { Future<void> doHttpSetMicr(bool isOpenMicrophone) async {
if(isOpenMicrophone == false){
state.spokesman.value = "";
state.spokesmanVolume.value = 0;
}
await getClient().setMicr(state.roomNumber.value, isOpenMicrophone, await getClient().setMicr(state.roomNumber.value, isOpenMicrophone,
UserStore.to.userInfoEntity.value!.uid); UserStore.to.userInfoEntity.value!.uid);
} }
@ -202,6 +233,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
BaseStructureResult res = BaseStructureResult res =
await getClient().getTvAnchor(state.roomNumber.value); await getClient().getTvAnchor(state.roomNumber.value);
state.remoteUid.value = res.data!.toString(); state.remoteUid.value = res.data!.toString();
state.remoteAssistantUid.value = res.data!.toString();
debugPrint("wgs输出===:获取当前全员观看主播${res.data}"); debugPrint("wgs输出===:获取当前全员观看主播${res.data}");
if (res.data!.toString().length != 9) { if (res.data!.toString().length != 9) {
@ -238,8 +270,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
// //
var isCurrentUserIsCamera = false; var isCurrentUserIsCamera = false;
for (var i = 0; i < state.cacheUsers.value.length; i++) { for (var i = 0; i < state.cacheUsers.value.length; i++) {
if (state.remoteUid.value == state.cacheUsers.value[i].uid && if (state.remoteUid.value == state.cacheUsers.value[i].uid && state.cacheUsers.value[i].enableCamera == true) {
state.cacheUsers.value[i].enableCamera == true) {
isCurrentUserIsCamera = true; isCurrentUserIsCamera = true;
} }
} }
@ -254,11 +285,13 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
} else { } else {
// ID为空并切换页面到视频状态 // ID为空并切换页面到视频状态
debugPrint("wgs输出===当前会议室不存在全员观看主播时设置主播ID为空并切换页面到视频状态"); debugPrint("wgs输出===当前会议室不存在全员观看主播时设置主播ID为空并切换页面到视频状态");
state.remoteUid.value = ""; // state.remoteUid.value = "";
state.remoteAssistantUid.value = "";
changePageState(1); changePageState(1);
} }
} }
} else { } else {
debugPrint("wgs输出===:当前全员观看是共享类型");
if (state.remoteUid.value == if (state.remoteUid.value ==
UserStore.to.userInfoEntity.value!.screenShareId) { UserStore.to.userInfoEntity.value!.screenShareId) {
// //
@ -270,6 +303,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
state.cacheUsers.value[i].enableShare = true; state.cacheUsers.value[i].enableShare = true;
} }
} }
changePageState(1);
} }
} }
update(); update();
@ -538,7 +572,9 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
} }
state.users.value = state.cacheUsers.value; state.users.value = state.cacheUsers.value;
update(); update();
doHttpGetTvAnchor(); if(listDynamic[0] != UserStore.to.userInfoEntity.value!.uid){
doHttpGetTvAnchor();
}
debugPrint("wgs输出===Socket-远端用户或主播离开会议室:$jsonStr"); 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) { 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], MeetingRoomMsg meetingRoomMsg = MeetingRoomMsg(list[0], list[1], list[2],
0, formatDate(dateTime, [HH, ':', nn, ':', ss])); 0, formatDate(dateTime, [HH, ':', nn, ':', ss]));
state.meetingRoomMsgs.value.add(meetingRoomMsg); state.meetingRoomMsgs.value.add(meetingRoomMsg);
state.msgNum.value = state.msgNum.value += 1;
update(); update();
Future.delayed(const Duration(milliseconds: 100), () { Future.delayed(const Duration(milliseconds: 100), () {
state.chatController state.chatController
.jumpTo(state.chatController.position.maxScrollExtent); .jumpTo(state.chatController.position.maxScrollExtent);
state.msgNum.value = 0;
}); });
debugPrint("wgs输出===Socket-会议室接收消息:$jsonStr"); debugPrint("wgs输出===Socket-会议室接收消息:$jsonStr");
}); });
@ -590,13 +642,17 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
var listDynamic = jsonDecode(jsonStr); var listDynamic = jsonDecode(jsonStr);
MeetingRoomUser meetingRoomUser = MeetingRoomUser.fromJson(listDynamic); MeetingRoomUser meetingRoomUser = MeetingRoomUser.fromJson(listDynamic);
if (meetingRoomUser.enableCamera == true) { if (meetingRoomUser.enableCamera == true) {
debugPrint("wgs输出===Socket-用户单独开摄像头"); debugPrint("wgs输出===Socket-用户单独开摄像头${jsonStr}");
// //
for (MeetingRoomUser mru in state.cacheUsers.value) { for (MeetingRoomUser mru in state.cacheUsers.value) {
if (mru.uid == meetingRoomUser.uid) { if (mru.uid == meetingRoomUser.uid) {
mru.enableCamera = true; 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) { if (meetingRoomUser.uid == UserStore.to.userInfoEntity.value!.uid) {
@ -659,7 +715,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
/// isAgain /// isAgain
Future<void> joinMeetingToSocket(bool isAgain) async { Future<void> joinMeetingToSocket(bool isAgain) async {
await state.hubConnection.value?.invoke("joinChannel", 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); mergeFetch(isAgain);
/*if(isAgain == false){ /*if(isAgain == false){
mergeFetch(isAgain); mergeFetch(isAgain);
@ -809,13 +865,14 @@ class MeetingMainLogic extends GetxController with RequestToolMixin {
for (MeetingRoomUser mru in state.cacheUsers.value) { for (MeetingRoomUser mru in state.cacheUsers.value) {
// //
if (avi.uid == 0) { if (avi.uid == 0) {
//debugPrint("wgs输出===RTC-用户音量提示(自己):${CountMicrophoneVolume.getVolume(avi.volume!)}"); // debugPrint("wgs输出===RTC-用户音量提示(自己):${CountMicrophoneVolume.getVolume(avi.volume!)}");
mru.volume = CountMicrophoneVolume.getVolume(avi.volume!); mru.volume = CountMicrophoneVolume.getVolume(avi.volume!);
state.microphoneVolume.value = state.microphoneVolume.value =
CountMicrophoneVolume.getVolume(avi.volume!); CountMicrophoneVolume.getVolume(avi.volume!);
} else { } else {
debugPrint("wgs输出===RTC-用户音量提示:${avi.uid}--${mru.uid}");
if (avi.uid.toString() == 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!); mru.volume = CountMicrophoneVolume.getVolume(avi.volume!);
if (avi.volume != 0) { if (avi.volume != 0) {

View File

@ -79,6 +79,8 @@ class MeetingMainState {
late RxBool isOpenShare = false.obs; late RxBool isOpenShare = false.obs;
/// ID /// ID
late RxString remoteUid = "".obs; late RxString remoteUid = "".obs;
/// ID-
late RxString remoteAssistantUid = "".obs;
/// ///
late RxBool isJoinSuccess = false.obs; late RxBool isJoinSuccess = false.obs;
@ -90,6 +92,9 @@ class MeetingMainState {
/// ///
late RxList<MeetingRoomMsg> meetingRoomMsgs = RxList([]); late RxList<MeetingRoomMsg> meetingRoomMsgs = RxList([]);
///
late RxInt msgNum = 0.obs;
/// signalR /// signalR
late RxString serviceUrl = "http://192.168.2.9:5192/session-manage".obs; late RxString serviceUrl = "http://192.168.2.9:5192/session-manage".obs;
late Rx<HubConnection?> hubConnection = Rx(null); late Rx<HubConnection?> hubConnection = Rx(null);

View File

@ -303,13 +303,13 @@ class MeetingMainPageState extends State<MeetingMainPage> {
MainAxisAlignment.spaceBetween, MainAxisAlignment.spaceBetween,
children: [ children: [
GestureDetector( GestureDetector(
child: Container( child: Container(
width: 200.w, width: 200.w,
height: 40.h, height: 40.h,
margin: const EdgeInsets.only( margin: const EdgeInsets.only(
left: 20, bottom: 40), left: 20, bottom: 40),
padding: padding:
const EdgeInsets.only(left: 20), const EdgeInsets.only(left: 20),
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(56), bottomLeft: Radius.circular(56),
@ -319,26 +319,50 @@ class MeetingMainPageState extends State<MeetingMainPage> {
border: Border.all( border: Border.all(
width: 1.w, width: 1.w,
color: color:
ColorUtil.Color_99_111_158), ColorUtil.Color_99_111_158),
), ),
child: Row( child: Row(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.center, CrossAxisAlignment.center,
mainAxisAlignment: mainAxisAlignment:
MainAxisAlignment.start, MainAxisAlignment.spaceBetween,
children: [ children: [
Image.asset( Row(
'assets/images/meeting_main_chat.png', children: [
width: 18.w, Image.asset(
height: 18.h, '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), Visibility(
Text( visible: state.msgNum.value > 0 ? true : false,
'说点什么...', child: Container(
style: TextStyle( width: 18.w,
fontSize: 14.sp, height: 18.h,
color: ColorUtil alignment: Alignment.center,
.Color_156_156_156), 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<MeetingMainPage> {
Get.bottomSheet( Get.bottomSheet(
isScrollControlled: true, isScrollControlled: true,
chatBottomSheet(context)); chatBottomSheet(context));
state.msgNum.value = 0;
Future.delayed( Future.delayed(
const Duration(milliseconds: 100), const Duration(milliseconds: 100),
() { () {
@ -400,57 +427,61 @@ class MeetingMainPageState extends State<MeetingMainPage> {
children: [ children: [
/// ///
GestureDetector( GestureDetector(
child: Column( child: Container(
mainAxisAlignment: MainAxisAlignment.center, padding: const EdgeInsets.only(left: 6,right: 6),
children: [ color: ColorUtil.Color_0_0_0_0,
state.isSpeak.value == false child: Column(
? Image.asset( mainAxisAlignment: MainAxisAlignment.center,
state.isSpeak.value == false children: [
? '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.isSpeak.value == false
? '申请发言' ? Image.asset(
: state.isOpenMicrophone.value == state.isSpeak.value == false
true ? 'assets/images/meeting_main_sqfy.png'
? "手动静音" : state.isOpenMicrophone
: "解除静音", .value ==
style: TextStyle( true
fontSize: 12.sp, ? 'assets/images/meeting_main_microphone_default.png'
color: ColorUtil.Color_202_202_202), : '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: () { onTap: () {
if (state.isSpeak.value == false) { if (state.isSpeak.value == false) {
@ -471,31 +502,35 @@ class MeetingMainPageState extends State<MeetingMainPage> {
/// ///
GestureDetector( GestureDetector(
child: Column( child: Container(
mainAxisAlignment: MainAxisAlignment.center, padding: const EdgeInsets.only(left: 6,right: 6),
children: [ color: ColorUtil.Color_0_0_0_0,
Image.asset( child: Column(
state.isSpeak.value == true mainAxisAlignment: MainAxisAlignment.center,
? state.isOpenCamera.value == true children: [
? 'assets/images/meeting_main_camera_open.png' Image.asset(
: 'assets/images/meeting_main_camera_default.png' state.isSpeak.value == true
: 'assets/images/meeting_main_sp.png', ? state.isOpenCamera.value == true
width: 22.w, ? 'assets/images/meeting_main_camera_open.png'
height: 22.h, : 'assets/images/meeting_main_camera_default.png'
), : 'assets/images/meeting_main_sp.png',
SizedBox(height: 4.h), width: 22.w,
Text( height: 22.h,
/*state.isSpeak.value == false ),
SizedBox(height: 4.h),
Text(
/*state.isSpeak.value == false
? '申请发言' ? '申请发言'
: */ : */
state.isOpenCamera.value == true state.isOpenCamera.value == true
? "关闭视频" ? "关闭视频"
: "开启视频", : "开启视频",
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: ColorUtil.Color_202_202_202), color: ColorUtil.Color_202_202_202),
) )
], ],
),
), ),
onTap: () { onTap: () {
if (state.isSpeak.value == false) { if (state.isSpeak.value == false) {
@ -549,22 +584,26 @@ class MeetingMainPageState extends State<MeetingMainPage> {
/// ///
GestureDetector( GestureDetector(
child: Column( child: Container(
mainAxisAlignment: MainAxisAlignment.center, padding: const EdgeInsets.only(left: 6,right: 6),
children: [ color: ColorUtil.Color_0_0_0_0,
Image.asset( child: Column(
'assets/images/meeting_main_member_default.png', mainAxisAlignment: MainAxisAlignment.center,
width: 22.w, children: [
height: 22.h, Image.asset(
), 'assets/images/meeting_main_member_default.png',
SizedBox(height: 4.h), width: 22.w,
Text( height: 22.h,
' 成员 ', ),
style: TextStyle( SizedBox(height: 4.h),
fontSize: 12.sp, Text(
color: ColorUtil.Color_202_202_202), ' 成员 ',
) style: TextStyle(
], fontSize: 12.sp,
color: ColorUtil.Color_202_202_202),
)
],
),
), ),
onTap: () { onTap: () {
Get.bottomSheet( Get.bottomSheet(
@ -1626,7 +1665,7 @@ class MeetingMainPageState extends State<MeetingMainPage> {
return Stack( return Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
state.remoteUid.value != "" state.remoteAssistantUid.value != ""
? AgoraVideoView( ? AgoraVideoView(
controller: VideoViewController( controller: VideoViewController(
rtcEngine: state.rctEngine.value!, rtcEngine: state.rctEngine.value!,
@ -1708,139 +1747,148 @@ class MeetingMainPageState extends State<MeetingMainPage> {
crossAxisCount: 2, childAspectRatio: 0.8, crossAxisSpacing: 0), crossAxisCount: 2, childAspectRatio: 0.8, crossAxisSpacing: 0),
itemCount: state.cacheUsers.value.length, itemCount: state.cacheUsers.value.length,
itemBuilder: (BuildContext ctx, index) { itemBuilder: (BuildContext ctx, index) {
return Stack( return GestureDetector(
children: [ child: Stack(
state.cacheUsers.value[index].enableCamera == true children: [
? state.cacheUsers.value[index].uid == state.cacheUsers.value[index].enableCamera == true
UserStore.to.userInfoEntity.value!.uid ? state.cacheUsers.value[index].uid ==
? AgoraVideoView( UserStore.to.userInfoEntity.value!.uid
controller: VideoViewController( ? AgoraVideoView(
rtcEngine: state.rctEngine.value!, controller: VideoViewController(
canvas: const VideoCanvas( rtcEngine: state.rctEngine.value!,
uid: 0, canvas: const VideoCanvas(
setupMode: VideoViewSetupMode uid: 0,
.videoViewSetupAdd)), 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( Positioned(
state.cacheUsers.value[index].uid), left: 4,
setupMode: bottom: 4,
VideoViewSetupMode.videoViewSetupAdd), child: Row(
connection: RtcConnection( children: [
channelId: state.roomNumber.value), Visibility(
), visible: state.cacheUsers.value[index].uid ==
) UserStore.to.userInfoEntity.value!.uid,
: Container( child: Image.asset(
color: ColorUtil.Color_16_19_13, 'assets/images/meeting_main_own.png',
child: SizedBox( width: 24.w,
width: double.infinity, height: 24.h,
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),
)
],
), ),
), ),
), Container(
Positioned( height: 20,
left: 4, margin: const EdgeInsets.only(left: 4),
bottom: 4, padding: const EdgeInsets.only(left: 4, right: 4),
child: Row( decoration: BoxDecoration(
children: [ borderRadius: BorderRadius.circular(2),
Visibility( color: ColorUtil.Color_0_0_0_96),
visible: state.cacheUsers.value[index].uid == child: state.cacheUsers.value[index].enableMicr ==
UserStore.to.userInfoEntity.value!.uid, true
child: Image.asset( ? Row(
'assets/images/meeting_main_own.png', mainAxisAlignment: MainAxisAlignment.center,
width: 24.w, crossAxisAlignment: CrossAxisAlignment.center,
height: 24.h, children: [
), SizedBox(
), width: 20.w,
Container( height: 20.h,
height: 20, child: LiquidCustomProgressIndicator(
margin: const EdgeInsets.only(left: 4), value: state.cacheUsers.value[index]
padding: const EdgeInsets.only(left: 4, right: 4), .volume ??
decoration: BoxDecoration( 0.0,
borderRadius: BorderRadius.circular(2), valueColor:
color: ColorUtil.Color_0_0_0_96), const AlwaysStoppedAnimation(
child: state.cacheUsers.value[index].enableMicr == ColorUtil.Color_2_177_136),
true backgroundColor:
? Row( ColorUtil.Color_255_255_255,
mainAxisAlignment: MainAxisAlignment.center, direction: Axis.vertical,
crossAxisAlignment: CrossAxisAlignment.center, shapePath:
children: [ ViewSvgPath.getMicrpphonePath()),
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),
))
],
), ),
) 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("该用户暂未开启摄像头");
}
},
); );
}), }),
); );

View File

@ -7,10 +7,4 @@ import 'user_state.dart';
class UserLogic extends GetxController with RequestToolMixin { class UserLogic extends GetxController with RequestToolMixin {
final UserState state = UserState(); final UserState state = UserState();
/// 退
void logout(){
UserStore.to.erase();
Get.toNamed(Routes.loginPage);
}
} }

View File

@ -17,6 +17,7 @@ import macos_window_utils
import package_info_plus import package_info_plus
import path_provider_foundation import path_provider_foundation
import sqflite_darwin import sqflite_darwin
import wakelock_plus
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AgoraRtcNgPlugin.register(with: registry.registrar(forPlugin: "AgoraRtcNgPlugin")) AgoraRtcNgPlugin.register(with: registry.registrar(forPlugin: "AgoraRtcNgPlugin"))
@ -31,4 +32,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
} }

File diff suppressed because it is too large Load Diff

View File

@ -101,6 +101,9 @@ dependencies:
# 后台下载 # 后台下载
al_downloader: ^1.8.2 al_downloader: ^1.8.2
# 屏幕常亮
wakelock_plus: ^1.2.10
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter