215 lines
6.6 KiB
Dart
215 lines
6.6 KiB
Dart
import 'dart:async';
|
||
|
||
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
|
||
import 'package:flutter/foundation.dart';
|
||
import 'package:get/get.dart';
|
||
import 'package:permission_handler/permission_handler.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 with RequestToolMixin{
|
||
final MeetingMainState state = MeetingMainState();
|
||
|
||
@override
|
||
void onInit() {
|
||
super.onInit();
|
||
|
||
// 接收参数
|
||
var data = Get.arguments;
|
||
state.roomNumber.value = data["roomNumber"];
|
||
|
||
doHttpGetMeetingToken();
|
||
}
|
||
|
||
@override
|
||
void onClose() {
|
||
super.onClose();
|
||
state.memberNameSearchController.dispose();
|
||
stopTime();
|
||
leaveMeeting();
|
||
state.hubConnection.value?.stop();
|
||
}
|
||
|
||
/// 合并请求
|
||
/// 1.获取会议室信息
|
||
/// 2.获取会议室所有用户
|
||
Future<void> mergeFetch() async {
|
||
ToastUtils.showLoading();
|
||
|
||
var results = await Future.wait([
|
||
getClient().getMeetingRoomInfo(state.roomNumber.value),
|
||
getClient().getMeetingRoomAllUser(state.roomNumber.value)]);
|
||
|
||
getMeetingRoomInfo(results[0].data as MeetingRoomInfo);
|
||
getMeetingRoomAllUser(results[1].data as List<MeetingRoomUser>);
|
||
|
||
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) => debugPrint("SignalR Socket:$message"),
|
||
)).build();
|
||
|
||
await state.hubConnection.value?.start();
|
||
|
||
joinChannelToSocket();
|
||
}
|
||
|
||
/// 加入会议室
|
||
Future<void> joinChannelToSocket() async {
|
||
await state.hubConnection.value?.invoke("joinChannel", args: [state.roomNumber.value, false, false, false]);
|
||
mergeFetch();
|
||
}
|
||
|
||
/// 改变会议信息浮层显示状态
|
||
void changeMeetingInfoState(bool isShow){
|
||
state.isShowMeetingInfoFloatingLayer.value = isShow;
|
||
}
|
||
|
||
/// 改变音频选择浮层显示状态
|
||
void changeMeetingAudioState(bool isShow){
|
||
state.isShowMeetingAudioFloatingLayer.value = isShow;
|
||
}
|
||
|
||
/// 改变当前页面状态
|
||
void changePageState(int pageState){
|
||
state.pageState.value = pageState;
|
||
}
|
||
|
||
/// 获取会议室信息
|
||
void getMeetingRoomInfo(MeetingRoomInfo meetingRoomInfo) async {
|
||
state.meetingRoomInfo.value = meetingRoomInfo;
|
||
startTime();
|
||
}
|
||
|
||
/// 获取会议室所有用户
|
||
void getMeetingRoomAllUser(List<MeetingRoomUser> meetingRoomUsers) async {
|
||
state.users.value = meetingRoomUsers;
|
||
state.cacheUsers.value = meetingRoomUsers;
|
||
}
|
||
|
||
/// 获取会议室Token
|
||
Future<void> doHttpGetMeetingToken() async {
|
||
BaseStructureResult<String> res = await getClient().getMeetingToken(state.roomNumber.value);
|
||
state.meetingToken.value = res.data!;
|
||
|
||
initRtc();
|
||
signalRSocket();
|
||
}
|
||
|
||
/// 启动计时
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// 初始化声网SDK
|
||
Future<void> initRtc() async {
|
||
// 请求麦克风权限
|
||
if (defaultTargetPlatform == TargetPlatform.android) {
|
||
await [Permission.microphone].request();
|
||
}
|
||
|
||
// 创建 RtcEngine 对象
|
||
state.rctEngine.value = createAgoraRtcEngine();
|
||
|
||
// 初始化 RtcEngine,设置频道场景为 channelProfileLiveBroadcasting(直播场景)
|
||
await state.rctEngine.value?.initialize(RtcEngineContext(
|
||
appId: state.appId,
|
||
channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
|
||
));
|
||
|
||
joinChannelToRtc();
|
||
|
||
// 回调
|
||
state.rctEngine.value?.registerEventHandler(
|
||
RtcEngineEventHandler(
|
||
// 成功加入频道回调
|
||
onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
|
||
debugPrint("自己加入会议室,ID:${connection.localUid}");
|
||
},
|
||
// 远端用户或主播加入当前频道回调
|
||
onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
|
||
debugPrint("远端用户或主播加入会议室,用户或主机的ID:$remoteUid");
|
||
},
|
||
// 远端用户或主播离开当前频道回调
|
||
onUserOffline: (RtcConnection connection, int remoteUid, UserOfflineReasonType reason) {
|
||
debugPrint("远端用户或主播离开会议室,用户或主机的ID:$remoteUid");
|
||
},
|
||
),
|
||
);
|
||
}
|
||
|
||
/// 加入会议室
|
||
Future<void> joinChannelToRtc() async {
|
||
await state.rctEngine.value?.joinChannel(
|
||
token: state.meetingToken.value,
|
||
channelId: state.roomNumber.value,
|
||
uid: 0,
|
||
options: const ChannelMediaOptions(
|
||
// 自动订阅所有视频流
|
||
autoSubscribeVideo: false,
|
||
// 自动订阅所有音频流
|
||
autoSubscribeAudio: true,
|
||
// 发布摄像头采集的视频
|
||
publishCameraTrack: false,
|
||
// 发布麦克风采集的音频
|
||
publishMicrophoneTrack: false,
|
||
// 设置用户角色为clientRoleAudience(观众)
|
||
clientRoleType: ClientRoleType.clientRoleAudience),
|
||
);
|
||
}
|
||
|
||
/// 离开会议室
|
||
Future<void> leaveMeeting() async {
|
||
// 离开
|
||
await state.rctEngine.value?.leaveChannel();
|
||
// 释放资源
|
||
await state.rctEngine.value?.release();
|
||
}
|
||
}
|