2026-07-10 20:31:52 +08:00

1732 lines
52 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:fluro/fluro.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:aslan/app_localizations.dart';
import 'package:aslan/chatvibe_core/constants/at_room_msg_type.dart';
import 'package:aslan/chatvibe_core/utilities/at_heartbeat_utils.dart';
import 'package:aslan/chatvibe_core/utilities/at_permission_utils.dart';
import 'package:aslan/chatvibe_core/utilities/at_room_utils.dart';
import 'package:aslan/chatvibe_data/sources/local/user_manager.dart';
import 'package:aslan/chatvibe_data/sources/repositories/family_repository_impl.dart';
import 'package:aslan/chatvibe_data/sources/repositories/room_repository_imp.dart';
import 'package:aslan/chatvibe_managers/room_manager.dart';
import 'package:aslan/chatvibe_managers/rtm_manager.dart';
import 'package:aslan/chatvibe_managers/user_profile_manager.dart';
import 'package:aslan/chatvibe_ui/widgets/room/redpack/room_redenvelope_list_page.dart';
import 'package:aslan/chatvibe_ui/widgets/room/room_msg_item.dart';
import 'package:provider/provider.dart';
import 'package:aslan/chatvibe_ui/components/at_float_ichart.dart';
import 'package:aslan/chatvibe_core/constants/at_global_config.dart';
import 'package:aslan/chatvibe_core/routes/at_routes.dart';
import 'package:aslan/chatvibe_core/routes/at_fluro_navigator.dart';
import 'package:aslan/chatvibe_core/utilities/at_lk_dialog_util.dart';
import 'package:aslan/chatvibe_core/utilities/at_loading_manager.dart';
import 'package:aslan/chatvibe_core/utilities/at_gift_vap_svga_manager.dart';
import 'package:aslan/chatvibe_data/sources/repositories/user_repository_impl.dart';
import 'package:aslan/chatvibe_domain/models/res/family_base_info_res.dart';
import 'package:aslan/chatvibe_domain/models/res/game_ludo_res.dart';
import 'package:aslan/chatvibe_domain/models/res/join_room_res.dart';
import 'package:aslan/chatvibe_domain/models/res/login_res.dart';
import 'package:aslan/chatvibe_domain/models/res/mic_res.dart';
import 'package:aslan/chatvibe_domain/models/res/room_res.dart';
import 'package:aslan/chatvibe_features/room/voice_room_route.dart';
import 'package:aslan/chatvibe_ui/widgets/room/empty_mai_select.dart';
import 'package:aslan/chatvibe_ui/widgets/room/join_room_member_page.dart';
import 'package:aslan/chatvibe_ui/widgets/room/at_room_user_info_card.dart';
import 'package:aslan/chatvibe_managers/audio_manager.dart';
import '../chatvibe_data/models/enum/at_heartbeat_status.dart';
import '../chatvibe_data/models/enum/at_room_info_event_type.dart';
import '../chatvibe_data/models/enum/at_room_roles_type.dart';
import '../chatvibe_data/models/enum/at_vip_type.dart';
import '../chatvibe_data/sources/local/at_foreground_service_helper.dart';
import '../chatvibe_domain/models/res/at_get_list_game_config_res.dart';
import '../chatvibe_domain/models/res/at_is_follow_room_res.dart';
import '../chatvibe_domain/models/res/at_room_red_packet_list_res.dart';
import '../chatvibe_domain/models/res/at_room_rocket_status_res.dart';
import '../chatvibe_domain/models/res/at_room_theme_list_res.dart';
import '../chatvibe_features/gift/gift_page.dart';
import '../chatvibe_ui/components/at_tts.dart';
import '../chatvibe_ui/widgets/room/game/room_game_list_page.dart';
typedef OnSoundVoiceChange = Function(num index, int volum);
typedef RtcProvider = RealTimeCommunicationManager;
class RealTimeCommunicationManager extends ChangeNotifier {
bool needUpDataUserInfo = false;
///当前所在房间
JoinRoomRes? currenRoom;
/// 声音音量变化监听
List<OnSoundVoiceChange> _onSoundVoiceChangeList = [];
///麦位
Map<num, MicRes> roomWheatMap = {};
final Set<int> _remoteRtcUidsInChannel = <int>{};
Timer? _roomStateResyncTimer;
Timer? _pendingMicResyncTimer;
bool _isRefreshingMicList = false;
static const Duration _roomStateResyncInterval = Duration(seconds: 15);
static const Duration _micChangeResyncDelay = Duration(milliseconds: 800);
BigInt? _lastMicChangeTimeId;
RtcEngine? engine;
BuildContext? context;
RtmProvider? rtmProvider;
ATIsFollowRoomRes? isFollowRoomRes;
ATRoomRocketStatusRes? roomRocketStatus;
ChatVibeFamilyBaseInfoRes? familyBaseInfoRes;
///正在玩的ludo游戏
GameLudoRes? playingLudoGame;
///是否是最小化ludo游戏
bool isMinLudoGame = false;
///房间是否静音
bool roomIsMute = false;
bool closeFullGame = false;
///禁音开关 默认关闭
bool isMic = true;
///在线用户列表
List<ChatVibeUserProfile> onlineUsers = [];
///房间管理员
List<ChatVibeUserProfile> managerUsers = [];
///音乐是否正在播放
bool isMusicPlaying = false;
///房间红包列表
List<ATRoomRedPacketListRes> redPacketList = [];
num roomTaskClaimableCount = 0;
bool _isJoiningRoom = false;
bool _isExitingRoom = false;
int _roomSessionId = 0;
Future<void>? _exitRoomFuture;
init(BuildContext context) {
this.context = context;
}
int _nextRoomSessionId() {
_roomSessionId++;
return _roomSessionId;
}
bool _isRoomSessionActive(int roomSessionId, String roomId) {
return !_isExitingRoom &&
_roomSessionId == roomSessionId &&
currenRoom?.roomProfile?.roomProfile?.id == roomId;
}
Future<void> joinAgoraChannel({
required int roomSessionId,
required String roomId,
}) async {
try {
final RtcEngine rtcEngine = await _initAgoraRtcEngine();
if (!_isRoomSessionActive(roomSessionId, roomId)) {
await _shutdownRtcEngine(rtcEngine);
return;
}
engine = rtcEngine;
_remoteRtcUidsInChannel.clear();
rtcEngine.setAudioProfile(
profile: AudioProfileType.audioProfileIot,
scenario: AudioScenarioType.audioScenarioMeeting,
);
rtcEngine.enableAudioVolumeIndication(
interval: 500,
smooth: 3,
reportVad: true,
);
await rtcEngine.disableVideo();
await rtcEngine.setLocalPublishFallbackOption(
StreamFallbackOptions.streamFallbackOptionAudioOnly,
);
rtcEngine.registerEventHandler(
RtcEngineEventHandler(
onError: (ErrorCodeType err, String msg) {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
print('rtc错误${err}');
},
onLocalAudioStateChanged:
(
RtcConnection connection,
LocalAudioStreamState state,
LocalAudioStreamReason reason,
) {},
onAudioRoutingChanged: (routing) {},
onAudioMixingStateChanged: (
AudioMixingStateType state,
AudioMixingReasonType reason,
) {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
Provider.of<AudioManager>(
context!,
listen: false,
).setPlayState(state, context!);
switch (state) {
case AudioMixingStateType.audioMixingStatePlaying:
isMusicPlaying = true;
break;
case AudioMixingStateType.audioMixingStateStopped:
case AudioMixingStateType.audioMixingStateFailed:
isMusicPlaying = false;
break;
default:
break;
}
},
onRemoteAudioStateChanged: (
RtcConnection connection,
int remoteUid,
RemoteAudioState state,
RemoteAudioStateReason reason,
int elapsed,
) {
// print('用户 $remoteUid 音频状态: $state, 原因: $reason');
},
onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
print('rtc 自己加入 ${connection.channelId} ${connection.localUid}');
},
onUserJoined: (connection, remoteUid, elapsed) {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
print('rtc用户 $remoteUid 加入了频道');
_remoteRtcUidsInChannel.add(remoteUid);
_applyRemoteAudioPolicy();
},
// 监听远端用户离开
onUserOffline: (connection, remoteUid, reason) {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
print('rtc用户 $remoteUid 离开了频道 (原因: ${reason})');
_remoteRtcUidsInChannel.remove(remoteUid);
_applyRemoteAudioPolicy();
},
onTokenPrivilegeWillExpire: (
RtcConnection connection,
String token,
) async {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
var rtcToken = await AccountRepository().getRtcToken(
roomId,
AccountStorage().getCurrentUser()?.userProfile?.id ?? "",
);
if (_isRoomSessionActive(roomSessionId, roomId) &&
identical(engine, rtcEngine)) {
rtcEngine.renewToken(rtcToken.rtcToken ?? "");
}
},
onAudioVolumeIndication: (
RtcConnection connection,
List<AudioVolumeInfo> speakers,
int speakerNumber,
int totalVolume,
) {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
initOnAudioVolumeIndication(
connection,
speakers,
speakerNumber,
totalVolume,
);
},
),
);
var rtcToken = await AccountRepository().getRtcToken(
roomId,
AccountStorage().getCurrentUser()?.userProfile?.id ?? "",
);
if (!_isRoomSessionActive(roomSessionId, roomId)) {
if (identical(engine, rtcEngine)) {
engine = null;
}
await _shutdownRtcEngine(rtcEngine);
return;
}
await rtcEngine.joinChannel(
token: rtcToken.rtcToken ?? "",
channelId: roomId,
uid: int.parse(
AccountStorage().getCurrentUser()?.userProfile?.account ?? "0",
),
options: ChannelMediaOptions(
// 自动订阅所有视频流
autoSubscribeVideo: false,
// 自动订阅所有音频流
autoSubscribeAudio: true,
// 发布摄像头采集的视频
publishCameraTrack: false,
// 发布麦克风采集的音频
publishMicrophoneTrack: true,
// 设置用户角色为 clientRoleBroadcaster主播或 clientRoleAudience观众
clientRoleType: ClientRoleType.clientRoleAudience,
channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
),
);
if (!_isRoomSessionActive(roomSessionId, roomId)) {
if (identical(engine, rtcEngine)) {
engine = null;
}
await _shutdownRtcEngine(rtcEngine);
return;
}
rtcEngine.muteAllRemoteAudioStreams(roomIsMute);
await syncLocalPublishStateFromMicSnapshot();
await _applyRemoteAudioPolicy();
} catch (e) {
if (_isRoomSessionActive(roomSessionId, roomId)) {
ATTts.show("Join room fail");
extRoom(false);
}
print('加入失败:${e.runtimeType},${e.toString()}');
}
}
Future<RtcEngine> _initAgoraRtcEngine() async {
RtcEngine? engine;
while (engine == null) {
engine = createAgoraRtcEngine();
await engine.initialize(
RtcEngineContext(appId: ATGlobalConfig.agoraRtcAppid),
);
}
return engine;
}
int? _parseRtcUid(String? account) {
if (account == null || account.isEmpty) {
return null;
}
return int.tryParse(account);
}
Set<int> _buildAllowedSpeakerUids() {
final Set<int> allowed = <int>{};
for (final mic in roomWheatMap.values) {
if (mic.user == null) {
continue;
}
if (mic.micMute == true) {
continue;
}
final int? uid = _parseRtcUid(mic.user?.account);
if (uid != null) {
allowed.add(uid);
}
}
return allowed;
}
Future<void> _applyRemoteAudioPolicy() async {
if (engine == null) {
return;
}
final Set<int> allowedSpeakerUids = _buildAllowedSpeakerUids();
for (final int uid in _remoteRtcUidsInChannel) {
final bool shouldMute = roomIsMute || !allowedSpeakerUids.contains(uid);
try {
await engine?.muteRemoteAudioStream(uid: uid, mute: shouldMute);
} catch (_) {
// 忽略单个用户静音失败,避免中断整体策略应用
}
}
}
void _startRoomStateResyncTimer() {
_stopRoomStateResyncTimer();
_roomStateResyncTimer = Timer.periodic(_roomStateResyncInterval, (_) {
if (currenRoom == null) {
return;
}
getMicList();
getOnlineUsers();
});
}
void _stopRoomStateResyncTimer() {
_roomStateResyncTimer?.cancel();
_roomStateResyncTimer = null;
}
void _scheduleMicStateResync() {
_pendingMicResyncTimer?.cancel();
_pendingMicResyncTimer = Timer(_micChangeResyncDelay, () {
if (currenRoom != null && !_isRefreshingMicList && !_isExitingRoom) {
getMicList();
}
});
}
BigInt? _parseMicChangeTimeId(String? timeId) {
if (timeId == null || timeId.isEmpty) {
return null;
}
return BigInt.tryParse(timeId);
}
bool _shouldAcceptMicChange(String? timeId) {
final BigInt? nextTimeId = _parseMicChangeTimeId(timeId);
if (nextTimeId == null) {
return true;
}
if (_lastMicChangeTimeId != null && nextTimeId < _lastMicChangeTimeId!) {
return false;
}
_lastMicChangeTimeId = nextTimeId;
return true;
}
MicRes _cloneMicWithUser(MicRes mic, ChatVibeUserProfile? user) {
return MicRes(
roomId: mic.roomId,
micIndex: mic.micIndex,
micLock: mic.micLock,
micMute: mic.micMute,
user: user,
roomToken: mic.roomToken,
emojiPath: mic.emojiPath,
type: mic.type,
number: mic.number,
);
}
List<MicRes> _normalizeMicSnapshot(List<MicRes> mics) {
final Set<String> seenUserIds = <String>{};
final List<MicRes> normalized = <MicRes>[];
for (final mic in mics) {
final String? userId = mic.user?.id;
if (userId != null && userId.isNotEmpty) {
if (seenUserIds.contains(userId)) {
normalized.add(_cloneMicWithUser(mic, null));
continue;
}
seenUserIds.add(userId);
}
normalized.add(mic);
}
return normalized;
}
Future<void> _shutdownRtcEngine(RtcEngine currentEngine) async {
try {
await currentEngine.muteLocalAudioStream(true);
} catch (_) {}
try {
await currentEngine.muteAllRemoteAudioStreams(true);
} catch (_) {}
try {
await currentEngine.stopAudioMixing();
} catch (_) {}
try {
await currentEngine.setClientRole(
role: ClientRoleType.clientRoleAudience,
);
} catch (_) {}
try {
await currentEngine.leaveChannel();
} catch (_) {}
try {
await Future.delayed(Duration(milliseconds: 100));
await currentEngine.release();
} catch (_) {}
}
Future<void> _disposeRtcEngine() async {
final currentEngine = engine;
engine = null;
if (currentEngine == null) {
_remoteRtcUidsInChannel.clear();
return;
}
await _shutdownRtcEngine(currentEngine);
_remoteRtcUidsInChannel.clear();
}
Future<void> syncLocalPublishStateFromMicSnapshot() async {
if (engine == null) {
return;
}
final String? myUserId = AccountStorage().getCurrentUser()?.userProfile?.id;
if (myUserId == null || myUserId.isEmpty) {
return;
}
final num myMicIndex = userOnMaiInIndex(myUserId);
final bool isOnMic = myMicIndex > -1;
final bool isMicMutedByRoom =
isOnMic ? (roomWheatMap[myMicIndex]?.micMute ?? true) : true;
final bool shouldPublish = isOnMic && !isMicMutedByRoom && !isMic;
final bool shouldKeepMusicPublishing =
isOnMic && !isMicMutedByRoom && isMic && isMusicPlaying;
if (shouldPublish) {
await engine?.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
adjustRecordingSignalVolume(100);
await engine?.muteLocalAudioStream(false);
ATHeartbeatUtils.scheduleAnchorHeartbeat(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
);
return;
}
if (shouldKeepMusicPublishing) {
await engine?.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
adjustRecordingSignalVolume(0);
await engine?.muteLocalAudioStream(false);
ATHeartbeatUtils.scheduleAnchorHeartbeat(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
);
return;
}
await engine?.setClientRole(role: ClientRoleType.clientRoleAudience);
await engine?.muteLocalAudioStream(true);
if (!isOnMic) {
isMic = true;
stopMusic();
}
}
void initOnAudioVolumeIndication(
RtcConnection connection,
List<AudioVolumeInfo> speakers,
int speakerNumber,
int totalVolume,
) {
// if (user == null) {
// throw "本地User尚未初始化";
// }
// print('初始化声音监听器:${user.toJson()}');
///声音全部清零
roomWheatMap.forEach((k, v) {
roomWheatMap[k]!.setVolume = 0;
});
for (var info in speakers) {
num? uid = info.uid;
int voloum = info.volume!;
print('${info.uid}在说话---${voloum}');
if (voloum > 0) {
///是本地声音
if (uid == 0) {
uid = num.parse(
AccountStorage().getCurrentUser()!.userProfile!.account!,
);
}
///在哪个麦
roomWheatMap.forEach((k, v) {
if (v.user != null) {
if (num.parse(v.user!.account!) == uid) {
roomWheatMap[k]!.setVolume = voloum;
for (var element in _onSoundVoiceChangeList) {
element.call(k, voloum);
}
}
}
});
}
}
}
///关注/取消房间
void followRoom() async {
var result = await AccountRepository().followRoom(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
);
if (isFollowRoomRes != null) {
isFollowRoomRes = isFollowRoomRes!.copyWith(
followRoom: !isFollowRoomRes!.followRoom!,
);
} else {
isFollowRoomRes = ATIsFollowRoomRes(followRoom: result);
}
SmartDialog.dismiss(tag: "unFollowDialog");
notifyListeners();
}
int startTime = 0;
void joinRoom(
BuildContext context,
String roomId, {
String? pwd,
bool clearRoomData = false,
bool needOpenRedenvelope = false,
String redPackId = "",
bool openGameDialog = false,
bool openGiftDialogToLuckyGift = false,
bool openGiftDialogToGift = false,
}) async {
if (_isJoiningRoom || _isExitingRoom) {
return;
}
_isJoiningRoom = true;
int nextTime = DateTime.now().millisecondsSinceEpoch;
if (nextTime - startTime < 1000) {
//频繁点击
_isJoiningRoom = false;
return;
}
startTime = nextTime;
try {
if (clearRoomData) {
if (currenRoom != null || engine != null) {
await extRoom(false, navigateHome: false);
} else {
_nextRoomSessionId();
_clearData();
}
}
bool hasPermission = await ATPermissionUtils.checkMicrophonePermission();
if (!hasPermission) {
ATTts.show('Microphone permission is denied.');
return;
}
if (roomId == currenRoom?.roomProfile?.roomProfile?.id) {
///最小化进入房间,或者进入的是同一个房间
loadRoomInfo(currenRoom?.roomProfile?.roomProfile?.id ?? "");
Provider.of<ChatVibeUserProfileManager>(
context,
listen: false,
).getMyUserInfo();
getMicList();
ATFloatIchart().remove();
ATNavigatorUtils.push(
context,
'${VoiceRoomRoute.voiceRoom}?id=$roomId',
transition: TransitionType.custom,
transitionDuration: kOpenRoomTransitionDuration,
transitionBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return kOpenRoomTransitionBuilder(
context,
animation,
secondaryAnimation,
child,
);
},
);
} else {
ATFloatIchart().remove();
if (currenRoom != null) {
// 切房时先退出当前房间,但不跳回 Home避免 context 失效导致后续 join 偶发失败
await extRoom(false, navigateHome: false);
}
rtmProvider = Provider.of<RtmProvider>(context, listen: false);
ATLoadingManager.exhibitOperation(context: context);
currenRoom = await AccountRepository().entryRoom(
roomId,
pwd: pwd,
redPackId: redPackId,
needOpenRedenvelope: needOpenRedenvelope,
);
final int roomSessionId = _nextRoomSessionId();
if (currenRoom?.entrants?.roles == ATRoomRolesType.TOURIST.name) {
// SmartDialog.show(
// tag: "showJoinRoomMember",
// alignment: Alignment.center,
// animationType: SmartAnimationType.fade,
// clickMaskDismiss: false,
// backType: SmartBackType.block,
// builder: (_) {
// return JoinRoomMemberPage(
// currenRoom?.roomProfile?.roomProfile?.id ?? "",
// () {
// ATLoadingManager.exhibitOperation(context: context);
// //加入会员
// ChatRoomRepository()
// .changeRoomRole(
// roomId,
// ATRoomRolesType.ADMIN.name,
// AccountStorage().getCurrentUser()?.userProfile?.id ??
// "",
// AccountStorage().getCurrentUser()?.userProfile?.id ??
// "",
// "ONESELF_JOIN",
// )
// .then(
// (result) async {
// currenRoom = currenRoom?.copyWith(
// entrants: currenRoom?.entrants?.copyWith(
// roles: ATRoomRolesType.MEMBER.name,
// ),
// );
// await initRoon(
// roomSessionId: roomSessionId,
// needOpenRedenvelope: needOpenRedenvelope,
// redPackId: redPackId,
// );
// ATLoadingManager.veilRoutine();
// notifyListeners();
// },
// onError: (e) {
// currenRoom = null;
// ATLoadingManager.veilRoutine();
// },
// );
// },
// () {
// _nextRoomSessionId();
// currenRoom = null;
// },
// () async {
await initRoon(
roomSessionId: roomSessionId,
needOpenRedenvelope: needOpenRedenvelope,
redPackId: redPackId,
);
ATLoadingManager.veilRoutine();
notifyListeners();
// },
// );
// },
// );
ATLoadingManager.veilRoutine();
} else {
await initRoon(
roomSessionId: roomSessionId,
needOpenRedenvelope: needOpenRedenvelope,
redPackId: redPackId,
);
ATLoadingManager.veilRoutine();
notifyListeners();
}
}
} catch (e) {
ATLoadingManager.veilRoutine();
print('joinRoom fail: $e');
} finally {
_isJoiningRoom = false;
}
if (openGameDialog) {
showBottomInBottomDialog(context, RoomGameListPage());
}
if (openGiftDialogToLuckyGift) {
SmartDialog.show(
tag: "showGiftControl",
alignment: Alignment.bottomCenter,
maskColor: Colors.transparent,
animationType: SmartAnimationType.fade,
clickMaskDismiss: true,
builder: (_) {
return GiftPage(initialIndex: 1);
},
);
}
if (openGiftDialogToGift) {
SmartDialog.show(
tag: "showGiftControl",
alignment: Alignment.bottomCenter,
maskColor: Colors.transparent,
animationType: SmartAnimationType.fade,
clickMaskDismiss: true,
builder: (_) {
return GiftPage();
},
);
}
}
///初始化房间相关
Future initRoon({
required int roomSessionId,
bool needOpenRedenvelope = false,
String? redPackId,
}) async {
final String roomId = currenRoom?.roomProfile?.roomProfile?.id ?? "";
if (roomId.isEmpty || !_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
if ((currenRoom?.roomProfile?.roomProfile?.event ==
ATRoomInfoEventType.WAITING_CONFIRMED.name ||
currenRoom?.roomProfile?.roomProfile?.event ==
ATRoomInfoEventType.ID_CHANGE.name) &&
currenRoom?.entrants?.roles == ATRoomRolesType.HOMEOWNER.name) {
///需要去修改房间信息,创建群聊
ATNavigatorUtils.push(
context!,
"${VoiceRoomRoute.roomEdit}?need=true",
replace: false,
);
return Future;
}
ATRoomUtils.roomAtGlobalConfig(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
);
if (currenRoom?.roomProfile?.roomProfile?.id !=
AccountStorage().getCurrentUser()?.userProfile?.id) {
ChatRoomRepository()
.isFollowRoom(currenRoom?.roomProfile?.roomProfile?.id ?? "")
.then((value) {
isFollowRoomRes = value;
notifyListeners();
});
}
ATNavigatorUtils.push(context!, VoiceRoomRoute.voiceRoom, replace: false);
///暂时让他每次都走一次创建群组新的腾讯云IM数据迁移
await Provider.of<RtmProvider>(context!, listen: false).createRoomGroup(
currenRoom?.roomProfile?.roomProfile?.roomAccount ?? "",
currenRoom?.roomProfile?.roomProfile?.roomName ?? "",
);
var joinResult = await rtmProvider?.joinRoomGroup(
currenRoom?.roomProfile?.roomProfile?.roomAccount ?? "",
"",
);
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
ChatRoomRepository()
.rocketClaim(currenRoom?.roomProfile?.roomProfile?.id ?? "")
.catchError((e) => false);
rtmProvider?.addMsg(
Msg(
groupId: currenRoom?.roomProfile?.roomProfile?.roomAccount ?? "",
msg: ATAppLocalizations.of(context!)!.systemRoomTips,
type: ATRoomMsgType.systemTips,
),
);
rtmProvider?.addMsg(
Msg(
groupId: currenRoom?.roomProfile?.roomProfile?.roomAccount ?? "",
msg: currenRoom?.roomProfile?.roomProfile?.roomDesc,
type: ATRoomMsgType.systemTips,
),
);
///获取麦位
getMicList();
Provider.of<ChatVibeRoomManager>(
context!,
listen: false,
).contributionLevel(currenRoom?.roomProfile?.roomProfile?.id ?? "");
await joinAgoraChannel(roomSessionId: roomSessionId, roomId: roomId);
if (_isRoomSessionActive(roomSessionId, roomId)) {
_startRoomStateResyncTimer();
} else {
return;
}
if (joinResult?.code == 0) {
Msg joinMsg = Msg(
groupId: currenRoom?.roomProfile?.roomProfile?.roomAccount ?? "",
user: AccountStorage().getCurrentUser()?.userProfile,
msg: "",
role: currenRoom?.entrants?.roles ?? "",
type: ATRoomMsgType.joinRoom,
);
rtmProvider?.sendMsg(joinMsg, addLocal: true);
if (ATGlobalConfig.isEntryVehicleAnimation) {
if (AccountStorage().getCurrentUser()?.userProfile?.getMountains() !=
null) {
Future.delayed(Duration(milliseconds: 500), () {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
ATGiftVapSvgaManager().play(
AccountStorage()
.getCurrentUser()
?.userProfile
?.getMountains()
?.sourceUrl ??
"",
priority: 100,
type: 1,
);
});
}
}
if (rtmProvider?.msgUserJoinListener != null) {
rtmProvider?.msgUserJoinListener!(joinMsg);
}
}
ChatRoomRepository()
.rocketStatus(currenRoom?.roomProfile?.roomProfile?.id ?? "")
.then((res) {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
roomRocketStatus = res;
notifyListeners();
})
.catchError((e) {});
ATForegroundServiceHelper().startService();
loadRoomRedPacketList(1);
if (needOpenRedenvelope) {
openRedEnvelope(redPackId ?? "");
}
GroupRepository()
.familyUserBaseInfo(currenRoom?.roomProfile?.userProfile?.id ?? "")
.then((res) {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
familyBaseInfoRes = res;
notifyListeners();
});
getRoomTaskClaimableCount();
getLudoGameInfo();
}
///更新房间火箭信息
void updateRoomRocketStatus(ATRoomRocketStatusRes res) {
roomRocketStatus = res;
notifyListeners();
}
///获取在线用户
Future getOnlineUsers() async {
final int roomSessionId = _roomSessionId;
final String roomId = currenRoom?.roomProfile?.roomProfile?.id ?? "";
if (roomId.isEmpty) {
return;
}
final users = await ChatRoomRepository().roomOnlineUsers(roomId);
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
onlineUsers = users;
managerUsers.clear();
for (var user in onlineUsers) {
if (user.roles == ATRoomRolesType.ADMIN.name) {
managerUsers.add(user);
}
}
notifyListeners();
}
Future getMicList() async {
if (currenRoom == null || _isRefreshingMicList) {
return;
}
final int roomSessionId = _roomSessionId;
final String roomId = currenRoom!.roomProfile?.roomProfile?.id ?? "";
if (roomId.isEmpty) {
return;
}
_isRefreshingMicList = true;
bool isOnMic = false;
try {
final roomWheatList = await ChatRoomRepository().micList(roomId);
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
roomWheatMap.clear();
for (final roomWheat in _normalizeMicSnapshot(roomWheatList)) {
roomWheatMap[roomWheat.micIndex!] = roomWheat;
if (roomWheat.user != null &&
roomWheat.user!.id ==
AccountStorage().getCurrentUser()?.userProfile?.id) {
isOnMic = true;
}
}
notifyListeners();
await syncLocalPublishStateFromMicSnapshot();
await _applyRemoteAudioPolicy();
ATHeartbeatUtils.scheduleHeartbeat(
ATHeartbeatStatus.VOICE_LIVE.name,
isOnMic,
roomId: roomId,
);
Future.delayed(Duration(milliseconds: 1500), () {
if (_isRoomSessionActive(roomSessionId, roomId)) {
getOnlineUsers();
}
});
} finally {
_isRefreshingMicList = false;
}
}
void getRoomTaskClaimableCount() {
ChatRoomRepository()
.roomTaskClaimableCount()
.then((res) {
roomTaskClaimableCount = res.claimableCount ?? 0;
notifyListeners();
})
.catchError((e) {});
}
Future<List<ATRoomRedPacketListRes>> loadRoomRedPacketList(
int current,
) async {
var result = await ChatRoomRepository().roomRedPacketList(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
current,
);
if (current == 1) {
redPacketList = result;
notifyListeners();
}
return result;
}
Future<void> extRoom(bool isLogout, {bool navigateHome = true}) async {
if (_isExitingRoom) {
return _exitRoomFuture ?? Future.value();
}
_nextRoomSessionId();
_isExitingRoom = true;
final JoinRoomRes? leavingRoom = currenRoom;
_exitRoomFuture = _extRoomInternal(
leavingRoom: leavingRoom,
isLogout: isLogout,
navigateHome: navigateHome,
);
try {
await _exitRoomFuture;
} finally {
_isExitingRoom = false;
_exitRoomFuture = null;
}
}
Future<void> _extRoomInternal({
required JoinRoomRes? leavingRoom,
required bool isLogout,
required bool navigateHome,
}) async {
try {
_stopRoomStateResyncTimer();
_pendingMicResyncTimer?.cancel();
_pendingMicResyncTimer = null;
rtmProvider?.msgAllListener = null;
rtmProvider?.msgChatListener = null;
rtmProvider?.msgGiftListener = null;
ATLoadingManager.exhibitOperation(context: context);
ATGiftVapSvgaManager().dispose();
ATHeartbeatUtils.scheduleHeartbeat(ATHeartbeatStatus.ONLINE.name, false);
ATHeartbeatUtils.cancelAnchorTimer();
rtmProvider?.cleanRoomData();
playingLudoGame = null;
await _disposeRtcEngine();
if (leavingRoom != null) {
await rtmProvider?.quitGroup(
leavingRoom.roomProfile?.roomProfile?.roomAccount ?? "",
);
await AccountRepository().quitRoom(
leavingRoom.roomProfile?.roomProfile?.id ?? "",
);
}
if (currenRoom == null ||
currenRoom?.roomProfile?.roomProfile?.id ==
leavingRoom?.roomProfile?.roomProfile?.id) {
_clearData();
}
ATLoadingManager.veilRoutine();
if (!isLogout && navigateHome) {
ATNavigatorUtils.popUntil(context!, ModalRoute.withName(ATRoutes.home));
}
} catch (e) {
print('rtc退出房间出错: $e');
_clearData();
ATLoadingManager.veilRoutine();
if (!isLogout && navigateHome) {
ATNavigatorUtils.popUntil(context!, ModalRoute.withName(ATRoutes.home));
}
}
}
///清空列表数据
void _clearData() {
_stopRoomStateResyncTimer();
_pendingMicResyncTimer?.cancel();
_pendingMicResyncTimer = null;
_remoteRtcUidsInChannel.clear();
_lastMicChangeTimeId = null;
roomRocketStatus = null;
familyBaseInfoRes = null;
rtmProvider
?.onNewMessageListenerGroupMap["${currenRoom?.roomProfile?.roomProfile?.roomAccount}"] =
null;
roomWheatMap.clear();
onlineUsers.clear();
needUpDataUserInfo = false;
ATRoomUtils.roomUsersMap.clear();
MsgItem.clearRoomUserCaches();
roomIsMute = false;
playingLudoGame = null;
isMinLudoGame = false;
rtmProvider?.roomAllMsgList.clear();
rtmProvider?.roomChatMsgList.clear();
redPacketList.clear();
currenRoom = null;
isMic = true;
isMusicPlaying = false;
engine = null;
Provider.of<AudioManager>(context!, listen: false).reset();
ATGiftVapSvgaManager().clearTasks();
ATRoomUtils.closeAllDialogs();
ATForegroundServiceHelper().stopService();
ATGlobalConfig.isEntryVehicleAnimation = true;
ATGlobalConfig.isGiftSpecialEffects = true;
ATGlobalConfig.isFloatingAnimationInGlobal = true;
ATGlobalConfig.isLuckGiftSpecialEffects = true;
}
void muteAllRemote() {
roomIsMute = !roomIsMute;
engine?.muteAllRemoteAudioStreams(roomIsMute);
_applyRemoteAudioPolicy();
notifyListeners();
}
///点击的位置
void clickSite(num index, {ChatVibeUserProfile? clickUser}) {
if (index == -1) {
if (clickUser != null) {
if (clickUser.id ==
AccountStorage().getCurrentUser()?.userProfile?.id) {
///是自己,直接打开资料卡
showBottomInBottomDialog(
context!,
ATRoomUserInfoCard(userId: clickUser.id),
);
} else {
showBottomInBottomDialog(
context!,
EmptyMaiSelect(index: index, clickUser: clickUser),
);
}
}
} else {
ChatVibeUserProfile? roomWheatUser = roomWheatMap[index]?.user;
if (roomWheatUser != null &&
roomWheatUser.id !=
AccountStorage().getCurrentUser()?.userProfile?.id &&
!isFz() &&
!isGL()) {
showBottomInBottomDialog(
context!,
ATRoomUserInfoCard(userId: roomWheatUser.id),
);
return;
}
showBottomInBottomDialog(
context!,
EmptyMaiSelect(index: index, clickUser: roomWheatUser),
);
// if (roomWheatUser != null) {
// ///麦上有人
// if (roomWheatUser.id ==
// AccountStorage().getCurrentUser()?.ChatVibeUserProfile?.id) {
// ///是自己
// showBottomInBottomDialog(
// context!,
// EmptyMaiSelect(index: index, clickUser: roomWheatUser),
// );
// } else {
// showBottomInBottomDialog(
// context!,
// RoomUserInfoCard(userId: roomWheatUser.id),
// );
// }
// } else {
// showBottomInBottomDialog(
// context!,
// EmptyMaiSelect(index: index, clickUser: roomWheatUser),
// );
// }
}
}
addSoundVoiceChangeListener(OnSoundVoiceChange onSoundVoiceChange) {
_onSoundVoiceChangeList.add(onSoundVoiceChange);
print('添加监听:${_onSoundVoiceChangeList.length}');
}
removeSoundVoiceChangeListener(OnSoundVoiceChange onSoundVoiceChange) {
_onSoundVoiceChangeList.remove(onSoundVoiceChange);
print('删除监听:${_onSoundVoiceChangeList.length}');
}
void shangMai(num index, {String? eventType, String? inviterId}) async {
var myUser = AccountStorage().getCurrentUser()?.userProfile;
if (AccountStorage().getVIP()?.name == ATVIPType.KING.name) {
///vip5无视所有规则
} else {
if (currenRoom?.roomProfile?.roomSetting?.touristMike ?? false) {
} else {
if (isTourists()) {
ATTts.show(
ATAppLocalizations.of(context!)!.touristsAreNotAllowedToGoOnTheMic,
);
return;
}
}
}
try {
var micGoUpRes = await ChatRoomRepository().micGoUp(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
index,
eventType: eventType,
inviterId: inviterId,
);
/// 设置成主播角色
engine?.renewToken(micGoUpRes.roomToken ?? "");
if (!micGoUpRes.micMute!) {
if (!isMic) {
engine?.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
adjustRecordingSignalVolume(100);
await engine?.muteLocalAudioStream(false);
}
} else {
engine?.setClientRole(role: ClientRoleType.clientRoleAudience);
await engine?.muteLocalAudioStream(true);
}
ATHeartbeatUtils.scheduleAnchorHeartbeat(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
);
final us = roomWheatMap[index];
if (us != null) {
roomWheatMap[index] = us.copyWith(
user: ChatVibeUserProfile(
id: myUser?.id,
account: myUser?.account,
userAvatar: myUser?.userAvatar,
userNickname: myUser?.userNickname,
userSex: myUser?.userSex,
),
);
}
if ((roomWheatMap[index]?.micMute ?? false)) {
///房主上麦自动解禁麦位
if (isFz()) {
jieJinMai(index);
}
}
await syncLocalPublishStateFromMicSnapshot();
await _applyRemoteAudioPolicy();
notifyListeners();
} catch (ex) {
ATTts.show('Failed to put on the microphone, $ex');
}
}
Future<void> xiaMai(num index) async {
try {
await ChatRoomRepository().micGoDown(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
index,
);
} finally {
//自己
if (roomWheatMap[index]?.user?.id ==
UserManager().getCurrentUser()?.userProfile?.id) {
isMic = true;
}
ATHeartbeatUtils.cancelAnchorTimer();
/// 设置成主持人角色
await engine?.renewToken("");
roomWheatMap[index]?.setUser = null;
await syncLocalPublishStateFromMicSnapshot();
await _applyRemoteAudioPolicy();
notifyListeners();
}
}
///踢人下麦
Future<void> killXiaMai(String userId) async {
try {
for (final entry in roomWheatMap.entries.toList()) {
final k = entry.key;
final v = entry.value;
if (v.user?.id == userId) {
///是否可以踢VIP有防踢
final canKill = await ChatRoomRepository().kickOffMicrophone(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
userId,
);
if (canKill) {
await ChatRoomRepository().micKill(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
k,
);
Provider.of<RtmProvider>(context!, listen: false).sendMsg(
Msg(
groupId: currenRoom?.roomProfile?.roomProfile?.roomAccount,
msg: userId,
type: ATRoomMsgType.killXiaMai,
),
addLocal: false,
);
roomWheatMap[k]?.setUser = null;
if (userId == AccountStorage().getCurrentUser()?.userProfile?.id) {
isMic = true;
}
await syncLocalPublishStateFromMicSnapshot();
await _applyRemoteAudioPolicy();
notifyListeners();
} else {
ATTts.show("cant kill the user");
}
}
}
} catch (e) {
ATTts.show("kill the user fail");
print('踢人下麦失败');
}
}
///自己是否在麦上
bool isOnMai() {
return roomWheatMap.values
.map((userWheat) => userWheat.user?.id)
.toList()
.contains(AccountStorage().getCurrentUser()?.userProfile?.id);
}
///自己是否在指定的麦上
bool isOnMaiInIndex(num index) {
return roomWheatMap[index]?.user?.id ==
AccountStorage().getCurrentUser()?.userProfile?.id;
}
///点击的用户在哪个麦上
num userOnMaiInIndex(String userId) {
num index = -1;
roomWheatMap.forEach((k, value) {
if (value.user?.id == userId) {
index = k;
}
});
return index;
}
///座位上的用户是否开麦
bool userOnMaiInIndexOfMute(String userId) {
bool micMute = false;
roomWheatMap.forEach((k, value) {
if (value.user?.id == userId) {
value.micMute;
}
});
return micMute;
}
///是否是房主
bool isFz() {
return currenRoom?.entrants?.roles == ATRoomRolesType.HOMEOWNER.name;
}
///是否是管理
bool isGL() {
return currenRoom?.entrants?.roles == ATRoomRolesType.ADMIN.name;
}
///是否是会员
bool isHY() {
return currenRoom?.entrants?.roles == ATRoomRolesType.MEMBER.name;
}
///是否是游客
bool isTourists() {
return currenRoom?.entrants?.roles == ATRoomRolesType.TOURIST.name;
}
///麦位变动
Future<void> micChange(List<MicRes>? mics, {String? timeId}) async {
if (mics == null || mics.isEmpty) {
return;
}
if (currenRoom == null || _isExitingRoom) {
return;
}
if (!_shouldAcceptMicChange(timeId)) {
_scheduleMicStateResync();
return;
}
roomWheatMap.clear();
for (final mic in _normalizeMicSnapshot(mics)) {
roomWheatMap[mic.micIndex!] = mic;
}
notifyListeners();
await syncLocalPublishStateFromMicSnapshot();
await _applyRemoteAudioPolicy();
_scheduleMicStateResync();
}
///找一个空麦位 -1表示没有空位
num findWheat() {
for (var entry in roomWheatMap.entries) {
if (entry.value.user == null && !entry.value.micLock!) {
return entry.key;
}
}
return -1;
}
void loadRoomInfo(String roomId) {
final int roomSessionId = _roomSessionId;
ChatRoomRepository().specific(roomId).then((value) {
if (!_isRoomSessionActive(roomSessionId, roomId)) {
return;
}
currenRoom = currenRoom?.copyWith(
roomProfile: currenRoom?.roomProfile?.copyWith(
roomCounter: value.counter,
roomSetting: value.setting,
roomProfile: currenRoom?.roomProfile?.roomProfile?.copyWith(
roomCover: value.roomCover,
roomName: value.roomName,
roomDesc: value.roomDesc,
),
),
);
///如果是游客禁止上麦,已经在麦上的游客需要下麦
bool touristMike =
currenRoom?.roomProfile?.roomSetting?.touristMike ?? false;
if (!touristMike && isTourists()) {
num index = userOnMaiInIndex(
AccountStorage().getCurrentUser()?.userProfile?.id ?? "",
);
if (index > -1) {
xiaMai(index);
}
}
notifyListeners();
});
}
///解锁麦位
void jieFeng(num index) async {
await ChatRoomRepository().micLock(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
index,
false,
);
}
///锁麦
void fengMai(num index) async {
await ChatRoomRepository().micLock(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
index,
true,
);
}
///静音麦克风
void jinMai(num index) async {
await ChatRoomRepository().micMute(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
index,
true,
);
if (isOnMaiInIndex(index)) {
Provider.of<RtcProvider>(
context!,
listen: false,
).engine?.setClientRole(role: ClientRoleType.clientRoleAudience);
}
var mic = roomWheatMap[index];
if (mic != null) {
roomWheatMap[index] = mic.copyWith(micMute: true);
notifyListeners();
}
}
///解除静音麦克风
void jieJinMai(num index) async {
await ChatRoomRepository().micMute(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
index,
false,
);
if (isOnMaiInIndex(index)) {
if (!Provider.of<RtcProvider>(context!, listen: false).isMic) {
if (roomWheatMap[index]?.user != null) {
adjustRecordingSignalVolume(100);
Provider.of<RtcProvider>(
context!,
listen: false,
).engine?.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
}
}
}
var mic = roomWheatMap[index];
if (mic != null) {
roomWheatMap[index] = mic.copyWith(micMute: false);
notifyListeners();
}
}
void addOnlineUser(String groupId, ChatVibeUserProfile user) {
if (groupId != currenRoom?.roomProfile?.roomProfile?.roomAccount) {
return;
}
bool isExtOnlineList = false;
for (var us in onlineUsers) {
if (us.id == user.id) {
isExtOnlineList = true;
break;
}
}
if (!isExtOnlineList) {
Provider.of<RtcProvider>(context!, listen: false).onlineUsers.add(user);
notifyListeners();
}
}
void removOnlineUser(String groupId, String userId) {
if (groupId != currenRoom?.roomProfile?.roomProfile?.roomAccount) {
return;
}
ChatVibeUserProfile? isExtOnlineUser;
for (var us in onlineUsers) {
if (us.id == userId) {
isExtOnlineUser = us;
break;
}
}
if (isExtOnlineUser != null) {
Provider.of<RtcProvider>(
context!,
listen: false,
).onlineUsers.remove(isExtOnlineUser);
notifyListeners();
}
}
void starPlayEmoji(Msg msg) {
if (msg.number! > -1) {
var mic = roomWheatMap[msg.number];
if (mic != null && mic.user != null) {
roomWheatMap[msg.number!] = mic.copyWith(
emojiPath: msg.msg,
type: msg.type,
number: msg.msg,
);
notifyListeners();
}
}
}
///更新房间背景
void updateRoomBG(ATRoomThemeListRes res) {
var roomTheme = RoomTheme(
expireTime: res.expireTime,
id: res.id,
themeStatus: res.themeStatus,
themeBack: res.themeBack,
);
currenRoom?.roomProps?.setRoomTheme(roomTheme);
notifyListeners();
}
void updateRoomSetting(RoomSetting roomSetting) {
currenRoom?.roomProfile?.setRoomSetting(roomSetting);
notifyListeners();
}
Map<num, GlobalKey<State<StatefulWidget>>> seatGlobalKeyMap = {};
void bindTargetKey(num index, GlobalKey<State<StatefulWidget>> targetKey) {
seatGlobalKeyMap[index] = targetKey;
}
GlobalKey<State<StatefulWidget>>? getSeatGlobalKeyByIndex(String userId) {
///需要有人的座位
num index = userOnMaiInIndex(userId);
if (index > -1) {
return seatGlobalKeyMap[index];
}
}
///播放音乐
void playMusic(String localPath, int cycle) {
if (localPath.isEmpty) {
return;
}
engine?.startAudioMixing(
filePath: localPath,
loopback: false,
cycle: cycle,
);
}
///停止播放音乐
void stopMusic() {
Provider.of<AudioManager>(context!, listen: false).reset();
engine?.stopAudioMixing();
}
///暂停播放音乐
void pauseMusic() {
engine?.pauseAudioMixing();
}
///恢复播放音乐
void resumeMusic() {
engine?.resumeAudioMixing();
}
void adjustRecordingSignalVolume(int volume) {
engine?.adjustRecordingSignalVolume(volume);
}
///打开红包列表页面
void openRedEnvelope(String redPackId) {
// if (redPackId.isEmpty) {
// return;
// }
SmartDialog.dismiss(tag: "showRoomRedenvelopeList");
SmartDialog.show(
tag: "showRoomRedenvelopeList",
alignment: Alignment.center,
animationType: SmartAnimationType.fade,
builder: (_) {
return RoomRedenvelopeListPage();
},
);
}
void roomMannyGameClose() {
playingLudoGame = null;
notifyListeners();
}
void gameLudoCreate(ATGetListGameConfigRes item) {
if (playingLudoGame == null) {
ChatRoomRepository()
.gameLudoCreate(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
0,
"1",
currenRoom?.roomProfile?.roomProfile?.userId ?? "",
item.id ?? "",
)
.then((res) {
playingLudoGame = res;
Provider.of<RtmProvider>(context!, listen: false).sendMsg(
Msg(
groupId:
currenRoom?.roomProfile?.roomProfile?.roomAccount ?? "",
msg: "${playingLudoGame?.gameInfo?.id}",
type: ATRoomMsgType.roomGameCreate,
),
addLocal: false,
);
notifyListeners();
});
}
}
Future gameLudoDisband() async {
if (playingLudoGame != null) {
try {
ATLoadingManager.exhibitOperation();
await ChatRoomRepository().gameLudoDisband(
currenRoom?.roomProfile?.roomProfile?.id ?? "",
);
ATLoadingManager.veilRoutine();
playingLudoGame = null;
Provider.of<RtmProvider>(context!, listen: false).sendMsg(
Msg(
groupId: currenRoom?.roomProfile?.roomProfile?.roomAccount ?? "",
msg: "${playingLudoGame?.gameInfo?.id}",
type: ATRoomMsgType.roomGameClose,
),
addLocal: false,
);
notifyListeners();
} catch (_) {
ATLoadingManager.veilRoutine();
}
}
}
void getLudoGameInfo() {
ChatRoomRepository()
.gameLudo(currenRoom?.roomProfile?.roomProfile?.id ?? "")
.then((res) {
playingLudoGame = res;
notifyListeners();
});
}
void minOrShowLudoGame(bool ms) {
isMinLudoGame = ms;
notifyListeners();
}
@override
void dispose() {
_stopRoomStateResyncTimer();
_pendingMicResyncTimer?.cancel();
_remoteRtcUidsInChannel.clear();
super.dispose();
}
void openGameDialog() {
showBottomInBottomDialog(context!, RoomGameListPage());
}
void openGiftDialogToLuckyGift() {
SmartDialog.show(
tag: "showGiftControl",
alignment: Alignment.bottomCenter,
maskColor: Colors.transparent,
animationType: SmartAnimationType.fade,
clickMaskDismiss: true,
builder: (_) {
return GiftPage(initialIndex: 1);
},
);
}
void openGiftDialogToGift() {
SmartDialog.show(
tag: "showGiftControl",
alignment: Alignment.bottomCenter,
maskColor: Colors.transparent,
animationType: SmartAnimationType.fade,
clickMaskDismiss: true,
builder: (_) {
return GiftPage();
},
);
}
}