parent
4d750d6316
commit
175ffa873c
|
|
@ -36,7 +36,10 @@ class MeetingRoomUser extends Object{
|
||||||
@JsonKey(name: 'isRoomManager')
|
@JsonKey(name: 'isRoomManager')
|
||||||
bool isRoomManager;
|
bool isRoomManager;
|
||||||
|
|
||||||
MeetingRoomUser(this.uid,this.connectId,this.account,this.enableMicr,this.enableCamera,this.screenShareId,this.userName,this.roleId,this.roleName,this.isRoomManager,);
|
@JsonKey(name: 'volume')
|
||||||
|
double? volume = 0.0;
|
||||||
|
|
||||||
|
MeetingRoomUser(this.uid,this.connectId,this.account,this.enableMicr,this.enableCamera,this.screenShareId,this.userName,this.roleId,this.roleName,this.isRoomManager,this.volume);
|
||||||
|
|
||||||
factory MeetingRoomUser.fromJson(Map<String, dynamic> srcJson) => _$MeetingRoomUserFromJson(srcJson);
|
factory MeetingRoomUser.fromJson(Map<String, dynamic> srcJson) => _$MeetingRoomUserFromJson(srcJson);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:signalr_core/signalr_core.dart';
|
import 'package:signalr_core/signalr_core.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 '../../common/config/request_config.dart';
|
import '../../common/config/request_config.dart';
|
||||||
import '../../common/mixins/request_tool_mixin.dart';
|
import '../../common/mixins/request_tool_mixin.dart';
|
||||||
import '../../common/models/common/base_structure_result.dart';
|
import '../../common/models/common/base_structure_result.dart';
|
||||||
|
|
@ -137,9 +138,10 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
/// 结束发言
|
/// 结束发言
|
||||||
Future<void> doHttpCancelSpeak() async {
|
Future<void> doHttpCancelSpeak() async {
|
||||||
BaseStructureResult res = await getClient().cancelSpeak(state.meetingRoomInfo.value!.id, state.meetingRoomInfo.value!.roomNum, UserStore.to.userInfoEntity.value!.uid);
|
BaseStructureResult res = await getClient().cancelSpeak(state.meetingRoomInfo.value!.id, state.meetingRoomInfo.value!.roomNum, UserStore.to.userInfoEntity.value!.uid);
|
||||||
|
setClientRole("观众");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 设置麦克风是否静音
|
/// 设置麦克风是否开启
|
||||||
void setMicrophoneOpen(bool isOpen){
|
void setMicrophoneOpen(bool isOpen){
|
||||||
state.isOpenMicrophone.value = isOpen;
|
state.isOpenMicrophone.value = isOpen;
|
||||||
for(var i = 0; i < state.cacheUsers.value.length; i++){
|
for(var i = 0; i < state.cacheUsers.value.length; i++){
|
||||||
|
|
@ -148,7 +150,22 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.users.value = state.cacheUsers.value;
|
state.users.value = state.cacheUsers.value;
|
||||||
setEnableLocalAudio(isOpen);
|
if(isOpen == true){
|
||||||
|
setClientRole("主播");
|
||||||
|
}else{
|
||||||
|
setClientRole("观众");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 设置视频是否打开
|
||||||
|
void setCameraOpen(bool isOpen){
|
||||||
|
state.isOpenCamera.value = isOpen;
|
||||||
|
if(isOpen == true){
|
||||||
|
setEnableLocalVideo(isOpen);
|
||||||
|
setClientRole("主播");
|
||||||
|
}else{
|
||||||
|
setClientRole("观众");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// --------------------------signalR Socket相关
|
/// --------------------------signalR Socket相关
|
||||||
|
|
@ -207,7 +224,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
if(UserStore.to.userInfoEntity.value!.uid == meetingRoomUser.uid){
|
if(UserStore.to.userInfoEntity.value!.uid == meetingRoomUser.uid){
|
||||||
state.isSpeak.value = true;
|
state.isSpeak.value = true;
|
||||||
state.isOpenMicrophone.value = true;
|
state.isOpenMicrophone.value = true;
|
||||||
setEnableLocalAudio(true);
|
setClientRole("主播");
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
debugPrint("wgs输出===:Socket-停止发言:${e?[0]}--${e?[1]}");
|
debugPrint("wgs输出===:Socket-停止发言:${e?[0]}--${e?[1]}");
|
||||||
|
|
@ -221,7 +238,7 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
if(UserStore.to.userInfoEntity.value!.uid == meetingRoomUser.uid){
|
if(UserStore.to.userInfoEntity.value!.uid == meetingRoomUser.uid){
|
||||||
state.isSpeak.value = false;
|
state.isSpeak.value = false;
|
||||||
state.isOpenMicrophone.value = false;
|
state.isOpenMicrophone.value = false;
|
||||||
setEnableLocalAudio(false);
|
setClientRole("观众");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
|
|
@ -268,7 +285,6 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
}
|
}
|
||||||
state.users.value = state.cacheUsers.value;
|
state.users.value = state.cacheUsers.value;
|
||||||
state.isOpenMicrophone.value = e?[0];
|
state.isOpenMicrophone.value = e?[0];
|
||||||
setEnableLocalAudio(e?[0]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/// 单独用户开闭麦回调
|
/// 单独用户开闭麦回调
|
||||||
|
|
@ -284,7 +300,6 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.isOpenMicrophone.value = true;
|
state.isOpenMicrophone.value = true;
|
||||||
setEnableLocalAudio(true);
|
|
||||||
}else{
|
}else{
|
||||||
debugPrint("wgs输出===:Socket-单独用户闭麦");
|
debugPrint("wgs输出===:Socket-单独用户闭麦");
|
||||||
for(MeetingRoomUser mru in state.cacheUsers.value){
|
for(MeetingRoomUser mru in state.cacheUsers.value){
|
||||||
|
|
@ -293,7 +308,6 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.isOpenMicrophone.value = false;
|
state.isOpenMicrophone.value = false;
|
||||||
setEnableLocalAudio(false);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -340,7 +354,11 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
));
|
));
|
||||||
|
|
||||||
// 设置默认音频路由为听筒
|
// 设置默认音频路由为听筒
|
||||||
state.rctEngine.value?.setDefaultAudioRouteToSpeakerphone(false);
|
await state.rctEngine.value?.setDefaultAudioRouteToSpeakerphone(false);
|
||||||
|
// 打开用户音量回调
|
||||||
|
await state.rctEngine.value?.enableAudioVolumeIndication(interval: 200, smooth: 3, reportVad: true);
|
||||||
|
// 启用音频模块
|
||||||
|
await state.rctEngine.value?.enableAudio();
|
||||||
|
|
||||||
joinMeetingToRtc();
|
joinMeetingToRtc();
|
||||||
|
|
||||||
|
|
@ -384,6 +402,49 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
// 音频采集开关回调
|
// 音频采集开关回调
|
||||||
onLocalAudioStateChanged: (RtcConnection connection, LocalAudioStreamState state, LocalAudioStreamReason reason){
|
onLocalAudioStateChanged: (RtcConnection connection, LocalAudioStreamState state, LocalAudioStreamReason reason){
|
||||||
debugPrint("wgs输出===:RTC-音频采集开关:$state");
|
debugPrint("wgs输出===:RTC-音频采集开关:$state");
|
||||||
|
},
|
||||||
|
|
||||||
|
// 视频采集开关回调
|
||||||
|
onRemoteVideoStateChanged: (RtcConnection connection,
|
||||||
|
int remoteUid,
|
||||||
|
RemoteVideoState state,
|
||||||
|
RemoteVideoStateReason reason,
|
||||||
|
int elapsed){
|
||||||
|
debugPrint("wgs输出===:RTC-视频采集开关:$state");
|
||||||
|
},
|
||||||
|
|
||||||
|
// 用户音量提示回调
|
||||||
|
onAudioVolumeIndication: (
|
||||||
|
RtcConnection connection,
|
||||||
|
List<AudioVolumeInfo> speakers,
|
||||||
|
int speakerNumber,
|
||||||
|
int totalVolume){
|
||||||
|
if(speakers.isNotEmpty){
|
||||||
|
for(AudioVolumeInfo avi in speakers){
|
||||||
|
for(MeetingRoomUser mru in state.cacheUsers.value){
|
||||||
|
if(avi.uid == 0){
|
||||||
|
debugPrint("wgs输出===:RTC-用户音量提示(自己):${CountMicrophoneVolume.getVolume(avi.volume!)}");
|
||||||
|
mru.volume = CountMicrophoneVolume.getVolume(avi.volume!);
|
||||||
|
state.microphoneVolume.value = CountMicrophoneVolume.getVolume(avi.volume!);
|
||||||
|
}else{
|
||||||
|
if(avi.uid.toString() == mru.uid){
|
||||||
|
debugPrint("wgs输出===:RTC-用户音量提示(远端用户):${speakers[0].uid}--${speakers[0].volume}");
|
||||||
|
mru.volume = CountMicrophoneVolume.getVolume(avi.volume!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 切换用户角色回调
|
||||||
|
onClientRoleChanged: (
|
||||||
|
RtcConnection connection,
|
||||||
|
ClientRoleType oldRole,
|
||||||
|
ClientRoleType newRole,
|
||||||
|
ClientRoleOptions newRoleOptions){
|
||||||
|
debugPrint("wgs输出===:RTC-切换用户角色");
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
@ -394,21 +455,21 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
await state.rctEngine.value?.joinChannel(
|
await state.rctEngine.value?.joinChannel(
|
||||||
token: state.meetingToken.value,
|
token: state.meetingToken.value,
|
||||||
channelId: state.roomNumber.value,
|
channelId: state.roomNumber.value,
|
||||||
uid: 0,
|
uid: int.parse(UserStore.to.userInfoEntity.value!.uid),
|
||||||
options: const ChannelMediaOptions(
|
options: const ChannelMediaOptions(
|
||||||
// 自动订阅所有视频流
|
// 自动订阅所有视频流
|
||||||
autoSubscribeVideo: true,
|
autoSubscribeVideo: true,
|
||||||
// 自动订阅所有音频流
|
// 自动订阅所有音频流
|
||||||
autoSubscribeAudio: true,
|
autoSubscribeAudio: true,
|
||||||
// 发布摄像头采集的视频
|
// 发布摄像头采集的视频
|
||||||
publishCameraTrack: false,
|
publishCameraTrack: true,
|
||||||
// 发布麦克风采集的音频
|
// 发布麦克风采集的音频
|
||||||
publishMicrophoneTrack: false,
|
publishMicrophoneTrack: true,
|
||||||
// 设置用户角色为 clientRoleBroadcaster(主播)或 clientRoleAudience(观众)
|
// 设置用户角色为 clientRoleBroadcaster(主播)或 clientRoleAudience(观众)
|
||||||
// 这里设置角色为clientRoleBroadcaster(主播)
|
// 这里设置角色为clientRoleBroadcaster(主播)
|
||||||
// 主播:可以在频道内发布音视频,同时也可以订阅其他主播发布的音视频
|
// 主播:可以在频道内发布音视频,同时也可以订阅其他主播发布的音视频
|
||||||
// 观众:可以在频道内订阅音视频,不具备发布音视频权限
|
// 观众:可以在频道内订阅音视频,不具备发布音视频权限
|
||||||
clientRoleType: ClientRoleType.clientRoleBroadcaster),
|
clientRoleType: ClientRoleType.clientRoleAudience),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -420,14 +481,34 @@ class MeetingMainLogic extends GetxController with RequestToolMixin{
|
||||||
await state.rctEngine.value?.release();
|
await state.rctEngine.value?.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 设置用户角色
|
||||||
|
Future<void> setClientRole(String roleStr) async {
|
||||||
|
if(roleStr == "主播"){
|
||||||
|
await state.rctEngine.value?.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
|
||||||
|
}else{
|
||||||
|
await state.rctEngine.value?.setClientRole(role: ClientRoleType.clientRoleAudience);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 设置音频输出路由(没有外接设备时生效)
|
/// 设置音频输出路由(没有外接设备时生效)
|
||||||
Future<void> setEnableSpeakerphone(int mode) async {
|
Future<void> setEnableSpeakerphone(int mode) async {
|
||||||
state.communicationMode.value = mode;
|
state.communicationMode.value = mode;
|
||||||
await state.rctEngine.value?.setEnableSpeakerphone(mode == 1 ? false : true);
|
await state.rctEngine.value?.setEnableSpeakerphone(mode == 1 ? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 设置是否打开本地音频采集
|
/// 设置是否打开本地视频采集
|
||||||
Future<void> setEnableLocalAudio(bool enabled) async {
|
Future<void> setEnableLocalVideo(bool enabled) async {
|
||||||
await state.rctEngine.value?.enableLocalAudio(enabled);
|
state.isOpenCamera.value = enabled;
|
||||||
|
if(enabled == true){
|
||||||
|
// 启用视频模块
|
||||||
|
await state.rctEngine.value?.enableVideo();
|
||||||
|
// 启用本地预览
|
||||||
|
await state.rctEngine.value?.startPreview();
|
||||||
|
}else{
|
||||||
|
// 关闭视频模块
|
||||||
|
await state.rctEngine.value?.disableVideo();
|
||||||
|
// 关闭本地预览
|
||||||
|
await state.rctEngine.value?.stopPreview();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,10 @@ class MeetingMainState {
|
||||||
late RxBool isSpeak = false.obs;
|
late RxBool isSpeak = false.obs;
|
||||||
/// 是否打开麦克风
|
/// 是否打开麦克风
|
||||||
late RxBool isOpenMicrophone = false.obs;
|
late RxBool isOpenMicrophone = false.obs;
|
||||||
|
/// 麦克风音量
|
||||||
|
late RxDouble microphoneVolume = 0.0.obs;
|
||||||
|
/// 是否打开摄像头
|
||||||
|
late RxBool isOpenCamera = false.obs;
|
||||||
|
|
||||||
/// 聊天数据
|
/// 聊天数据
|
||||||
late RxList<MeetingRoomMsg> meetingRoomMsgs = RxList([]);
|
late RxList<MeetingRoomMsg> meetingRoomMsgs = RxList([]);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:liquid_progress_indicator_v2/liquid_progress_indicator.dart';
|
||||||
import 'package:wgshare/common/store/user_store.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/share/meeting_main_share_view.dart';
|
||||||
import 'package:wgshare/pages/metting/video/meeting_main_video_view.dart';
|
import 'package:wgshare/pages/metting/video/meeting_main_video_view.dart';
|
||||||
|
|
@ -9,6 +10,7 @@ import 'package:wgshare/utils/toast_utils.dart';
|
||||||
|
|
||||||
import '../../utils/color_util.dart';
|
import '../../utils/color_util.dart';
|
||||||
import '../../utils/cus_behavior.dart';
|
import '../../utils/cus_behavior.dart';
|
||||||
|
import '../../view/view_svg_path.dart';
|
||||||
import 'meeting_main_logic.dart';
|
import 'meeting_main_logic.dart';
|
||||||
import 'meeting_main_state.dart';
|
import 'meeting_main_state.dart';
|
||||||
import 'voice/meeting_main_voice_view.dart';
|
import 'voice/meeting_main_voice_view.dart';
|
||||||
|
|
@ -167,19 +169,21 @@ class MeetingMainPage extends StatelessWidget {
|
||||||
|
|
||||||
// 语音
|
// 语音
|
||||||
Visibility(
|
Visibility(
|
||||||
visible: true,
|
visible: state.pageState.value == 0,
|
||||||
child: MeetingMainVoiceComponent(users: state.cacheUsers.value)
|
child: MeetingMainVoiceComponent(users: state.cacheUsers.value)
|
||||||
),
|
),
|
||||||
|
|
||||||
// 视频
|
// 视频
|
||||||
Visibility(
|
Visibility(
|
||||||
visible: false,
|
visible: state.pageState.value == 1,
|
||||||
child: MeetingMainVideoComponent()
|
child: null != state.rctEngine.value
|
||||||
|
? MeetingMainVideoComponent(rtcEngine: state.rctEngine.value!, channelId: state.roomNumber.value,isOpenCamera: state.isOpenCamera.value)
|
||||||
|
: Container()
|
||||||
),
|
),
|
||||||
|
|
||||||
// 共享屏幕
|
// 共享屏幕
|
||||||
Visibility(
|
Visibility(
|
||||||
visible: false,
|
visible: state.pageState.value == 2,
|
||||||
child: MeetingMainShareComponent()
|
child: MeetingMainShareComponent()
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
@ -247,15 +251,33 @@ class MeetingMainPage extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Image.asset(
|
state.isSpeak.value == false
|
||||||
|
? Image.asset(
|
||||||
state.isSpeak.value == false
|
state.isSpeak.value == false
|
||||||
? 'assets/images/meeting_main_sqfy.png'
|
? 'assets/images/meeting_main_sqfy.png'
|
||||||
: state.isOpenMicrophone.value == true
|
: state.isOpenMicrophone.value == true
|
||||||
? 'assets/images/meeting_main_microphone_default.png'
|
? 'assets/images/meeting_main_microphone_default.png'
|
||||||
: 'assets/images/meeting_main_sqfy.png',
|
: 'assets/images/meeting_main_sqfy.png',
|
||||||
width: 22.w,
|
width: 20.w,
|
||||||
height: 22.h,
|
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),
|
SizedBox(height: 4.h),
|
||||||
Text(
|
Text(
|
||||||
state.isSpeak.value == false ? '申请发言' : state.isOpenMicrophone.value == true ? "手动静音" : "解除静音",
|
state.isSpeak.value == false ? '申请发言' : state.isOpenMicrophone.value == true ? "手动静音" : "解除静音",
|
||||||
|
|
@ -288,13 +310,13 @@ class MeetingMainPage extends StatelessWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Image.asset(
|
Image.asset(
|
||||||
'assets/images/meeting_main_sp.png',
|
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,
|
width: 22.w,
|
||||||
height: 22.h,
|
height: 22.h,
|
||||||
),
|
),
|
||||||
SizedBox(height: 4.h),
|
SizedBox(height: 4.h),
|
||||||
Text(
|
Text(
|
||||||
'开启视频',
|
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),
|
||||||
|
|
@ -302,7 +324,13 @@ class MeetingMainPage extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: (){
|
onTap: (){
|
||||||
ToastUtils.getErrFluttertoast(context: context, msg: '开启视频...');
|
if(state.isSpeak.value == true){
|
||||||
|
if(state.isOpenCamera.value == true){
|
||||||
|
logic.setCameraOpen(false);
|
||||||
|
}else{
|
||||||
|
logic.setCameraOpen(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,19 @@
|
||||||
|
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:wgshare/common/store/user_store.dart';
|
||||||
|
|
||||||
import '../../../utils/color_util.dart';
|
import '../../../utils/color_util.dart';
|
||||||
import 'meeting_main_video_logic.dart';
|
import 'meeting_main_video_logic.dart';
|
||||||
import 'meeting_main_video_state.dart';
|
import 'meeting_main_video_state.dart';
|
||||||
|
|
||||||
class MeetingMainVideoComponent extends StatelessWidget {
|
class MeetingMainVideoComponent extends StatelessWidget {
|
||||||
MeetingMainVideoComponent({Key? key}) : super(key: key);
|
MeetingMainVideoComponent({super.key, required this.rtcEngine, required this.channelId, required this.isOpenCamera});
|
||||||
|
|
||||||
|
final RtcEngine rtcEngine;
|
||||||
|
final String channelId;
|
||||||
|
final bool isOpenCamera;
|
||||||
|
|
||||||
final MeetingMainVideoLogic logic = Get.put(MeetingMainVideoLogic());
|
final MeetingMainVideoLogic logic = Get.put(MeetingMainVideoLogic());
|
||||||
final MeetingMainVideoState state = Get.find<MeetingMainVideoLogic>().state;
|
final MeetingMainVideoState state = Get.find<MeetingMainVideoLogic>().state;
|
||||||
|
|
@ -85,23 +91,28 @@ class MeetingMainVideoComponent extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
/// 右上角小窗
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 58,
|
top: 58,
|
||||||
right: 13,
|
right: 12,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Visibility(
|
||||||
width: 120.w,
|
visible: isOpenCamera,
|
||||||
height: 150.h,
|
child: SizedBox(
|
||||||
padding: const EdgeInsets.only(left: 12, right: 12),
|
width: 120.w,
|
||||||
decoration: BoxDecoration(
|
height: 150.h,
|
||||||
image: DecorationImage(
|
child: Center(
|
||||||
fit: BoxFit.fill,
|
child: isOpenCamera
|
||||||
image: NetworkImage(
|
? AgoraVideoView(
|
||||||
"https://tse1-mm.cn.bing.net/th/id/OIP-C.hdhK40Dw3yN_2mjNQNqFCgAAAA?w=186&h=186&c=7&r=0&o=5&pid=1.7",
|
controller: VideoViewController(
|
||||||
),
|
rtcEngine: rtcEngine,
|
||||||
|
canvas: VideoCanvas(uid: int.parse(UserStore.to.userInfoEntity.value!.uid)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
: const CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
left: 4,
|
left: 4,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:liquid_progress_indicator_v2/liquid_progress_indicator.dart';
|
||||||
|
|
||||||
import '../../../common/models/meeting_room_user.dart';
|
import '../../../common/models/meeting_room_user.dart';
|
||||||
import '../../../utils/color_util.dart';
|
import '../../../utils/color_util.dart';
|
||||||
import '../../../utils/cus_behavior.dart';
|
import '../../../utils/cus_behavior.dart';
|
||||||
|
import '../../../view/view_svg_path.dart';
|
||||||
import 'meeting_main_voice_logic.dart';
|
import 'meeting_main_voice_logic.dart';
|
||||||
import 'meeting_main_voice_state.dart';
|
import 'meeting_main_voice_state.dart';
|
||||||
|
|
||||||
|
|
@ -54,13 +56,21 @@ class MeetingMainVoiceComponent extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 6.h),
|
SizedBox(height: 6.h),
|
||||||
Row(
|
users[index].enableMicr == true
|
||||||
|
? Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Image.asset(
|
Container(
|
||||||
users[index].enableMicr == true ? 'assets/images/meeting_main_speak1.png' : 'assets/images/meeting_main_microphone_open.png',
|
width: 20.w,
|
||||||
width: 22.w,
|
height: 20.h,
|
||||||
height: 22.h,
|
child: LiquidCustomProgressIndicator(
|
||||||
|
value: users[index].volume ?? 0.0,
|
||||||
|
valueColor: const AlwaysStoppedAnimation(ColorUtil.Color_2_177_136),
|
||||||
|
backgroundColor: ColorUtil.Color_255_255_255,
|
||||||
|
direction: Axis.vertical,
|
||||||
|
shapePath: ViewSvgPath.getMicrpphonePath()
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
users[index].userName,
|
users[index].userName,
|
||||||
|
|
@ -69,6 +79,23 @@ class MeetingMainVoiceComponent extends StatelessWidget {
|
||||||
color: ColorUtil.Color_255_255_255),
|
color: ColorUtil.Color_255_255_255),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
)
|
||||||
|
: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Image.asset(
|
||||||
|
'assets/images/meeting_main_microphone_open.png',
|
||||||
|
width: 20.w,
|
||||||
|
height: 20.h,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
users[index].userName,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12.sp,
|
||||||
|
color: ColorUtil.Color_255_255_255),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
/// 计算声网SDK返回的用户音量
|
||||||
|
class CountMicrophoneVolume {
|
||||||
|
|
||||||
|
static double getVolume(int volume){
|
||||||
|
var resultVolume = 0.0;
|
||||||
|
if(volume == 0){
|
||||||
|
resultVolume = 0;
|
||||||
|
}else if(volume > 0 && volume < 200){
|
||||||
|
resultVolume = volume / 200;
|
||||||
|
}else{
|
||||||
|
resultVolume = 1;
|
||||||
|
}
|
||||||
|
return resultVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// 各类SVG路径
|
||||||
|
class ViewSvgPath {
|
||||||
|
|
||||||
|
/// 麦克风
|
||||||
|
static Path getMicrpphonePath(){
|
||||||
|
Path mPath = Path();
|
||||||
|
mPath.moveTo(10.2188, 11.875);
|
||||||
|
mPath.cubicTo(11.9375, 11.875, 13.3438, 10.4688, 13.3438, 8.75);
|
||||||
|
mPath.lineTo(13.3438, 5);
|
||||||
|
mPath.cubicTo(13.3438, 3.28125, 11.9375, 1.875, 10.2188, 1.875);
|
||||||
|
mPath.cubicTo(8.5, 1.875, 7.09375, 3.28125, 7.09375, 5);
|
||||||
|
mPath.lineTo(7.09375, 8.75);
|
||||||
|
mPath.cubicTo(7.09375, 10.4688, 8.5, 11.875, 10.2188, 11.875);
|
||||||
|
|
||||||
|
mPath.moveTo(15.777, 9.61683);
|
||||||
|
mPath.cubicTo(15.8297, 9.27504, 15.5973, 8.95668, 15.2555, 8.90394);
|
||||||
|
mPath.cubicTo(14.9137, 8.85316, 14.5954, 9.08558, 14.5426, 9.42543);
|
||||||
|
mPath.cubicTo(14.2145, 11.5348, 12.3571, 13.1246, 10.2184, 13.1246);
|
||||||
|
mPath.cubicTo(8.07973, 13.1246, 6.22035, 11.5329, 5.89418, 9.42348);
|
||||||
|
mPath.cubicTo(5.84144, 9.08168, 5.52113, 8.84926, 5.18129, 8.90199);
|
||||||
|
mPath.cubicTo(4.83949, 8.95473, 4.60707, 9.27308, 4.6598, 9.61488);
|
||||||
|
mPath.cubicTo(5.05433, 12.1637, 7.08168, 14.0641, 9.5934, 14.3375);
|
||||||
|
mPath.lineTo(9.5934, 16.2496);
|
||||||
|
mPath.lineTo(7.7184, 16.2496);
|
||||||
|
mPath.cubicTo(7.37269, 16.2496, 7.0934, 16.5289, 7.0934, 16.8746);
|
||||||
|
mPath.cubicTo(7.0934, 17.2204, 7.37269, 17.4996, 7.7184, 17.4996);
|
||||||
|
mPath.lineTo(12.7184, 17.4996);
|
||||||
|
mPath.cubicTo(13.0641, 17.4996, 13.3434, 17.2204, 13.3434, 16.8746);
|
||||||
|
mPath.cubicTo(13.3434, 16.5289, 13.0641, 16.2496, 12.7184, 16.2496);
|
||||||
|
mPath.lineTo(10.8434, 16.2496);
|
||||||
|
mPath.lineTo(10.8434, 14.3375);
|
||||||
|
mPath.cubicTo(13.3532, 14.0641, 15.3825, 12.1657, 15.777, 9.61683);
|
||||||
|
mPath.close();
|
||||||
|
return mPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -594,6 +594,14 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.0"
|
||||||
|
liquid_progress_indicator_v2:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: liquid_progress_indicator_v2
|
||||||
|
sha256: "6bb2c675bab4936864a63ccd503be417e407974e11c62711917a4006bb9288b8"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.0"
|
||||||
logger:
|
logger:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,9 @@ dependencies:
|
||||||
# .net socket通信插件
|
# .net socket通信插件
|
||||||
signalr_core: ^1.1.1
|
signalr_core: ^1.1.1
|
||||||
|
|
||||||
|
# 水波效果的进度器
|
||||||
|
liquid_progress_indicator_v2: ^0.5.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue