1.获取会议室信息接口调用
2.获取会议室token接口调用 3.获取会议室所有成员接口调用 4.成员列表渲染和逻辑处理 5.SignalR Socket长连接 5.1加入会议室接口调用
|
After Width: | Height: | Size: 766 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 861 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 410 B |
|
Before Width: | Height: | Size: 619 B After Width: | Height: | Size: 446 B |
|
After Width: | Height: | Size: 619 B |
|
|
@ -2,7 +2,9 @@ import 'package:dio/dio.dart' hide Headers;
|
|||
|
||||
import 'package:retrofit/retrofit.dart';
|
||||
import '../models/common/base_structure_result.dart';
|
||||
import '../models/meeting_room_info.dart';
|
||||
import '../models/meeting_room_item.dart';
|
||||
import '../models/meeting_room_user.dart';
|
||||
import '../models/user_info_entity.dart';
|
||||
|
||||
part 'retrofit_client.g.dart';
|
||||
|
|
@ -33,4 +35,22 @@ abstract class RetrofitClient {
|
|||
@Query("PageIndex") int PageIndex,
|
||||
@Query("PageSize") int PageSize,
|
||||
);
|
||||
|
||||
/// 获取会议室信息
|
||||
@GET("/room/{roomNum}")
|
||||
Future<BaseStructureResult<MeetingRoomInfo>> getMeetingRoomInfo(
|
||||
@Path("roomNum") String roomNum,
|
||||
);
|
||||
|
||||
/// 获取会议室所有用户
|
||||
@GET("/room/user")
|
||||
Future<BaseStructureResult<List<MeetingRoomUser>>> getMeetingRoomAllUser(
|
||||
@Query("roomNum") String roomNum,
|
||||
);
|
||||
|
||||
/// 获取会议室Token
|
||||
@GET("/room/tk/rtc")
|
||||
Future<BaseStructureResult<String>> getMeetingToken(
|
||||
@Query("roomNum") String roomNum,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'meeting_room_info.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class MeetingRoomInfo extends Object{
|
||||
|
||||
@JsonKey(name: 'id')
|
||||
String id;
|
||||
|
||||
@JsonKey(name: 'roomName')
|
||||
String roomName;
|
||||
|
||||
@JsonKey(name: 'roomNum')
|
||||
String roomNum;
|
||||
|
||||
@JsonKey(name: 'onlineUserCount')
|
||||
int onlineUserCount;
|
||||
|
||||
@JsonKey(name: 'year')
|
||||
int year;
|
||||
|
||||
@JsonKey(name: 'subject')
|
||||
int subject;
|
||||
|
||||
MeetingRoomInfo(this.id,this.roomName,this.roomNum,this.onlineUserCount,this.year,this.subject,);
|
||||
|
||||
factory MeetingRoomInfo.fromJson(Map<String, dynamic> srcJson) => _$MeetingRoomInfoFromJson(srcJson);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'meeting_room_user.g.dart';
|
||||
|
||||
|
||||
@JsonSerializable()
|
||||
class MeetingRoomUser extends Object{
|
||||
|
||||
@JsonKey(name: 'uid')
|
||||
String uid;
|
||||
|
||||
@JsonKey(name: 'connectId')
|
||||
String connectId;
|
||||
|
||||
@JsonKey(name: 'account')
|
||||
String account;
|
||||
|
||||
@JsonKey(name: 'enableMicr')
|
||||
bool enableMicr;
|
||||
|
||||
@JsonKey(name: 'enableCamera')
|
||||
bool enableCamera;
|
||||
|
||||
@JsonKey(name: 'screenShareId')
|
||||
String screenShareId;
|
||||
|
||||
@JsonKey(name: 'userName')
|
||||
String userName;
|
||||
|
||||
@JsonKey(name: 'roleId')
|
||||
String roleId;
|
||||
|
||||
@JsonKey(name: 'roleName')
|
||||
String roleName;
|
||||
|
||||
@JsonKey(name: 'isRoomManager')
|
||||
bool isRoomManager;
|
||||
|
||||
MeetingRoomUser(this.uid,this.connectId,this.account,this.enableMicr,this.enableCamera,this.screenShareId,this.userName,this.roleId,this.roleName,this.isRoomManager,);
|
||||
|
||||
factory MeetingRoomUser.fromJson(Map<String, dynamic> srcJson) => _$MeetingRoomUserFromJson(srcJson);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ class HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
|
|||
),
|
||||
),
|
||||
onTap: (){
|
||||
Get.toNamed(Routes.meetingMainPage);
|
||||
Get.toNamed(Routes.meetingMainPage, arguments: {"roomNumber": state.meetingRooms[index].roomNum});
|
||||
},
|
||||
)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class LoginLogic extends GetxController with RequestToolMixin {
|
|||
if (null != res.data) {
|
||||
UserStore.to.setToken(res.data!.token);
|
||||
UserStore.to.setUserDetailInfo(res.data!);
|
||||
Get.toNamed(Routes.meetingMainPage);
|
||||
Get.toNamed(Routes.meetingMainPage, arguments: {"roomNumber": state.meetingCodeController.text});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,78 @@
|
|||
import 'package:get/get.dart';
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
import 'package:signalr_core/signalr_core.dart';
|
||||
import 'package:wgshare/common/store/user_store.dart';
|
||||
|
||||
import '../../common/config/request_config.dart';
|
||||
import '../../common/mixins/request_tool_mixin.dart';
|
||||
import '../../common/models/common/base_structure_result.dart';
|
||||
import '../../common/models/meeting_room_info.dart';
|
||||
import '../../common/models/meeting_room_user.dart';
|
||||
import '../../utils/toast_utils.dart';
|
||||
import 'meeting_main_state.dart';
|
||||
|
||||
class MeetingMainLogic extends GetxController {
|
||||
class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||
final MeetingMainState state = MeetingMainState();
|
||||
|
||||
@override
|
||||
void onInit() async {
|
||||
super.onInit();
|
||||
|
||||
// 接收参数
|
||||
var data = Get.arguments;
|
||||
state.roomNumber.value = data["roomNumber"];
|
||||
|
||||
signalRSocket();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
super.onClose();
|
||||
state.memberNameSearchController.dispose();
|
||||
stopTime();
|
||||
state.hubConnection.value?.stop();
|
||||
}
|
||||
|
||||
/// 合并请求
|
||||
/// 1.获取会议室信息
|
||||
/// 2.获取会议室所有用户
|
||||
/// 3.获取会议室Token
|
||||
void mergeFetch() async {
|
||||
ToastUtils.showLoading();
|
||||
|
||||
var results = await Future.wait([
|
||||
getClient().getMeetingRoomInfo(state.roomNumber.value),
|
||||
getClient().getMeetingRoomAllUser(state.roomNumber.value),
|
||||
getClient().getMeetingToken(state.roomNumber.value)]);
|
||||
|
||||
doHttpGetMeetingRoomInfo(results[0].data as MeetingRoomInfo);
|
||||
doHttpGetMeetingRoomAllUser(results[1].data as List<MeetingRoomUser>);
|
||||
doHttpGetMeetingToken(results[2].data as String);
|
||||
|
||||
ToastUtils.dismiss();
|
||||
}
|
||||
|
||||
/// Socket长连接
|
||||
Future<void> signalRSocket() async {
|
||||
state.hubConnection.value = HubConnectionBuilder().withUrl('${RequestConfig().baseUrl}/session-manage',
|
||||
HttpConnectionOptions(
|
||||
transport: HttpTransportType.longPolling,
|
||||
accessTokenFactory: () async => await Future.value(UserStore.to.token),
|
||||
logging: (level, message) => print("SignalR Socket:$message"),
|
||||
)).build();
|
||||
|
||||
await state.hubConnection.value?.start();
|
||||
|
||||
joinChannel();
|
||||
}
|
||||
|
||||
/// 加入会议室
|
||||
void joinChannel() async {
|
||||
await state.hubConnection.value?.invoke("joinChannel", args: [state.roomNumber.value, false, false, false]);
|
||||
mergeFetch();
|
||||
}
|
||||
|
||||
/// 改变会议信息浮层显示状态
|
||||
void changeMeetingInfoState(bool isShow){
|
||||
state.isShowMeetingInfoFloatingLayer.value = isShow;
|
||||
|
|
@ -19,4 +87,58 @@ class MeetingMainLogic extends GetxController {
|
|||
void changePageState(int pageState){
|
||||
state.pageState.value = pageState;
|
||||
}
|
||||
|
||||
/// 获取会议室信息
|
||||
void doHttpGetMeetingRoomInfo(MeetingRoomInfo meetingRoomInfo) async {
|
||||
state.meetingRoomInfo.value = meetingRoomInfo;
|
||||
startTime();
|
||||
}
|
||||
|
||||
/// 获取会议室所有用户
|
||||
void doHttpGetMeetingRoomAllUser(List<MeetingRoomUser> meetingRoomUsers) async {
|
||||
state.users.value = meetingRoomUsers;
|
||||
state.cacheUsers.value = meetingRoomUsers;
|
||||
}
|
||||
|
||||
/// 获取会议室Token
|
||||
void doHttpGetMeetingToken(String meetingToken) async {
|
||||
state.meetingToken.value = meetingToken;
|
||||
}
|
||||
|
||||
/// 启动计时
|
||||
void startTime(){
|
||||
state.stopwatch.value.start();
|
||||
state.timer.value = Timer.periodic(const Duration(milliseconds: 100), upTime);
|
||||
}
|
||||
|
||||
/// 更新计时
|
||||
void upTime(Timer t) {
|
||||
if(state.stopwatch.value.isRunning){
|
||||
state.duration.value =
|
||||
"${state.stopwatch.value.elapsed.inHours.toString().padLeft(2, "0")}"
|
||||
":${(state.stopwatch.value.elapsed.inMinutes % 60).toString().padLeft(2, "0")}"
|
||||
":${(state.stopwatch.value.elapsed.inSeconds % 60).toString().padLeft(2, "0")}";
|
||||
}
|
||||
}
|
||||
|
||||
/// 停止计时
|
||||
void stopTime() {
|
||||
state.timer.value?.cancel();
|
||||
state.stopwatch.value.stop();
|
||||
}
|
||||
|
||||
/// 搜索成员
|
||||
void searchMember(String value){
|
||||
if(value.isNotEmpty){
|
||||
List<MeetingRoomUser> memberSearchList = [];
|
||||
for(var i = 0; i < state.cacheUsers.length; i++){
|
||||
if(state.cacheUsers[i].userName.contains(value)){
|
||||
memberSearchList.add(state.cacheUsers.value[i]);
|
||||
}
|
||||
}
|
||||
state.users.value = memberSearchList;
|
||||
}else{
|
||||
state.users.value = state.cacheUsers.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,21 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_rx/src/rx_types/rx_types.dart';
|
||||
import 'package:signalr_core/signalr_core.dart';
|
||||
|
||||
import '../../common/models/meeting_room_info.dart';
|
||||
import '../../common/models/meeting_room_user.dart';
|
||||
|
||||
class MeetingMainState {
|
||||
|
||||
MeetingMainState() {
|
||||
///Initialize variables
|
||||
}
|
||||
|
||||
late TextEditingController memberNameSearchController = TextEditingController();
|
||||
|
||||
/// 是否显示会议信息浮层
|
||||
late RxBool isShowMeetingInfoFloatingLayer = false.obs;
|
||||
|
||||
|
|
@ -18,4 +27,28 @@ class MeetingMainState {
|
|||
|
||||
/// 当前页面状态,0:语音,1:视频,2,共享
|
||||
late RxInt pageState = 0.obs;
|
||||
|
||||
/// 会议室编号
|
||||
late RxString roomNumber = "".obs;
|
||||
|
||||
/// 会议室信息
|
||||
late Rx<MeetingRoomInfo?> meetingRoomInfo = Rx(null);
|
||||
|
||||
/// 会议室计时相关
|
||||
late RxString duration = "".obs;
|
||||
late Rx<Stopwatch> stopwatch = Rx(Stopwatch());
|
||||
late Rx<Timer?> timer = Rx(null);
|
||||
|
||||
/// Http接口获取的会议室所有用户
|
||||
late RxList<MeetingRoomUser> users = RxList([]);
|
||||
|
||||
/// 搜索用户时,缓存会议室所有用户原始数据
|
||||
late RxList<MeetingRoomUser> cacheUsers = RxList([]);
|
||||
|
||||
/// 会议室Token
|
||||
late RxString meetingToken = "".obs;
|
||||
|
||||
/// signalR 长连接相关
|
||||
late RxString serviceUrl = "http://192.168.2.9:5192/session-manage".obs;
|
||||
late Rx<HubConnection?> hubConnection = Rx(null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:wgshare/common/store/user_store.dart';
|
||||
import 'package:wgshare/pages/metting/share/meeting_main_share_view.dart';
|
||||
import 'package:wgshare/pages/metting/video/meeting_main_video_view.dart';
|
||||
import 'package:wgshare/utils/toast_utils.dart';
|
||||
|
|
@ -33,7 +34,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
),
|
||||
backgroundColor: ColorUtil.Color_41_41_41,
|
||||
),
|
||||
body: Stack(
|
||||
body: Obx(() => Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
|
|
@ -87,7 +88,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'高三教研数学组',
|
||||
state.meetingRoomInfo.value?.roomName ?? '',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14.sp,
|
||||
|
|
@ -103,7 +104,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
),
|
||||
SizedBox(height: 4.h),
|
||||
Text(
|
||||
'08:50',
|
||||
state.duration.value,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12.sp,
|
||||
|
|
@ -127,7 +128,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
),
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
isScrollControlled: true,
|
||||
isScrollControlled: true,
|
||||
leaveBottomSheet(context)
|
||||
);
|
||||
},
|
||||
|
|
@ -145,7 +146,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
// 语音
|
||||
Visibility(
|
||||
visible: true,
|
||||
child: MeetingMainVoiceComponent()
|
||||
child: MeetingMainVoiceComponent(users: state.cacheUsers.value)
|
||||
),
|
||||
|
||||
// 视频
|
||||
|
|
@ -198,7 +199,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
),
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
isScrollControlled: true,
|
||||
isScrollControlled: true,
|
||||
chatBottomSheet(context)
|
||||
);
|
||||
Future.delayed(const Duration(milliseconds: 100), () {
|
||||
|
|
@ -240,7 +241,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
),
|
||||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
isScrollControlled: true,
|
||||
isScrollControlled: true,
|
||||
applySpeakPermissionBottomSheet(
|
||||
context)
|
||||
);
|
||||
|
|
@ -317,7 +318,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
onTap: () {
|
||||
Get.bottomSheet(
|
||||
isScrollControlled: true,
|
||||
queryMemberFloatingLayer(context)
|
||||
Obx(() => queryMemberFloatingLayer(context)),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
@ -351,7 +352,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
meetingInfoFloatingLayer(),
|
||||
meetingAudioFloatingLayer(),
|
||||
],
|
||||
));
|
||||
)));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -416,7 +417,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
|
||||
/// 会议信息浮层
|
||||
Widget meetingInfoFloatingLayer() {
|
||||
return Obx(() => Visibility(
|
||||
return Visibility(
|
||||
visible: state.isShowMeetingInfoFloatingLayer.value,
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
@ -436,7 +437,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'高三教研数学组',
|
||||
state.meetingRoomInfo.value?.roomName ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
|
|
@ -476,7 +477,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'561564899156',
|
||||
state.roomNumber.value,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: ColorUtil.Color_202_202_202,
|
||||
|
|
@ -499,62 +500,6 @@ class MeetingMainPage extends StatelessWidget {
|
|||
color: ColorUtil.Color_49_47_47,
|
||||
margin: const EdgeInsets.only(top: 14, bottom: 14),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'密码',
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: ColorUtil.Color_134_134_134),
|
||||
),
|
||||
Text(
|
||||
'5615648',
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: ColorUtil.Color_202_202_202,
|
||||
fontWeight: FontWeight.w500),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 1.h,
|
||||
color: ColorUtil.Color_49_47_47,
|
||||
margin: const EdgeInsets.only(top: 14, bottom: 14),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'发起人',
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: ColorUtil.Color_134_134_134),
|
||||
),
|
||||
Text(
|
||||
'晓晓',
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: ColorUtil.Color_202_202_202,
|
||||
fontWeight: FontWeight.w500),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 1.h,
|
||||
color: ColorUtil.Color_49_47_47,
|
||||
margin: const EdgeInsets.only(top: 14, bottom: 14),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16),
|
||||
child: Row(
|
||||
|
|
@ -568,7 +513,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
color: ColorUtil.Color_134_134_134),
|
||||
),
|
||||
Text(
|
||||
'晓晓',
|
||||
UserStore.to.userInfoEntity.value!.userName,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: ColorUtil.Color_202_202_202,
|
||||
|
|
@ -596,7 +541,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
color: ColorUtil.Color_134_134_134),
|
||||
),
|
||||
Text(
|
||||
'08:50',
|
||||
state.duration.value,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: ColorUtil.Color_202_202_202,
|
||||
|
|
@ -641,12 +586,12 @@ class MeetingMainPage extends StatelessWidget {
|
|||
))
|
||||
],
|
||||
),
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
/// 选择音频输出浮层
|
||||
Widget meetingAudioFloatingLayer() {
|
||||
return Obx(() => Visibility(
|
||||
return Visibility(
|
||||
visible: state.isShowMeetingAudioFloatingLayer.value,
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
@ -676,7 +621,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
))
|
||||
],
|
||||
),
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
/// 音频列表
|
||||
|
|
@ -897,17 +842,22 @@ class MeetingMainPage extends StatelessWidget {
|
|||
SizedBox(width: 8.w),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: state.memberNameSearchController,
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
color: ColorUtil.Color_235_235_235
|
||||
),
|
||||
textInputAction: TextInputAction.search,
|
||||
decoration: InputDecoration(
|
||||
contentPadding: EdgeInsets.all(0),
|
||||
border: OutlineInputBorder(borderSide: BorderSide.none),
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
border: const OutlineInputBorder(borderSide: BorderSide.none),
|
||||
hintText: '输入用户名',
|
||||
hintStyle: TextStyle(
|
||||
color: ColorUtil.Color_70_71_73,
|
||||
fontSize: 14.sp)),
|
||||
onSubmitted: (value){
|
||||
logic.searchMember(value);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
|
|
@ -917,7 +867,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
margin:
|
||||
const EdgeInsets.only(top: 18, left: 16, right: 16, bottom: 16),
|
||||
child: Text(
|
||||
'会议中(2)',
|
||||
'会议中(${state.users.length})',
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
|
|
@ -944,31 +894,39 @@ class MeetingMainPage extends StatelessWidget {
|
|||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: NetworkImage(
|
||||
"https://ts4.cn.mm.bing.net/th?id=OIP-C.QDl_Z7HdQWX_XbVYgBLJLQAAAA&w=250&h=250&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2",
|
||||
),
|
||||
),
|
||||
color: ColorUtil.Color_85_117_242
|
||||
),
|
||||
margin: const EdgeInsets.only(right: 8),
|
||||
width: 36.w,
|
||||
height: 36.h,
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
state.users[index].userName.length >= 3
|
||||
? state.users[index].userName.substring(1,state.users[index].userName.length)
|
||||
: state.users[index].userName,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: ColorUtil.Color_244_244_244
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'晓晓',
|
||||
state.users[index].userName,
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: ColorUtil.Color_243_243_243),
|
||||
),
|
||||
SizedBox(width: 8.w),
|
||||
Text(
|
||||
'主持人',
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: ColorUtil.Color_2_177_136),
|
||||
Visibility(
|
||||
child: Text(
|
||||
'主持人',
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: ColorUtil.Color_2_177_136),
|
||||
),
|
||||
visible: state.users[index].isRoomManager,
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
@ -984,7 +942,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
Container(
|
||||
margin: const EdgeInsets.only(left: 12),
|
||||
child: Image.asset(
|
||||
'assets/images/meeting_main_microphone_default.png',
|
||||
state.users[index].enableMicr == true ? 'assets/images/meeting_main_microphone_default.png' : 'assets/images/meeting_main_microphone_close.png',
|
||||
width: 17.w,
|
||||
height: 17.h,
|
||||
),
|
||||
|
|
@ -992,7 +950,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
Container(
|
||||
margin: const EdgeInsets.only(left: 12),
|
||||
child: Image.asset(
|
||||
'assets/images/meeting_main_camera_default.png',
|
||||
state.users[index].enableCamera == true ? 'assets/images/meeting_main_camera_default.png' : 'assets/images/meeting_main_camera_close.png',
|
||||
width: 17.w,
|
||||
height: 17.h,
|
||||
),
|
||||
|
|
@ -1012,7 +970,7 @@ class MeetingMainPage extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
},
|
||||
itemCount: 10,
|
||||
itemCount: state.users.length,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ class MeetingMainShareComponent extends StatelessWidget {
|
|||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/meeting_main_microphone_close.png',
|
||||
'assets/images/meeting_main_microphone_open.png',
|
||||
width: 13.w,
|
||||
height: 14.h,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class MeetingMainVideoComponent extends StatelessWidget {
|
|||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/meeting_main_microphone_close.png',
|
||||
'assets/images/meeting_main_microphone_open.png',
|
||||
width: 13.w,
|
||||
height: 14.h,
|
||||
),
|
||||
|
|
@ -189,7 +189,7 @@ class MeetingMainVideoComponent extends StatelessWidget {
|
|||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/meeting_main_microphone_close.png',
|
||||
'assets/images/meeting_main_microphone_open.png',
|
||||
width: 13.w,
|
||||
height: 14.h,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -2,13 +2,16 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../common/models/meeting_room_user.dart';
|
||||
import '../../../utils/color_util.dart';
|
||||
import '../../../utils/cus_behavior.dart';
|
||||
import 'meeting_main_voice_logic.dart';
|
||||
import 'meeting_main_voice_state.dart';
|
||||
|
||||
class MeetingMainVoiceComponent extends StatelessWidget {
|
||||
MeetingMainVoiceComponent({Key? key}) : super(key: key);
|
||||
MeetingMainVoiceComponent({Key? key, required this.users}) : super(key: key);
|
||||
|
||||
final List<MeetingRoomUser> users;
|
||||
|
||||
final MeetingMainVoiceLogic logic = Get.put(MeetingMainVoiceLogic());
|
||||
final MeetingMainVoiceState state = Get.find<MeetingMainVoiceLogic>().state;
|
||||
|
|
@ -27,7 +30,7 @@ class MeetingMainVoiceComponent extends StatelessWidget {
|
|||
crossAxisCount: 3,
|
||||
childAspectRatio: 0.7,
|
||||
crossAxisSpacing: 20),
|
||||
itemCount: 15,
|
||||
itemCount: users.length,
|
||||
itemBuilder: (BuildContext ctx, index) {
|
||||
return Column(
|
||||
children: [
|
||||
|
|
@ -35,27 +38,32 @@ class MeetingMainVoiceComponent extends StatelessWidget {
|
|||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(99),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: NetworkImage(
|
||||
"https://ts4.cn.mm.bing.net/th?id=OIP-C.QDl_Z7HdQWX_XbVYgBLJLQAAAA&w=250&h=250&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2",
|
||||
),
|
||||
),
|
||||
color: ColorUtil.Color_85_117_242
|
||||
),
|
||||
width: 76.w,
|
||||
height: 76.h,
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
users[index].userName.length >= 3
|
||||
? users[index].userName.substring(1,users[index].userName.length)
|
||||
: users[index].userName,
|
||||
style: TextStyle(
|
||||
fontSize: 22.sp,
|
||||
color: ColorUtil.Color_244_244_244
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 6.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/meeting_main_speak1.png',
|
||||
users[index].enableMicr == true ? 'assets/images/meeting_main_speak1.png' : 'assets/images/meeting_main_microphone_open.png',
|
||||
width: 22.w,
|
||||
height: 22.h,
|
||||
),
|
||||
Text(
|
||||
'张三啊',
|
||||
users[index].userName,
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: ColorUtil.Color_255_255_255),
|
||||
|
|
|
|||
|
|
@ -70,12 +70,6 @@ class UserPageState extends State<UserPage> {
|
|||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
color: ColorUtil.Color_85_117_242
|
||||
/*image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image: NetworkImage(
|
||||
"https://ts4.cn.mm.bing.net/th?id=OIP-C.QDl_Z7HdQWX_XbVYgBLJLQAAAA&w=250&h=250&c=8&rs=1&qlt=90&o=6&pid=3.1&rm=2",
|
||||
),
|
||||
),*/
|
||||
),
|
||||
width: 132.w,
|
||||
height: 132.h,
|
||||
|
|
@ -91,14 +85,12 @@ class UserPageState extends State<UserPage> {
|
|||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: Text(
|
||||
UserStore.to.userInfoEntity.value!.userName,
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: ColorUtil.Color_85_117_242
|
||||
),
|
||||
Text(
|
||||
UserStore.to.userInfoEntity.value!.userName,
|
||||
style: TextStyle(
|
||||
fontSize: 16.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: ColorUtil.Color_85_117_242
|
||||
),
|
||||
),
|
||||
Container(
|
||||
|
|
|
|||
|
|
@ -5,15 +5,19 @@
|
|||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import agora_rtc_engine
|
||||
import device_info_plus
|
||||
import geolocator_apple
|
||||
import iris_method_channel
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import sqflite_darwin
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
AgoraRtcNgPlugin.register(with: registry.registrar(forPlugin: "AgoraRtcNgPlugin"))
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
|
||||
IrisMethodChannelPlugin.register(with: registry.registrar(forPlugin: "IrisMethodChannelPlugin"))
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@ packages:
|
|||
description: dart
|
||||
source: sdk
|
||||
version: "0.3.2"
|
||||
agora_rtc_engine:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: agora_rtc_engine
|
||||
sha256: deefb5ea051c4d916552cbf76cfbdd652867aa9b554ff9afb3c732ec2e44652e
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.3.2"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -114,26 +122,26 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: cached_network_image
|
||||
sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916"
|
||||
sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
version: "3.3.1"
|
||||
cached_network_image_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_platform_interface
|
||||
sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
|
||||
sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.1.1"
|
||||
version: "4.0.0"
|
||||
cached_network_image_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_web
|
||||
sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062"
|
||||
sha256: "205d6a9f1862de34b93184f22b9d2d94586b2f05c581d546695e3d8f6a805cd7"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "1.2.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -210,10 +218,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: device_info_plus
|
||||
sha256: f545ffbadee826f26f2e1a0f0cbd667ae9a6011cc0f77c0f8f00a969655e6e95
|
||||
sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "11.1.1"
|
||||
version: "10.1.2"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -246,6 +254,14 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
equatable:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: equatable
|
||||
sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.7"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -287,10 +303,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: flutter_cache_manager
|
||||
sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
|
||||
sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
version: "3.3.1"
|
||||
flutter_easyloading:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -478,10 +494,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
|
||||
sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
version: "0.13.6"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -514,6 +530,14 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
iris_method_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: iris_method_channel
|
||||
sha256: "131d0a40ba646ba8fd4bf76e24d4ebd4aa3174ee39aa5fe8240c3b827979052c"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -854,10 +878,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: rxdart
|
||||
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
|
||||
sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.28.0"
|
||||
version: "0.27.7"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -874,6 +898,14 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
signalr_core:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: signalr_core
|
||||
sha256: dca676372a00c051511591ed0e24521ff7aa4e9320a7fa778a1007f7f522c8c0
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
|
@ -951,6 +983,14 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
sse_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sse_client
|
||||
sha256: "71bd826430b41ab20a69d85bf2dfe9f11cfe222938e681ada1aea71fc8adf348"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.1.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1023,6 +1063,14 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
tuple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: tuple
|
||||
sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1071,22 +1119,14 @@ packages:
|
|||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket
|
||||
sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.1.6"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f"
|
||||
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
version: "2.4.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ dependencies:
|
|||
easy_debounce: ^2.0.3 # 防抖节流
|
||||
# loading插件
|
||||
flutter_easyloading: ^3.0.5
|
||||
cached_network_image: ^3.4.1
|
||||
cached_network_image: ^3.3.1
|
||||
package_info_plus: ^8.1.1
|
||||
fluttertoast: ^8.2.8
|
||||
functional_widget_annotation: ^0.10.0
|
||||
|
|
@ -67,7 +67,14 @@ dependencies:
|
|||
# MD5加密
|
||||
crypto: ^3.0.2
|
||||
|
||||
device_info_plus: ^11.1.1
|
||||
# 获取设备信息
|
||||
device_info_plus: ^10.0.0
|
||||
|
||||
# 声网 Flutter SDK 依赖项,请使用最新版本的 agora_rtc_engine
|
||||
agora_rtc_engine: ^6.3.2
|
||||
|
||||
# .net socket通信插件
|
||||
signalr_core: ^1.1.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
|
|
@ -6,12 +6,18 @@
|
|||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <agora_rtc_engine/agora_rtc_engine_plugin.h>
|
||||
#include <geolocator_windows/geolocator_windows.h>
|
||||
#include <iris_method_channel/iris_method_channel_plugin_c_api.h>
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
AgoraRtcEnginePluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("AgoraRtcEnginePlugin"));
|
||||
GeolocatorWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("GeolocatorWindows"));
|
||||
IrisMethodChannelPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("IrisMethodChannelPluginCApi"));
|
||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
agora_rtc_engine
|
||||
geolocator_windows
|
||||
iris_method_channel
|
||||
permission_handler_windows
|
||||
)
|
||||
|
||||
|
|
|
|||