From 36ba0f3573d36102927299f1135b5902ffa81c47 Mon Sep 17 00:00:00 2001 From: roxy Date: Thu, 30 Apr 2026 10:11:30 +0800 Subject: [PATCH] 1.2.6 --- ios/Runner.xcodeproj/project.pbxproj | 12 +- .../popular/follow/sc_room_follow_page.dart | 3 +- .../popular/history/sc_room_history_page.dart | 3 +- .../home/popular/mine/sc_home_mine_page.dart | 25 +- .../popular/party/sc_home_party_page.dart | 37 +- lib/modules/room/edit/room_edit_page.dart | 18 + lib/modules/room/voice_room_page.dart | 25 + lib/modules/room/voice_room_route.dart | 19 +- lib/modules/search/sc_search_page.dart | 18 +- lib/modules/splash/splash_page.dart | 2 + lib/modules/user/me_page2.dart | 23 +- lib/services/audio/rtc_manager.dart | 449 ++++++++++++++++-- .../home/home_room_preload_manager.dart | 65 +++ .../widgets/room/exit_min_room_page.dart | 31 +- lib/ui_kit/widgets/room/room_menu_dialog.dart | 2 +- pubspec.yaml | 2 +- 16 files changed, 626 insertions(+), 108 deletions(-) create mode 100644 lib/services/home/home_room_preload_manager.dart diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 9195c54..bd9cabe 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -502,7 +502,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 7; + CURRENT_PROJECT_VERSION = 8; DEVELOPMENT_TEAM = S9X2AJ2US9; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -511,7 +511,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = com.org.yumiparty; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -693,7 +693,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 7; + CURRENT_PROJECT_VERSION = 8; DEVELOPMENT_TEAM = F33K8VUZ62; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -702,7 +702,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = com.org.yumiparty; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -722,7 +722,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/RunnerRelease.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 7; + CURRENT_PROJECT_VERSION = 8; DEVELOPMENT_TEAM = F33K8VUZ62; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -731,7 +731,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; PRODUCT_BUNDLE_IDENTIFIER = com.org.yumiparty; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/lib/modules/home/popular/follow/sc_room_follow_page.dart b/lib/modules/home/popular/follow/sc_room_follow_page.dart index f5426d8..5962815 100644 --- a/lib/modules/home/popular/follow/sc_room_follow_page.dart +++ b/lib/modules/home/popular/follow/sc_room_follow_page.dart @@ -272,8 +272,7 @@ class _RoomFollowPageState Provider.of(context, listen: false).joinVoiceRoomSession( context, roomRes.roomProfile?.id ?? "", - previewSeatCount: - roomRes.roomProfile?.extValues?.roomSetting?.mikeSize?.toInt(), + previewData: RoomEntryPreviewData.fromFollowRoom(roomRes), ); }, ); diff --git a/lib/modules/home/popular/history/sc_room_history_page.dart b/lib/modules/home/popular/history/sc_room_history_page.dart index 1fd5414..9842276 100644 --- a/lib/modules/home/popular/history/sc_room_history_page.dart +++ b/lib/modules/home/popular/history/sc_room_history_page.dart @@ -272,8 +272,7 @@ class _SCRoomHistoryPageState Provider.of(context, listen: false).joinVoiceRoomSession( context, roomRes.roomProfile?.id ?? "", - previewSeatCount: - roomRes.roomProfile?.extValues?.roomSetting?.mikeSize?.toInt(), + previewData: RoomEntryPreviewData.fromFollowRoom(roomRes), ); }, ); diff --git a/lib/modules/home/popular/mine/sc_home_mine_page.dart b/lib/modules/home/popular/mine/sc_home_mine_page.dart index 5bd651a..634c705 100644 --- a/lib/modules/home/popular/mine/sc_home_mine_page.dart +++ b/lib/modules/home/popular/mine/sc_home_mine_page.dart @@ -238,23 +238,26 @@ class _HomeMinePageState extends State ], ), onTap: () { - String roomId = - Provider.of( - context, - listen: false, - ).myRoom?.id ?? - ""; + final roomManager = Provider.of( + context, + listen: false, + ); + final myRoom = roomManager.myRoom; + final roomId = myRoom?.id ?? ""; Provider.of( context, listen: false, ).joinVoiceRoomSession( context, roomId, - previewSeatCount: - Provider.of( - context, - listen: false, - ).myRoom?.setting?.mikeSize?.toInt(), + previewData: + myRoom == null + ? null + : RoomEntryPreviewData.fromMyRoom( + myRoom, + ownerProfile: + AccountStorage().getCurrentUser()?.userProfile, + ), ); }, ) diff --git a/lib/modules/home/popular/party/sc_home_party_page.dart b/lib/modules/home/popular/party/sc_home_party_page.dart index 641a6b6..9a69562 100644 --- a/lib/modules/home/popular/party/sc_home_party_page.dart +++ b/lib/modules/home/popular/party/sc_home_party_page.dart @@ -15,6 +15,7 @@ import '../../../../shared/business_logic/models/res/follow_room_res.dart'; import '../../../../shared/business_logic/models/res/room_res.dart'; import '../../../../services/audio/rtc_manager.dart'; import '../../../../services/general/sc_app_general_manager.dart'; +import '../../../../services/home/home_room_preload_manager.dart'; import '../../../../ui_kit/components/sc_compontent.dart'; import '../../../../ui_kit/components/text/sc_text.dart'; import '../../../../ui_kit/widgets/room/room_live_audio_indicator.dart'; @@ -122,7 +123,7 @@ class _HomePartyPageState extends State enablePullUp: false, controller: _refreshController, onRefresh: () { - loadData(); + loadData(forceRefresh: true); }, onLoading: () {}, child: SingleChildScrollView( @@ -968,20 +969,20 @@ class _HomePartyPageState extends State ); } - loadData() { - final generalManager = Provider.of( - context, - listen: false, - ); - setState(() { - isLoading = true; - _isBannerLoading = - generalManager.exploreBanners.isEmpty && - generalManager.homeBanners.isEmpty; - _isLeaderboardLoading = generalManager.appLeaderResult == null; - }); - SCChatRoomRepository() - .discovery(allRegion: true) + loadData({bool forceRefresh = false}) { + final generalManager = Provider.of( + context, + listen: false, + ); + setState(() { + isLoading = true; + _isBannerLoading = + generalManager.exploreBanners.isEmpty && + generalManager.homeBanners.isEmpty; + _isLeaderboardLoading = generalManager.appLeaderResult == null; + }); + SCHomeRoomPreloadManager.instance + .loadPartyRooms(forceRefresh: forceRefresh) .then((values) { rooms = _mergeLatestRoomsWithCurrentCounters(values); isLoading = false; @@ -1020,7 +1021,9 @@ class _HomePartyPageState extends State _buildItem(SocialChatRoomRes res, int index) { final rankBorderAsset = - index < _topRankBorderAssets.length ? _topRankBorderAssets[index] : null; + index < _topRankBorderAssets.length + ? _topRankBorderAssets[index] + : null; final rankBorderOverflow = 12.w; final rankInfoHorizontalInset = rankBorderAsset != null ? 10.w : 0.w; final rankInfoBottomInset = rankBorderAsset != null ? 9.w : 0.w; @@ -1177,7 +1180,7 @@ class _HomePartyPageState extends State Provider.of(context, listen: false).joinVoiceRoomSession( context, res.id ?? "", - previewSeatCount: res.extValues?.roomSetting?.mikeSize?.toInt(), + previewData: RoomEntryPreviewData.fromSocialChatRoom(res), ); }, ); diff --git a/lib/modules/room/edit/room_edit_page.dart b/lib/modules/room/edit/room_edit_page.dart index 702ec45..111d2fe 100644 --- a/lib/modules/room/edit/room_edit_page.dart +++ b/lib/modules/room/edit/room_edit_page.dart @@ -591,6 +591,24 @@ class _RoomEditPageState extends State { rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id ?? "", clearRoomData: true, + previewData: RoomEntryPreviewData( + roomId: + mergedRoomInfo.id ?? + rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id, + roomAccount: + rtcProvider?.currenRoom?.roomProfile?.roomProfile?.roomAccount, + userId: rtcProvider?.currenRoom?.roomProfile?.roomProfile?.userId, + roomCover: mergedRoomInfo.roomCover, + roomName: mergedRoomInfo.roomName ?? submittedRoomName, + roomDesc: mergedRoomInfo.roomDesc ?? submittedRoomDesc, + roomSetting: rtcProvider?.currenRoom?.roomProfile?.roomSetting, + ownerProfile: rtcProvider?.currenRoom?.roomProfile?.userProfile, + roomAdminCount: + rtcProvider?.currenRoom?.roomProfile?.roomCounter?.adminCount, + roomMemberCount: + rtcProvider?.currenRoom?.roomProfile?.roomCounter?.memberCount, + entrantsRole: rtcProvider?.currenRoom?.entrants?.roles, + ), ); } else { SCLoadingManager.hide(); diff --git a/lib/modules/room/voice_room_page.dart b/lib/modules/room/voice_room_page.dart index 9feb64e..246efe2 100644 --- a/lib/modules/room/voice_room_page.dart +++ b/lib/modules/room/voice_room_page.dart @@ -65,6 +65,8 @@ class _VoiceRoomPageState extends State final Map _luckyGiftComboSessions = {}; int _shownRoomStartupFailureToken = 0; + RtcProvider? _rtcProvider; + bool _roomProviderRebuildScheduled = false; @override void initState() { @@ -90,11 +92,20 @@ class _VoiceRoomPageState extends State @override void didChangeDependencies() { super.didChangeDependencies(); + final rtcProvider = context.read(); + if (!identical(_rtcProvider, rtcProvider)) { + _rtcProvider?.removeListener(_handleRoomProviderChanged); + _rtcProvider = rtcProvider; + rtcProvider.addListener(_handleRoomProviderChanged); + } _ensureRoomVisualEffectsEnabled(); } @override void dispose() { + _rtcProvider?.removeListener(_handleRoomProviderChanged); + _rtcProvider = null; + _roomProviderRebuildScheduled = false; _suspendRoomVisualEffects(); _tabController.removeListener(_handleTabChange); _tabController.dispose(); // 释放资源 @@ -109,6 +120,20 @@ class _VoiceRoomPageState extends State setState(() {}); } + void _handleRoomProviderChanged() { + if (!mounted || _roomProviderRebuildScheduled) { + return; + } + _roomProviderRebuildScheduled = true; + WidgetsBinding.instance.addPostFrameCallback((_) { + _roomProviderRebuildScheduled = false; + if (!mounted) { + return; + } + setState(() {}); + }); + } + void _enableRoomVisualEffects() { Provider.of( context, diff --git a/lib/modules/room/voice_room_route.dart b/lib/modules/room/voice_room_route.dart index 678083d..e4b9815 100644 --- a/lib/modules/room/voice_room_route.dart +++ b/lib/modules/room/voice_room_route.dart @@ -20,6 +20,9 @@ class VoiceRoomRoute implements SCIRouterProvider { static String roomBackgroundPreview = '/room/background/preview'; static String roomBackgroundUpload = '/room/background/upload'; static String roomMusic = '/room/music'; + static int _voiceRoomRouteDepth = 0; + + static bool get isVoiceRoomOpen => _voiceRoomRouteDepth > 0; static Route _buildRoute(Widget page, {RouteSettings? settings}) { if (Platform.isIOS) { @@ -54,14 +57,26 @@ class VoiceRoomRoute implements SCIRouterProvider { bool rootNavigator = false, }) { final navigator = Navigator.of(context, rootNavigator: rootNavigator); + if (!replace && isVoiceRoomOpen) { + debugPrint('[RoomRoute] skip duplicate voice room route'); + return Future.value(); + } final route = _buildRoute( const VoiceRoomPage(), settings: RouteSettings(name: voiceRoom), ); + _voiceRoomRouteDepth = replace ? 1 : _voiceRoomRouteDepth + 1; + Future routeFuture; if (replace) { - return navigator.pushReplacement(route); + routeFuture = navigator.pushReplacement(route); + } else { + routeFuture = navigator.push(route); } - return navigator.push(route); + return routeFuture.whenComplete(() { + if (_voiceRoomRouteDepth > 0) { + _voiceRoomRouteDepth -= 1; + } + }); } static Future openRoomEdit( diff --git a/lib/modules/search/sc_search_page.dart b/lib/modules/search/sc_search_page.dart index 98db4a1..8cbb05a 100644 --- a/lib/modules/search/sc_search_page.dart +++ b/lib/modules/search/sc_search_page.dart @@ -434,13 +434,11 @@ class _SearchRoomListState extends State { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () async { - if (context != null) { - Provider.of(context, listen: false).joinVoiceRoomSession( - context, - e.id ?? "", - previewSeatCount: e.extValues?.roomSetting?.mikeSize?.toInt(), - ); - } + Provider.of(context, listen: false).joinVoiceRoomSession( + context, + e.id ?? "", + previewData: RoomEntryPreviewData.fromSocialChatRoom(e), + ); }, child: Stack( alignment: Alignment.bottomCenter, @@ -544,9 +542,9 @@ class _SearchRoomListState extends State { width: 20.w, height: 20.w, ), - (e.extValues?.roomSetting?.password?.isEmpty ?? false) - ? SizedBox(width: 3.w) - : Container(height: 10.w), + (e.extValues?.roomSetting?.password?.isEmpty ?? false) + ? SizedBox(width: 3.w) + : Container(height: 10.w), (e.extValues?.roomSetting?.password?.isEmpty ?? false) ? text( e.displayMemberCount, diff --git a/lib/modules/splash/splash_page.dart b/lib/modules/splash/splash_page.dart index 5f4c7e0..060d74f 100644 --- a/lib/modules/splash/splash_page.dart +++ b/lib/modules/splash/splash_page.dart @@ -14,6 +14,7 @@ import 'package:yumi/shared/data_sources/sources/local/user_manager.dart'; import 'package:yumi/shared/business_logic/models/res/login_res.dart'; import 'package:yumi/app/routes/sc_routes.dart'; import 'package:yumi/app/routes/sc_fluro_navigator.dart'; +import 'package:yumi/services/home/home_room_preload_manager.dart'; import 'package:yumi/shared/data_sources/sources/local/file_cache_manager.dart'; import 'package:yumi/ui_kit/components/sc_compontent.dart'; @@ -95,6 +96,7 @@ class _SplashPageState extends State { _selectedVariant = _pickSplashVariant(); WidgetsBinding.instance.addPostFrameCallback((_) { unawaited(FileCacheManager.getInstance().getFilePath()); + SCHomeRoomPreloadManager.instance.preloadInitialHomeRooms(); unawaited(WeeklyStarSplashCache.refreshCacheInBackground()); unawaited(LastWeeklyCPSplashCache.refreshCacheInBackground()); }); diff --git a/lib/modules/user/me_page2.dart b/lib/modules/user/me_page2.dart index 6c77808..47b605a 100644 --- a/lib/modules/user/me_page2.dart +++ b/lib/modules/user/me_page2.dart @@ -7,7 +7,6 @@ import 'package:yumi/app_localizations.dart'; import 'package:yumi/modules/index/main_route.dart'; import 'package:yumi/modules/store/store_route.dart'; import 'package:yumi/modules/user/settings/settings_route.dart'; -import 'package:yumi/modules/user/task/task_route.dart'; import 'package:yumi/modules/user/vip/vip_route.dart'; import 'package:yumi/modules/wallet/wallet_route.dart'; import 'package:yumi/services/auth/user_profile_manager.dart'; @@ -114,6 +113,14 @@ class _MePage2State extends State { return repository.vipStatus(); } + void _refreshAfterVipReturn(SocialChatUserProfileManager profileManager) { + debugPrint('[VIP][MeEntry] refresh user data after vip page return'); + profileManager.fetchUserProfileData(loadGuardCount: false); + profileManager.balance(); + _loadCounter(); + _loadVipStatus(); + } + void _openInviteActivity() { final inviteActivityUrl = _appendToken(_inviteActivityUrl); if (inviteActivityUrl.isEmpty) return; @@ -287,12 +294,6 @@ class _MePage2State extends State { Widget _buildEntryRow() { return Row( children: [ - _buildEntryItem( - title: SCAppLocalizations.of(context)!.task, - iconPath: 'sc_images/index/sc_icon_task.png', - onTap: () => SCNavigatorUtils.push(context, TaskRoute.task), - ), - SizedBox(width: 10.w), _buildEntryItem( title: SCAppLocalizations.of(context)!.store, iconPath: 'sc_images/index/sc_icon_shop.png', @@ -304,12 +305,6 @@ class _MePage2State extends State { iconPath: 'sc_images/index/sc_icon_bag.png', onTap: () => SCNavigatorUtils.push(context, StoreRoute.bags), ), - SizedBox(width: 10.w), - _buildEntryItem( - title: SCAppLocalizations.of(context)!.level, - iconPath: 'sc_images/index/sc_icon_level.png', - onTap: () => SCNavigatorUtils.push(context, SCMainRoute.levelList), - ), ], ); } @@ -408,7 +403,7 @@ class _MePage2State extends State { onTap: () async { await SCNavigatorUtils.push(context, VipRoute.detail); if (mounted) { - _loadVipStatus(); + _refreshAfterVipReturn(profileManager); } }, child: Container( diff --git a/lib/services/audio/rtc_manager.dart b/lib/services/audio/rtc_manager.dart index 11db985..7221dba 100644 --- a/lib/services/audio/rtc_manager.dart +++ b/lib/services/audio/rtc_manager.dart @@ -27,6 +27,10 @@ import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart'; import 'package:yumi/shared/business_logic/models/res/join_room_res.dart'; import 'package:yumi/shared/business_logic/models/res/login_res.dart'; import 'package:yumi/shared/business_logic/models/res/mic_res.dart'; +import 'package:yumi/shared/business_logic/models/res/follow_room_res.dart' + as follow_room; +import 'package:yumi/shared/business_logic/models/res/my_room_res.dart' + as my_room; import 'package:yumi/shared/business_logic/models/res/room_res.dart'; import 'package:yumi/modules/room/voice_room_route.dart'; import 'package:yumi/ui_kit/widgets/room/empty_mai_select.dart'; @@ -76,8 +80,178 @@ class _RoomStartupAsyncResult { } } +class _AgoraJoinCanceled implements Exception { + const _AgoraJoinCanceled(this.reason); + + final String reason; + + @override + String toString() => reason; +} + enum _PendingRoomStartupSeatActionType { clickSeat, goUpMic } +class RoomEntryPreviewData { + const RoomEntryPreviewData({ + this.roomId, + this.roomAccount, + this.userId, + this.roomCover, + this.roomName, + this.roomDesc, + this.event, + this.sysOrigin, + this.countryCode, + this.countryName, + this.nationalFlag, + this.langCode, + this.del, + this.createTime, + this.updateTime, + this.activeTime, + this.roomSetting, + this.ownerProfile, + this.roomAdminCount, + this.roomMemberCount, + this.entrantsRole, + }); + + factory RoomEntryPreviewData.fromSocialChatRoom(SocialChatRoomRes room) { + return RoomEntryPreviewData( + roomId: room.id, + roomAccount: room.roomAccount, + userId: room.userId, + roomCover: room.roomCover, + roomName: room.roomName, + roomDesc: room.roomDesc, + event: room.event, + sysOrigin: room.sysOrigin, + countryCode: room.countryCode, + countryName: room.countryName, + nationalFlag: room.nationalFlag, + roomSetting: room.extValues?.roomSetting, + ownerProfile: room.userProfile, + roomAdminCount: room.roomCounter?.adminCount, + roomMemberCount: room.roomCounter?.memberCount, + ); + } + + factory RoomEntryPreviewData.fromFollowRoom(follow_room.FollowRoomRes room) { + final roomProfile = room.roomProfile; + return RoomEntryPreviewData( + roomId: roomProfile?.id ?? room.id, + roomAccount: roomProfile?.roomAccount, + userId: roomProfile?.userId, + roomCover: roomProfile?.roomCover, + roomName: roomProfile?.roomName, + roomDesc: roomProfile?.roomDesc, + event: roomProfile?.event, + sysOrigin: roomProfile?.sysOrigin, + countryCode: roomProfile?.countryCode, + countryName: roomProfile?.countryName, + nationalFlag: roomProfile?.nationalFlag, + roomSetting: roomProfile?.extValues?.roomSetting, + ownerProfile: roomProfile?.userProfile, + roomAdminCount: roomProfile?.roomCounter?.adminCount, + roomMemberCount: roomProfile?.roomCounter?.memberCount, + ); + } + + factory RoomEntryPreviewData.fromMyRoom( + my_room.MyRoomRes room, { + SocialChatUserProfile? ownerProfile, + }) { + return RoomEntryPreviewData( + roomId: room.id, + roomAccount: room.roomAccount, + userId: room.userId, + roomCover: room.roomCover, + roomName: room.roomName, + roomDesc: room.roomDesc, + event: room.event, + sysOrigin: room.sysOrigin, + countryCode: room.countryCode, + countryName: room.countryName, + nationalFlag: room.nationalFlag, + langCode: room.langCode, + del: room.del, + createTime: room.createTime, + updateTime: room.updateTime, + activeTime: room.activeTime, + roomSetting: room.setting, + ownerProfile: ownerProfile, + roomAdminCount: room.counter?.adminCount, + roomMemberCount: room.counter?.memberCount, + entrantsRole: SCRoomRolesType.HOMEOWNER.name, + ); + } + + final String? roomId; + final String? roomAccount; + final String? userId; + final String? roomCover; + final String? roomName; + final String? roomDesc; + final String? event; + final String? sysOrigin; + final String? countryCode; + final String? countryName; + final String? nationalFlag; + final String? langCode; + final bool? del; + final num? createTime; + final num? updateTime; + final num? activeTime; + final RoomSetting? roomSetting; + final SocialChatUserProfile? ownerProfile; + final num? roomAdminCount; + final num? roomMemberCount; + final String? entrantsRole; + + int? get seatCount => roomSetting?.mikeSize?.toInt(); + + JoinRoomRes toJoinRoomRes({String? fallbackRoomId}) { + final resolvedRoomId = + (roomId ?? "").trim().isNotEmpty ? roomId : fallbackRoomId; + return JoinRoomRes( + entrants: + (entrantsRole ?? "").trim().isNotEmpty + ? Entrants(roles: entrantsRole) + : null, + roomProfile: RoomProfile( + regionCode: countryCode, + roomCounter: + roomAdminCount != null || roomMemberCount != null + ? RoomCounter( + adminCount: roomAdminCount, + memberCount: roomMemberCount, + ) + : null, + roomProfile: RoomProfile2( + activeTime: activeTime, + countryCode: countryCode, + countryName: countryName, + createTime: createTime, + del: del, + event: event, + id: resolvedRoomId, + langCode: langCode, + nationalFlag: nationalFlag, + roomAccount: roomAccount, + roomCover: roomCover, + roomDesc: roomDesc, + roomName: roomName, + sysOrigin: sysOrigin, + updateTime: updateTime, + userId: userId, + ), + roomSetting: roomSetting, + userProfile: ownerProfile, + ), + ); + } +} + class _PendingRoomStartupSeatAction { const _PendingRoomStartupSeatAction.clickSeat({ required this.index, @@ -122,20 +296,24 @@ class RealTimeCommunicationManager extends ChangeNotifier { bool _isHandlingAgoraRoomFailure = false; bool _agoraJoined = false; bool _agoraRoleIsBroadcaster = false; + String? _agoraJoinedChannelId; bool _agoraAudioConfigured = false; RoomStartupStatus _roomStartupStatus = RoomStartupStatus.idle; RoomStartupFailureType _roomStartupFailureType = RoomStartupFailureType.none; int _roomStartupFailureToken = 0; int _roomEntryRequestSerial = 0; int? _previewRoomSeatCount; + bool _currentRoomIsEntryPreview = false; bool _isHandlingRoomStartupFailure = false; Timer? _micListPollingTimer; Timer? _onlineUsersPollingTimer; Timer? _joinAgoraTimeoutTimer; Timer? _agoraDisconnectedCleanupTimer; + Timer? _roomEntryEffectTimer; Completer? _joinAgoraCompleter; Future? _rtcEngineInitTask; Future? _rtcEnginePrewarmTask; + Future? _pendingRoomSwitchAgoraLeaveTask; String? _joiningChannelId; bool _isRefreshingMicList = false; bool _isRefreshingOnlineUsers = false; @@ -247,6 +425,10 @@ class RealTimeCommunicationManager extends ChangeNotifier { if (_roomVisualEffectsEnabled == enabled) { return; } + if (!enabled) { + _roomEntryEffectTimer?.cancel(); + _roomEntryEffectTimer = null; + } _roomVisualEffectsEnabled = enabled; notifyListeners(); } @@ -273,6 +455,9 @@ class RealTimeCommunicationManager extends ChangeNotifier { } void _setRoomStartupFailed(RoomStartupFailureType failureType) { + if (_roomStartupStatus != RoomStartupStatus.loading) { + return; + } _stopRoomStatePolling(); _isHandlingRoomStartupFailure = false; _roomStartupFailureType = failureType; @@ -825,10 +1010,11 @@ class RealTimeCommunicationManager extends ChangeNotifier { } void _resetAgoraTracking({bool clearJoiningChannel = true}) { - _cancelAgoraJoinWaiter(); + _cancelAgoraJoinWaiter(const _AgoraJoinCanceled('Agora join canceled')); _cancelAgoraDisconnectedCleanup(); _agoraJoined = false; _agoraRoleIsBroadcaster = false; + _agoraJoinedChannelId = null; if (clearJoiningChannel) { _joiningChannelId = null; } @@ -1138,7 +1324,24 @@ class RealTimeCommunicationManager extends ChangeNotifier { }); } - Future _cleanupAgoraRoomState({bool clearMicSeats = false}) async { + Future _cleanupAgoraRoomState({ + bool clearMicSeats = false, + String? onlyIfJoinedChannelId, + }) async { + final expectedChannelId = (onlyIfJoinedChannelId ?? "").trim(); + if (expectedChannelId.isNotEmpty) { + final joinedChannelId = (_agoraJoinedChannelId ?? "").trim(); + final currentRoomId = + (currenRoom?.roomProfile?.roomProfile?.id ?? "").trim(); + if (joinedChannelId.isNotEmpty && joinedChannelId != expectedChannelId) { + return; + } + if (joinedChannelId.isEmpty && + currentRoomId.isNotEmpty && + currentRoomId != expectedChannelId) { + return; + } + } _resetAgoraTracking(); try { await engine?.leaveChannel(); @@ -1261,7 +1464,16 @@ class RealTimeCommunicationManager extends ChangeNotifier { return; } - _cancelAgoraJoinWaiter(); + final pendingRoomSwitchLeaveTask = _pendingRoomSwitchAgoraLeaveTask; + if (pendingRoomSwitchLeaveTask != null) { + try { + await pendingRoomSwitchLeaveTask; + } catch (error) { + debugPrint('[Agora] pending room switch leave failed: $error'); + } + } + + _cancelAgoraJoinWaiter(const _AgoraJoinCanceled('Agora join superseded')); _cancelAgoraDisconnectedCleanup(); _joiningChannelId = channelId; _agoraJoined = false; @@ -1303,6 +1515,13 @@ class RealTimeCommunicationManager extends ChangeNotifier { _syncSelfMicRuntimeState(); rtcEngine.muteAllRemoteAudioStreams(roomIsMute); } catch (e) { + if (e is _AgoraJoinCanceled) { + debugPrint('[Agora] join canceled: $e'); + if (throwOnError) { + rethrow; + } + return; + } await _handleAgoraJoinFailed(e, exitRoom: !throwOnError); if (throwOnError) { rethrow; @@ -1475,6 +1694,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { } _agoraJoined = true; _agoraRoleIsBroadcaster = false; + _agoraJoinedChannelId = joinedChannelId.trim(); _cancelAgoraDisconnectedCleanup(); _joinAgoraTimeoutTimer?.cancel(); _joinAgoraTimeoutTimer = null; @@ -1533,6 +1753,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { reason == ConnectionChangedReasonType.connectionChangedRejoinSuccess) { _agoraJoined = true; + _agoraJoinedChannelId = connection.channelId?.trim(); _cancelAgoraDisconnectedCleanup(); _resyncHeartbeatFromAgoraState(); return; @@ -1771,6 +1992,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { bool needOpenRedenvelope = false, String redPackId = "", int? previewSeatCount, + RoomEntryPreviewData? previewData, }) async { int nextTime = DateTime.now().millisecondsSinceEpoch; if (nextTime - startTime < 1000) { @@ -1787,6 +2009,16 @@ class RealTimeCommunicationManager extends ChangeNotifier { throw ArgumentError('Microphone permission is denied.'); } if (roomId == currenRoom?.roomProfile?.roomProfile?.id) { + if (_currentRoomIsEntryPreview || + _roomStartupStatus == RoomStartupStatus.loading) { + SCFloatIchart().remove(); + if (!context.mounted) { + return; + } + VoiceRoomRoute.openVoiceRoom(context); + return; + } + ///最小化进入房间,或者进入的是同一个房间 final loaded = await loadRoomInfo( currenRoom?.roomProfile?.roomProfile?.id ?? "", @@ -1811,7 +2043,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { } else { SCFloatIchart().remove(); if (currenRoom != null) { - await exitCurrentVoiceRoomSession(false, deferRemoteCleanup: false); + _switchAwayFromCurrentRoomForNewEntry(); } if (!context.mounted) { return; @@ -1823,7 +2055,11 @@ class RealTimeCommunicationManager extends ChangeNotifier { ); _setRoomStartupLoading(); setRoomVisualEffectsEnabled(true); - _setPreviewRoomSeatCount(previewSeatCount, notify: false); + _applyRoomEntryPreview( + roomId, + previewData: previewData, + previewSeatCount: previewSeatCount, + ); VoiceRoomRoute.openVoiceRoom(context); notifyListeners(); final entryRequestSerial = ++_roomEntryRequestSerial; @@ -1858,9 +2094,11 @@ class RealTimeCommunicationManager extends ChangeNotifier { return; } currenRoom = enteredRoom; + _currentRoomIsEntryPreview = false; _previewRoomSeatCount = null; notifyListeners(); await initializeRoomSession( + entryRequestSerial: entryRequestSerial, needOpenRedenvelope: needOpenRedenvelope, redPackId: redPackId, shouldOpenRoomPage: false, @@ -1879,6 +2117,17 @@ class RealTimeCommunicationManager extends ChangeNotifier { _roomStartupStatus == RoomStartupStatus.loading; } + bool _isCurrentRoomEntrySession(int entryRequestSerial, String roomId) { + return entryRequestSerial == _roomEntryRequestSerial && + roomId.isNotEmpty && + currenRoom?.roomProfile?.roomProfile?.id == roomId; + } + + bool _isActiveRoomStartup(int entryRequestSerial, String roomId) { + return _isActiveRoomEntryRequest(entryRequestSerial) && + _isCurrentRoomEntrySession(entryRequestSerial, roomId); + } + void _setPreviewRoomSeatCount(int? seatCount, {bool notify = true}) { final normalizedSeatCount = _normalizePreviewRoomSeatCount(seatCount); if (_previewRoomSeatCount == normalizedSeatCount) { @@ -1902,11 +2151,31 @@ class RealTimeCommunicationManager extends ChangeNotifier { } } + void _applyRoomEntryPreview( + String roomId, { + RoomEntryPreviewData? previewData, + int? previewSeatCount, + }) { + final resolvedPreviewSeatCount = previewData?.seatCount ?? previewSeatCount; + _setPreviewRoomSeatCount(resolvedPreviewSeatCount, notify: false); + if (previewData == null) { + return; + } + currenRoom = previewData.toJoinRoomRes(fallbackRoomId: roomId); + _currentRoomIsEntryPreview = true; + } + Future _cleanupStaleEnteredRoom(JoinRoomRes enteredRoom) async { final staleRoomId = enteredRoom.roomProfile?.roomProfile?.id ?? ""; if (staleRoomId.isEmpty) { return; } + if (_isCurrentRoomId(staleRoomId)) { + debugPrint( + '[RoomStartup] skip stale entry cleanup: room $staleRoomId is active again', + ); + return; + } await _retryExitNetworkRequest('quit stale entered room $staleRoomId', () { return SCAccountRepository().quitRoom(staleRoomId).then((didQuit) { if (!didQuit) { @@ -1918,12 +2187,17 @@ class RealTimeCommunicationManager extends ChangeNotifier { ///初始化房间相关 Future initializeRoomSession({ + required int entryRequestSerial, bool needOpenRedenvelope = false, String? redPackId, bool shouldOpenRoomPage = true, }) async { _disableMicListRefreshForCurrentSession = false; _disableOnlineUsersRefreshForCurrentSession = false; + final startupRoomId = currenRoom?.roomProfile?.roomProfile?.id ?? ""; + if (!_isActiveRoomStartup(entryRequestSerial, startupRoomId)) { + return; + } if ((currenRoom?.roomProfile?.roomProfile?.event == SCRoomInfoEventType.WAITING_CONFIRMED.name || currenRoom?.roomProfile?.roomProfile?.event == @@ -1938,26 +2212,39 @@ class RealTimeCommunicationManager extends ChangeNotifier { ); if (currenRoom?.roomProfile?.roomProfile?.id != AccountStorage().getCurrentUser()?.userProfile?.id) { - SCChatRoomRepository() - .isFollowRoom(currenRoom?.roomProfile?.roomProfile?.id ?? "") - .then((value) { - isFollowRoomRes = value; - notifyListeners(); - }); + final followRoomId = startupRoomId; + SCChatRoomRepository().isFollowRoom(followRoomId).then((value) { + if (!_isActiveRoomStartup(entryRequestSerial, followRoomId)) { + return; + } + isFollowRoomRes = value; + notifyListeners(); + }); } _setRoomStartupLoading(); setRoomVisualEffectsEnabled(true); if (shouldOpenRoomPage) { VoiceRoomRoute.openVoiceRoom(context!); } - unawaited(_bootstrapEnteredVoiceRoomSession()); + unawaited( + _bootstrapEnteredVoiceRoomSession( + entryRequestSerial: entryRequestSerial, + roomId: startupRoomId, + groupId: currenRoom?.roomProfile?.roomProfile?.roomAccount ?? "", + ), + ); } - Future _bootstrapEnteredVoiceRoomSession() async { + Future _bootstrapEnteredVoiceRoomSession({ + required int entryRequestSerial, + required String roomId, + required String groupId, + }) async { var failureType = RoomStartupFailureType.im; + if (!_isActiveRoomStartup(entryRequestSerial, roomId)) { + return; + } try { - final roomId = currenRoom?.roomProfile?.roomProfile?.id ?? ""; - final groupId = currenRoom?.roomProfile?.roomProfile?.roomAccount ?? ""; final joinGroupFuture = rtmProvider?.joinRoomGroup(groupId, ""); final rtcTokenFuture = _captureStartupFuture( _fetchRtcTokenForCurrentRoom(isPublisher: false), @@ -1965,6 +2252,9 @@ class RealTimeCommunicationManager extends ChangeNotifier { final microphoneListFuture = retrieveMicrophoneList(); final onlineUsersFuture = fetchOnlineUsersList(); final joinResult = await joinGroupFuture; + if (!_isActiveRoomStartup(entryRequestSerial, roomId)) { + return; + } if (joinResult == null || joinResult.code != 0) { debugPrint( '[RoomStartup] join IM group failed code=${joinResult?.code} desc=${joinResult?.desc}', @@ -1986,16 +2276,36 @@ class RealTimeCommunicationManager extends ChangeNotifier { ); await Future.wait([microphoneListFuture, onlineUsersFuture]); + if (!_isActiveRoomStartup(entryRequestSerial, roomId)) { + return; + } _startRoomStatePolling(); - Provider.of( - context!, - listen: false, - ).fetchContributionLevelData(roomId); + final currentContext = context; + if (currentContext != null && currentContext.mounted) { + Provider.of( + currentContext, + listen: false, + ).fetchContributionLevelData(roomId); + } failureType = RoomStartupFailureType.rtc; - final rtcToken = (await rtcTokenFuture).requireValue(); + final rtcTokenResult = await rtcTokenFuture; + if (!_isActiveRoomStartup(entryRequestSerial, roomId)) { + return; + } + final rtcToken = rtcTokenResult.requireValue(); await joinAgoraVoiceChannel(throwOnError: true, rtcToken: rtcToken); + if (!_isActiveRoomStartup(entryRequestSerial, roomId)) { + await _cleanupAgoraRoomState( + clearMicSeats: currenRoom == null, + onlyIfJoinedChannelId: roomId, + ); + return; + } await _bootstrapRoomHeartbeatState(); + if (!_isActiveRoomStartup(entryRequestSerial, roomId)) { + return; + } _setRoomStartupReady(); Msg joinMsg = Msg( @@ -2006,30 +2316,46 @@ class RealTimeCommunicationManager extends ChangeNotifier { type: SCRoomMsgType.joinRoom, ); rtmProvider?.dispatchMessage(joinMsg, addLocal: true); - _playRoomEntryEffects(joinMsg); + _playRoomEntryEffects( + joinMsg, + entryRequestSerial: entryRequestSerial, + roomId: roomId, + ); _loadRoomSecondaryData(); } catch (error, stackTrace) { + if (!_isActiveRoomStartup(entryRequestSerial, roomId)) { + debugPrint('[RoomStartup] ignore canceled bootstrap failure: $error'); + return; + } debugPrint('[RoomStartup] bootstrap failed: $error\n$stackTrace'); _setRoomStartupFailed(failureType); } } - void _playRoomEntryEffects(Msg joinMsg) { + void _playRoomEntryEffects( + Msg joinMsg, { + required int entryRequestSerial, + required String roomId, + }) { if (SCGlobalConfig.isEntryVehicleAnimation) { - if (AccountStorage().getCurrentUser()?.userProfile?.getMountains() != - null && - shouldShowRoomVisualEffects) { - Future.delayed(Duration(milliseconds: 550), () { - SCGiftVapSvgaManager().play( - AccountStorage() - .getCurrentUser() - ?.userProfile - ?.getMountains() - ?.sourceUrl ?? - "", - priority: 100, - type: 1, - ); + final sourceUrl = + AccountStorage() + .getCurrentUser() + ?.userProfile + ?.getMountains() + ?.sourceUrl ?? + ""; + if (sourceUrl.isNotEmpty && + shouldShowRoomVisualEffects && + _isCurrentRoomEntrySession(entryRequestSerial, roomId)) { + _roomEntryEffectTimer?.cancel(); + _roomEntryEffectTimer = Timer(const Duration(milliseconds: 550), () { + _roomEntryEffectTimer = null; + if (!shouldShowRoomVisualEffects || + !_isCurrentRoomEntrySession(entryRequestSerial, roomId)) { + return; + } + SCGiftVapSvgaManager().play(sourceUrl, priority: 100, type: 1); }); } } @@ -2193,6 +2519,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { _stopRoomStatePolling(); final groupId = currenRoom?.roomProfile?.roomProfile?.roomAccount ?? ""; final roomId = currenRoom?.roomProfile?.roomProfile?.id ?? ""; + final isPreviewOnlyExit = _currentRoomIsEntryPreview; final exitRtmProvider = rtmProvider; final navigationContext = context; try { @@ -2218,8 +2545,8 @@ class RealTimeCommunicationManager extends ChangeNotifier { final agoraLeaveTask = _leaveAgoraRoomForExit(); final remoteCleanupTask = _cleanupExitedRoomRemotely( exitRtmProvider: exitRtmProvider, - groupId: groupId, - roomId: roomId, + groupId: isPreviewOnlyExit ? "" : groupId, + roomId: isPreviewOnlyExit ? "" : roomId, shouldSendOnlineHeartbeat: !isLogout, ); if (deferRemoteCleanup) { @@ -2231,6 +2558,44 @@ class RealTimeCommunicationManager extends ChangeNotifier { } } + void _switchAwayFromCurrentRoomForNewEntry() { + _stopRoomStatePolling(); + final groupId = currenRoom?.roomProfile?.roomProfile?.roomAccount ?? ""; + final roomId = currenRoom?.roomProfile?.roomProfile?.id ?? ""; + final isPreviewOnlyExit = _currentRoomIsEntryPreview; + final exitRtmProvider = rtmProvider; + try { + exitRtmProvider?.msgAllListener = null; + exitRtmProvider?.msgChatListener = null; + exitRtmProvider?.msgGiftListener = null; + SCGiftVapSvgaManager().stopPlayback(); + setRoomVisualEffectsEnabled(false); + SCHeartbeatUtils.cancelTimer(); + exitRtmProvider?.cleanRoomData(); + } catch (e) { + debugPrint('rtc切换房间本地清理出错: $e'); + } + + _clearData(); + final agoraLeaveTask = _leaveAgoraRoomForExit(); + _pendingRoomSwitchAgoraLeaveTask = agoraLeaveTask; + unawaited( + agoraLeaveTask.whenComplete(() { + if (identical(_pendingRoomSwitchAgoraLeaveTask, agoraLeaveTask)) { + _pendingRoomSwitchAgoraLeaveTask = null; + } + }), + ); + unawaited( + _cleanupExitedRoomRemotely( + exitRtmProvider: exitRtmProvider, + groupId: isPreviewOnlyExit ? "" : groupId, + roomId: isPreviewOnlyExit ? "" : roomId, + shouldSendOnlineHeartbeat: false, + ), + ); + } + Future _cleanupExitedRoomRemotely({ required RtmProvider? exitRtmProvider, required String groupId, @@ -2348,6 +2713,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { } _isHandlingRoomStartupFailure = true; final failedRoom = currenRoom; + final isPreviewOnlyFailure = _currentRoomIsEntryPreview; final groupId = failedRoom?.roomProfile?.roomProfile?.roomAccount ?? ""; final roomId = failedRoom?.roomProfile?.roomProfile?.id ?? ""; final navigatorContext = navigationContext ?? context; @@ -2359,12 +2725,12 @@ class RealTimeCommunicationManager extends ChangeNotifier { SCHeartbeatUtils.cancelTimer(); SCHeartbeatUtils.cancelAnchorTimer(); rtmProvider?.cleanRoomData(); - if (groupId.isNotEmpty) { + if (!isPreviewOnlyFailure && groupId.isNotEmpty) { await rtmProvider?.quitGroup(groupId); } await _cleanupAgoraRoomState(clearMicSeats: true); await Future.delayed(const Duration(milliseconds: 100)); - if (roomId.isNotEmpty) { + if (!isPreviewOnlyFailure && roomId.isNotEmpty) { await SCAccountRepository().quitRoom(roomId); } } catch (e) { @@ -2382,6 +2748,8 @@ class RealTimeCommunicationManager extends ChangeNotifier { ///清空列表数据 void _clearData() { _roomEntryRequestSerial += 1; + _roomEntryEffectTimer?.cancel(); + _roomEntryEffectTimer = null; _previewRoomSeatCount = null; _finishRoomStartupSeatLoading(executePendingAction: false); _resetSelfMicGoUpFailureState(); @@ -2394,6 +2762,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { _isSelfMicActionInFlight = false; _roomStartupStatus = RoomStartupStatus.idle; _roomStartupFailureType = RoomStartupFailureType.none; + _currentRoomIsEntryPreview = false; _isHandlingRoomStartupFailure = false; _isHandlingAgoraRoomFailure = false; _pendingMicListRefresh = false; diff --git a/lib/services/home/home_room_preload_manager.dart b/lib/services/home/home_room_preload_manager.dart new file mode 100644 index 0000000..2534778 --- /dev/null +++ b/lib/services/home/home_room_preload_manager.dart @@ -0,0 +1,65 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:yumi/shared/business_logic/models/res/room_res.dart'; +import 'package:yumi/shared/data_sources/sources/local/user_manager.dart'; +import 'package:yumi/shared/data_sources/sources/repositories/sc_room_repository_imp.dart'; + +class SCHomeRoomPreloadManager { + SCHomeRoomPreloadManager._(); + + static final SCHomeRoomPreloadManager instance = SCHomeRoomPreloadManager._(); + + static const Duration _partyRoomCacheTtl = Duration(seconds: 30); + + Future>? _partyRoomsFuture; + List? _partyRooms; + DateTime? _partyRoomsLoadedAt; + + void preloadInitialHomeRooms() { + final token = AccountStorage().getToken(); + if (AccountStorage().getCurrentUser() == null || token.isEmpty) { + return; + } + unawaited( + loadPartyRooms().catchError((error, stackTrace) { + debugPrint('[HomePreload] party rooms preload failed: $error'); + return []; + }), + ); + } + + Future> loadPartyRooms({bool forceRefresh = false}) { + if (!forceRefresh && _hasFreshPartyRoomCache) { + return Future.value(List.from(_partyRooms!)); + } + if (!forceRefresh) { + final pendingFuture = _partyRoomsFuture; + if (pendingFuture != null) { + return pendingFuture; + } + } + + final future = SCChatRoomRepository() + .discovery(allRegion: true) + .then((rooms) { + _partyRooms = List.from(rooms); + _partyRoomsLoadedAt = DateTime.now(); + return List.from(rooms); + }) + .whenComplete(() { + _partyRoomsFuture = null; + }); + _partyRoomsFuture = future; + return future; + } + + bool get _hasFreshPartyRoomCache { + final rooms = _partyRooms; + final loadedAt = _partyRoomsLoadedAt; + if (rooms == null || loadedAt == null) { + return false; + } + return DateTime.now().difference(loadedAt) < _partyRoomCacheTtl; + } +} diff --git a/lib/ui_kit/widgets/room/exit_min_room_page.dart b/lib/ui_kit/widgets/room/exit_min_room_page.dart index f898190..de72e4a 100644 --- a/lib/ui_kit/widgets/room/exit_min_room_page.dart +++ b/lib/ui_kit/widgets/room/exit_min_room_page.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:yumi/app_localizations.dart'; @@ -6,8 +8,14 @@ import 'package:yumi/ui_kit/components/text/sc_text.dart'; import 'package:provider/provider.dart'; import 'package:yumi/app/routes/sc_routes.dart'; import 'package:yumi/app/routes/sc_fluro_navigator.dart'; +import 'package:yumi/services/audio/rtm_manager.dart'; import 'package:yumi/services/gift/gift_animation_manager.dart'; +import 'package:yumi/services/music/room_music_manager.dart'; import 'package:yumi/services/audio/rtc_manager.dart'; +import 'package:yumi/shared/data_sources/sources/local/floating_screen_manager.dart'; +import 'package:yumi/shared/tools/sc_gift_vap_svga_manager.dart'; +import 'package:yumi/shared/tools/sc_room_effect_scheduler.dart'; +import 'package:yumi/ui_kit/widgets/room/anim/room_entrance_widget.dart'; import '../../components/sc_float_ichart.dart'; @@ -54,15 +62,34 @@ class _ExitMinRoomPageState extends State { ), ], ), - onTap: () { + onTap: () async { + final rtcProvider = context.read(); + if (rtcProvider.roomStartupStatus == + RoomStartupStatus.loading || + rtcProvider.roomStartupStatus == RoomStartupStatus.failed) { + SCNavigatorUtils.goBack(context); + await rtcProvider.exitCurrentVoiceRoomSession(false); + return; + } final giftAnimationManager = context.read(); + final rtmProvider = context.read(); + rtcProvider.setRoomVisualEffectsEnabled(false); + rtmProvider.msgFloatingGiftListener = null; + rtmProvider.msgLuckyGiftRewardTickerListener = null; + RoomEntranceHelper.clearQueue(); + OverlayManager().removeRoom(); + SCRoomEffectScheduler().clearDeferredTasks( + reason: 'room_minimize', + ); + SCGiftVapSvgaManager().stopPlayback(); + unawaited(context.read().stopForRoomExit()); + giftAnimationManager.cleanupAnimationResources(); SCFloatIchart().show(); SCNavigatorUtils.popUntil( context, ModalRoute.withName(SCRoutes.home), ); - giftAnimationManager.cleanupAnimationResources(); }, ), SCDebounceWidget( diff --git a/lib/ui_kit/widgets/room/room_menu_dialog.dart b/lib/ui_kit/widgets/room/room_menu_dialog.dart index 78ef5a5..1e89fc8 100644 --- a/lib/ui_kit/widgets/room/room_menu_dialog.dart +++ b/lib/ui_kit/widgets/room/room_menu_dialog.dart @@ -38,7 +38,7 @@ class _RoomMenuDialogState extends State { static const int _menuReport = 5; static const int _menuBackground = 6; static const int _menuMusic = 7; - static bool get _showBackgroundFeature => true; + static bool get _showBackgroundFeature => false; List items2 = []; diff --git a/pubspec.yaml b/pubspec.yaml index 4fedae8..a2d6d96 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.2.5+7 +version: 1.2.6+8 environment: