1.2.6
This commit is contained in:
parent
fd445ccdaa
commit
36ba0f3573
@ -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 = "";
|
||||
|
||||
@ -272,8 +272,7 @@ class _RoomFollowPageState
|
||||
Provider.of<RtcProvider>(context, listen: false).joinVoiceRoomSession(
|
||||
context,
|
||||
roomRes.roomProfile?.id ?? "",
|
||||
previewSeatCount:
|
||||
roomRes.roomProfile?.extValues?.roomSetting?.mikeSize?.toInt(),
|
||||
previewData: RoomEntryPreviewData.fromFollowRoom(roomRes),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@ -272,8 +272,7 @@ class _SCRoomHistoryPageState
|
||||
Provider.of<RtcProvider>(context, listen: false).joinVoiceRoomSession(
|
||||
context,
|
||||
roomRes.roomProfile?.id ?? "",
|
||||
previewSeatCount:
|
||||
roomRes.roomProfile?.extValues?.roomSetting?.mikeSize?.toInt(),
|
||||
previewData: RoomEntryPreviewData.fromFollowRoom(roomRes),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@ -238,23 +238,26 @@ class _HomeMinePageState extends State<SCHomeMinePage>
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
String roomId =
|
||||
Provider.of<SocialChatRoomManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).myRoom?.id ??
|
||||
"";
|
||||
final roomManager = Provider.of<SocialChatRoomManager>(
|
||||
context,
|
||||
listen: false,
|
||||
);
|
||||
final myRoom = roomManager.myRoom;
|
||||
final roomId = myRoom?.id ?? "";
|
||||
Provider.of<RealTimeCommunicationManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).joinVoiceRoomSession(
|
||||
context,
|
||||
roomId,
|
||||
previewSeatCount:
|
||||
Provider.of<SocialChatRoomManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).myRoom?.setting?.mikeSize?.toInt(),
|
||||
previewData:
|
||||
myRoom == null
|
||||
? null
|
||||
: RoomEntryPreviewData.fromMyRoom(
|
||||
myRoom,
|
||||
ownerProfile:
|
||||
AccountStorage().getCurrentUser()?.userProfile,
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
|
||||
@ -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<SCHomePartyPage>
|
||||
enablePullUp: false,
|
||||
controller: _refreshController,
|
||||
onRefresh: () {
|
||||
loadData();
|
||||
loadData(forceRefresh: true);
|
||||
},
|
||||
onLoading: () {},
|
||||
child: SingleChildScrollView(
|
||||
@ -968,20 +969,20 @@ class _HomePartyPageState extends State<SCHomePartyPage>
|
||||
);
|
||||
}
|
||||
|
||||
loadData() {
|
||||
final generalManager = Provider.of<SCAppGeneralManager>(
|
||||
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<SCAppGeneralManager>(
|
||||
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<SCHomePartyPage>
|
||||
|
||||
_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<SCHomePartyPage>
|
||||
Provider.of<RtcProvider>(context, listen: false).joinVoiceRoomSession(
|
||||
context,
|
||||
res.id ?? "",
|
||||
previewSeatCount: res.extValues?.roomSetting?.mikeSize?.toInt(),
|
||||
previewData: RoomEntryPreviewData.fromSocialChatRoom(res),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@ -591,6 +591,24 @@ class _RoomEditPageState extends State<RoomEditPage> {
|
||||
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();
|
||||
|
||||
@ -65,6 +65,8 @@ class _VoiceRoomPageState extends State<VoiceRoomPage>
|
||||
final Map<String, _LuckyGiftComboSession> _luckyGiftComboSessions =
|
||||
<String, _LuckyGiftComboSession>{};
|
||||
int _shownRoomStartupFailureToken = 0;
|
||||
RtcProvider? _rtcProvider;
|
||||
bool _roomProviderRebuildScheduled = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -90,11 +92,20 @@ class _VoiceRoomPageState extends State<VoiceRoomPage>
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final rtcProvider = context.read<RtcProvider>();
|
||||
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<VoiceRoomPage>
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _handleRoomProviderChanged() {
|
||||
if (!mounted || _roomProviderRebuildScheduled) {
|
||||
return;
|
||||
}
|
||||
_roomProviderRebuildScheduled = true;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_roomProviderRebuildScheduled = false;
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
void _enableRoomVisualEffects() {
|
||||
Provider.of<RtcProvider>(
|
||||
context,
|
||||
|
||||
@ -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<T> _buildRoute<T>(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<T?>.value();
|
||||
}
|
||||
final route = _buildRoute<T>(
|
||||
const VoiceRoomPage(),
|
||||
settings: RouteSettings(name: voiceRoom),
|
||||
);
|
||||
_voiceRoomRouteDepth = replace ? 1 : _voiceRoomRouteDepth + 1;
|
||||
Future<T?> routeFuture;
|
||||
if (replace) {
|
||||
return navigator.pushReplacement<T, T>(route);
|
||||
routeFuture = navigator.pushReplacement<T, T>(route);
|
||||
} else {
|
||||
routeFuture = navigator.push<T>(route);
|
||||
}
|
||||
return navigator.push<T>(route);
|
||||
return routeFuture.whenComplete(() {
|
||||
if (_voiceRoomRouteDepth > 0) {
|
||||
_voiceRoomRouteDepth -= 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static Future<T?> openRoomEdit<T>(
|
||||
|
||||
@ -434,13 +434,11 @@ class _SearchRoomListState extends State<SearchRoomList> {
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () async {
|
||||
if (context != null) {
|
||||
Provider.of<RtcProvider>(context, listen: false).joinVoiceRoomSession(
|
||||
context,
|
||||
e.id ?? "",
|
||||
previewSeatCount: e.extValues?.roomSetting?.mikeSize?.toInt(),
|
||||
);
|
||||
}
|
||||
Provider.of<RtcProvider>(context, listen: false).joinVoiceRoomSession(
|
||||
context,
|
||||
e.id ?? "",
|
||||
previewData: RoomEntryPreviewData.fromSocialChatRoom(e),
|
||||
);
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomCenter,
|
||||
@ -544,9 +542,9 @@ class _SearchRoomListState extends State<SearchRoomList> {
|
||||
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,
|
||||
|
||||
@ -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<SplashPage> {
|
||||
_selectedVariant = _pickSplashVariant();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
unawaited(FileCacheManager.getInstance().getFilePath());
|
||||
SCHomeRoomPreloadManager.instance.preloadInitialHomeRooms();
|
||||
unawaited(WeeklyStarSplashCache.refreshCacheInBackground());
|
||||
unawaited(LastWeeklyCPSplashCache.refreshCacheInBackground());
|
||||
});
|
||||
|
||||
@ -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<MePage2> {
|
||||
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<MePage2> {
|
||||
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<MePage2> {
|
||||
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<MePage2> {
|
||||
onTap: () async {
|
||||
await SCNavigatorUtils.push(context, VipRoute.detail);
|
||||
if (mounted) {
|
||||
_loadVipStatus();
|
||||
_refreshAfterVipReturn(profileManager);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
|
||||
@ -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<T> {
|
||||
}
|
||||
}
|
||||
|
||||
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<void>? _joinAgoraCompleter;
|
||||
Future<RtcEngine>? _rtcEngineInitTask;
|
||||
Future<void>? _rtcEnginePrewarmTask;
|
||||
Future<void>? _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<void> _cleanupAgoraRoomState({bool clearMicSeats = false}) async {
|
||||
Future<void> _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<void> _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<void> 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<void> _bootstrapEnteredVoiceRoomSession() async {
|
||||
Future<void> _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<SocialChatRoomManager>(
|
||||
context!,
|
||||
listen: false,
|
||||
).fetchContributionLevelData(roomId);
|
||||
final currentContext = context;
|
||||
if (currentContext != null && currentContext.mounted) {
|
||||
Provider.of<SocialChatRoomManager>(
|
||||
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<void> _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;
|
||||
|
||||
65
lib/services/home/home_room_preload_manager.dart
Normal file
65
lib/services/home/home_room_preload_manager.dart
Normal file
@ -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<List<SocialChatRoomRes>>? _partyRoomsFuture;
|
||||
List<SocialChatRoomRes>? _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 <SocialChatRoomRes>[];
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<SocialChatRoomRes>> loadPartyRooms({bool forceRefresh = false}) {
|
||||
if (!forceRefresh && _hasFreshPartyRoomCache) {
|
||||
return Future.value(List<SocialChatRoomRes>.from(_partyRooms!));
|
||||
}
|
||||
if (!forceRefresh) {
|
||||
final pendingFuture = _partyRoomsFuture;
|
||||
if (pendingFuture != null) {
|
||||
return pendingFuture;
|
||||
}
|
||||
}
|
||||
|
||||
final future = SCChatRoomRepository()
|
||||
.discovery(allRegion: true)
|
||||
.then((rooms) {
|
||||
_partyRooms = List<SocialChatRoomRes>.from(rooms);
|
||||
_partyRoomsLoadedAt = DateTime.now();
|
||||
return List<SocialChatRoomRes>.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;
|
||||
}
|
||||
}
|
||||
@ -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<ExitMinRoomPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
onTap: () async {
|
||||
final rtcProvider = context.read<RtcProvider>();
|
||||
if (rtcProvider.roomStartupStatus ==
|
||||
RoomStartupStatus.loading ||
|
||||
rtcProvider.roomStartupStatus == RoomStartupStatus.failed) {
|
||||
SCNavigatorUtils.goBack(context);
|
||||
await rtcProvider.exitCurrentVoiceRoomSession(false);
|
||||
return;
|
||||
}
|
||||
final giftAnimationManager =
|
||||
context.read<GiftAnimationManager>();
|
||||
final rtmProvider = context.read<RtmProvider>();
|
||||
rtcProvider.setRoomVisualEffectsEnabled(false);
|
||||
rtmProvider.msgFloatingGiftListener = null;
|
||||
rtmProvider.msgLuckyGiftRewardTickerListener = null;
|
||||
RoomEntranceHelper.clearQueue();
|
||||
OverlayManager().removeRoom();
|
||||
SCRoomEffectScheduler().clearDeferredTasks(
|
||||
reason: 'room_minimize',
|
||||
);
|
||||
SCGiftVapSvgaManager().stopPlayback();
|
||||
unawaited(context.read<RoomMusicManager>().stopForRoomExit());
|
||||
giftAnimationManager.cleanupAnimationResources();
|
||||
SCFloatIchart().show();
|
||||
SCNavigatorUtils.popUntil(
|
||||
context,
|
||||
ModalRoute.withName(SCRoutes.home),
|
||||
);
|
||||
giftAnimationManager.cleanupAnimationResources();
|
||||
},
|
||||
),
|
||||
SCDebounceWidget(
|
||||
|
||||
@ -38,7 +38,7 @@ class _RoomMenuDialogState extends State<RoomMenuDialog> {
|
||||
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<RoomMenu> items2 = [];
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user