diff --git a/lib/app/config/configs/sc_variant1_config.dart b/lib/app/config/configs/sc_variant1_config.dart index e4502ee..c31ecf2 100644 --- a/lib/app/config/configs/sc_variant1_config.dart +++ b/lib/app/config/configs/sc_variant1_config.dart @@ -16,7 +16,7 @@ class SCVariant1Config implements AppConfig { @override String get apiHost => const String.fromEnvironment( 'API_HOST', - defaultValue: 'https://jvapi.haiyihy.com/', + defaultValue: 'http://192.168.110.64:1100/', ); // 默认连本地接口,本地调试可通过 --dart-define=API_HOST 覆盖,线上“https://jvapi.haiyihy.com/” @override diff --git a/lib/app/constants/sc_global_config.dart b/lib/app/constants/sc_global_config.dart index 59cdd01..0ba2a6b 100644 --- a/lib/app/constants/sc_global_config.dart +++ b/lib/app/constants/sc_global_config.dart @@ -168,8 +168,7 @@ class SCGlobalConfig { } static String clampFloatingBroadcastScope(String value) { - final scope = normalizeFloatingBroadcastScope(value); - return _isLowPerformanceDevice ? floatingBroadcastScopeOff : scope; + return normalizeFloatingBroadcastScope(value); } static String floatingBroadcastScopeStorageKey(String? account) { @@ -188,8 +187,7 @@ class SCGlobalConfig { static bool get isLowPerformanceDevice => _isLowPerformanceDevice; - static bool get allowsHighCostAnimations => - !_isLowPerformanceDevice && sdkInt > maxSdkNoAnim; + static bool get allowsHighCostAnimations => true; static int get recommendedImageCacheBytes => _isLowPerformanceDevice ? 40 * 1024 * 1024 : 100 * 1024 * 1024; @@ -211,19 +209,17 @@ class SCGlobalConfig { isLowRamDevice || processorCount <= 6 || matchesKnownLowPerformanceModel; - resetVisualEffectSwitchesToRecommendedDefaults(); } static bool clampVisualEffectPreference(bool enabled) { - return !_isLowPerformanceDevice && enabled; + return enabled; } static void resetVisualEffectSwitchesToRecommendedDefaults() { - final enabled = !_isLowPerformanceDevice; - isEntryVehicleAnimation = enabled; - isGiftSpecialEffects = enabled; - isFloatingAnimationInGlobal = enabled; - isLuckGiftSpecialEffects = enabled; + isEntryVehicleAnimation = true; + isGiftSpecialEffects = true; + isFloatingAnimationInGlobal = true; + isLuckGiftSpecialEffects = true; } /// 获取当前业务逻辑策略 diff --git a/lib/modules/chat/message_chat_page.dart b/lib/modules/chat/message_chat_page.dart index f24c035..f1f6d06 100644 --- a/lib/modules/chat/message_chat_page.dart +++ b/lib/modules/chat/message_chat_page.dart @@ -23,7 +23,6 @@ import 'package:yumi/shared/tools/sc_message_utils.dart'; import 'package:yumi/shared/tools/sc_user_id_utils.dart'; import 'package:yumi/shared/data_sources/sources/repositories/sc_user_repository_impl.dart'; import 'package:yumi/shared/business_logic/models/res/login_res.dart'; -import 'package:yumi/shared/business_logic/models/res/sc_vip_res.dart'; import 'package:yumi/services/audio/rtm_manager.dart'; import 'package:marquee/marquee.dart'; import 'package:provider/provider.dart'; @@ -59,7 +58,6 @@ import 'package:yumi/shared/tools/sc_message_notifier.dart'; import 'package:yumi/shared/tools/sc_path_utils.dart'; import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart'; import 'package:yumi/shared/data_sources/sources/local/user_manager.dart'; -import 'package:yumi/shared/data_sources/sources/repositories/sc_vip_repository_imp.dart'; import 'package:yumi/services/auth/user_profile_manager.dart'; import 'package:yumi/modules/index/main_route.dart'; import 'package:yumi/ui_kit/widgets/sc_nine_patch_image.dart'; @@ -81,29 +79,6 @@ const EdgeInsets _vipBubbleCenterSliceRatio = EdgeInsets.fromLTRB( ); const EdgeInsets _vipBubbleSourceEdgeInset = EdgeInsets.all(2); -String _resolveVipChatBubbleImageUrl(SCVipResourceRes? resource) { - final candidates = [ - resource?.sourceResourceUrl, - resource?.previewUrl, - resource?.coverUrl, - resource?.cover, - ]; - return _firstNonBlankChatBubbleUrl([ - ...candidates.where((value) => SCNetworkSvgaWidget.isSvga(value)), - ...candidates, - ]); -} - -String _firstNonBlankChatBubbleUrl(Iterable values) { - for (final value in values) { - final text = value?.trim(); - if (text != null && text.isNotEmpty) { - return text; - } - } - return ""; -} - class SCMessageChatPage extends StatefulWidget { final V2TimConversation? conversation; final bool shrinkWrap; @@ -144,8 +119,6 @@ class _SCMessageChatPageState extends State { ///互相关注才能互相发送消息 bool canSendMsg = false; SocialChatUserProfile? friend; - SCVipResourceRes? _selfVipChatBubble; - bool _isSelfVipChatBubbleLoading = false; final Map _localCpInviteStates = {}; ///是否显示发送按钮 @@ -196,7 +169,6 @@ class _SCMessageChatPageState extends State { rtmProvider?.onRevokeMessageListener = _onRevokeMessage; rtmProvider?.onNewMessageCurrentConversationListener = _onNewMessage; loadMsg(); - _loadSelfVipChatBubble(); if (_isC2CConversation && friend == null) { loadFriend(); @@ -385,171 +357,6 @@ class _SCMessageChatPageState extends State { }); } - Future _loadSelfVipChatBubble() async { - if (_isSelfVipChatBubbleLoading) return; - final currentUserId = AccountStorage().getCurrentUser()?.userProfile?.id; - if (currentUserId == null || currentUserId.isEmpty) return; - - _isSelfVipChatBubbleLoading = true; - final repository = SCVipRepositoryImp(); - SCVipHomeRes? vipHome; - SCVipResourceRes? chatBubble; - - try { - final home = await repository.vipHome(); - vipHome = home; - chatBubble = _resolveSelfVipChatBubbleFromHome(home); - } catch (error) {} - - if (chatBubble == null) { - try { - final status = await repository.vipStatus(); - chatBubble = _resolveSelfVipChatBubbleFromStatus(status); - if (chatBubble == null && - vipHome != null && - _isUsableVipStatus(status)) { - chatBubble = _firstUsableVipChatBubble([ - _currentVipLevelConfig( - vipHome, - targetLevel: status.levelInt, - targetLevelCode: status.levelCode, - )?.chatBubble, - ]); - } - } catch (error) {} - } - - if (!mounted) return; - setState(() { - _selfVipChatBubble = chatBubble; - _isSelfVipChatBubbleLoading = false; - }); - } - - SCVipResourceRes? _resolveSelfVipChatBubbleFromHome(SCVipHomeRes home) { - final status = home.state; - if (status?.active == false) { - return null; - } - - final config = _currentVipLevelConfig(home); - if (_isUsableVipStatus(status)) { - return _firstUsableVipChatBubble([ - status?.chatBubble, - config?.chatBubble, - ]); - } - - final profileLevel = - AccountStorage().getCurrentUser()?.userProfile?.vipLevelForColoredId ?? - 0; - if (profileLevel > 0) { - return _firstUsableVipChatBubble([config?.chatBubble]); - } - return null; - } - - SCVipResourceRes? _resolveSelfVipChatBubbleFromStatus(SCVipStatusRes status) { - if (!_isUsableVipStatus(status)) { - return null; - } - return _firstUsableVipChatBubble([status.chatBubble]); - } - - SCVipLevelConfigRes? _currentVipLevelConfig( - SCVipHomeRes home, { - int? targetLevel, - String? targetLevelCode, - }) { - final status = home.state; - final statusLevel = _vipLevelIntFromStatus(status); - final profileLevel = - AccountStorage().getCurrentUser()?.userProfile?.vipLevelForColoredId ?? - 0; - final resolvedTargetLevel = - (targetLevel ?? 0) > 0 - ? targetLevel! - : (statusLevel > 0 ? statusLevel : profileLevel); - final statusLevelCode = - targetLevelCode?.trim() ?? status?.levelCode?.trim(); - - for (final level in home.levels) { - if (resolvedTargetLevel > 0 && level.levelInt == resolvedTargetLevel) { - return level; - } - } - if (statusLevelCode != null && statusLevelCode.isNotEmpty) { - for (final level in home.levels) { - if (_sameVipLevelCode(level.levelCode, statusLevelCode)) { - return level; - } - } - } - return null; - } - - bool _isUsableVipStatus(SCVipStatusRes? status) { - return status != null && - status.active != false && - (_vipLevelIntFromStatus(status) > 0 || - _hasNonBlankText(status.levelCode) || - _hasNonBlankText(status.displayName) || - _resolveVipChatBubbleImageUrl(status.chatBubble).isNotEmpty); - } - - int _vipLevelIntFromStatus(SCVipStatusRes? status) { - final explicitLevel = status?.levelInt ?? 0; - if (explicitLevel > 0) { - return explicitLevel; - } - return _parseVipLevelText(status?.levelCode) ?? - _parseVipLevelText(status?.displayName) ?? - 0; - } - - int? _parseVipLevelText(String? value) { - final text = value?.trim(); - if (text == null || text.isEmpty) { - return null; - } - final match = RegExp( - r'(?:S?VIP)?\s*([1-9]\d*)', - caseSensitive: false, - ).firstMatch(text); - return int.tryParse(match?.group(1) ?? ''); - } - - bool _sameVipLevelCode(String? left, String? right) { - final normalizedLeft = left?.replaceAll(RegExp(r'\s+'), '').toLowerCase(); - final normalizedRight = right?.replaceAll(RegExp(r'\s+'), '').toLowerCase(); - return normalizedLeft != null && - normalizedLeft.isNotEmpty && - normalizedLeft == normalizedRight; - } - - bool _hasNonBlankText(String? value) { - return value?.trim().isNotEmpty ?? false; - } - - SCVipResourceRes? _firstUsableVipChatBubble( - Iterable resources, - ) { - for (final resource in resources) { - if (_resolveVipChatBubbleImageUrl(resource).isNotEmpty) { - return resource; - } - } - return null; - } - - String _vipChatBubbleLogValue(SCVipResourceRes? resource) { - if (resource == null) return 'null'; - return '{id:${resource.resourceId},name:${resource.name},' - 'previewUrl:${resource.previewUrl},' - 'sourceUrl:${resource.sourceResourceUrl},' - 'selectedUrl:${_resolveVipChatBubbleImageUrl(resource)}}'; - } - ///消息列表 Widget _msgList() { return SmartRefresher( @@ -595,7 +402,6 @@ class _SCMessageChatPageState extends State { delegate: SliverChildBuilderDelegate( (c, i) => _MessageItem( message: currentConversationMessageList[i], - selfVipChatBubble: _selfVipChatBubble, currentConversation: currentConversation, preMessage: i > 0 ? currentConversationMessageList[i - 1] : null, @@ -1182,7 +988,6 @@ class _MessageItem extends StatelessWidget { final V2TimMessage message; final V2TimMessage? preMessage; - final SCVipResourceRes? selfVipChatBubble; final V2TimConversation? currentConversation; BusinessLogicStrategy get _strategy => SCGlobalConfig.businessLogicStrategy; @@ -1201,7 +1006,6 @@ class _MessageItem extends StatelessWidget { _MessageItem({ required this.message, - this.selfVipChatBubble, this.currentConversation, this.preMessage, // this.userProfile, @@ -2827,24 +2631,18 @@ class _MessageItem extends StatelessWidget { if (chatBubbleUrl.isNotEmpty) { return _buildVipTextBubble(content: content, imageUrl: chatBubbleUrl); } - if (message.isSelf ?? false) { - final vipChatBubbleUrl = _resolveVipChatBubbleImageUrl(selfVipChatBubble); - if (vipChatBubbleUrl.isNotEmpty) { - return _buildVipTextBubble( - content: content, - imageUrl: vipChatBubbleUrl, - ); - } - } return _buildDefaultTextBubble(content); } PropsResources? _currentUserChatBubble() { - final memoryBubble = - AccountStorage().getCurrentUser()?.userProfile?.getChatBox(); + final currentUser = AccountStorage().getCurrentUser(); + final memoryBubble = currentUser?.userProfile?.getChatBox(); if (_resolveChatBubbleImageUrl(memoryBubble).isNotEmpty) { return memoryBubble; } + if (currentUser?.userProfile != null) { + return memoryBubble; + } final userJson = DataPersistence.getCurrentUser(); if (userJson.isEmpty) { diff --git a/lib/modules/gift/gift_page.dart b/lib/modules/gift/gift_page.dart index eb74d7f..83f3a54 100644 --- a/lib/modules/gift/gift_page.dart +++ b/lib/modules/gift/gift_page.dart @@ -1900,16 +1900,6 @@ class _GiftPageState extends State with TickerProviderStateMixin { 'animationCount=$animationCount', ); SCGiftVapSvgaManager().play(gift.giftSourceUrl!); - } else if (!_isCpGift(gift) && - SCGlobalConfig.isLowPerformanceDevice && - SCGlobalConfig.isGiftSpecialEffects && - (rtcProvider?.shouldShowRoomVisualEffects ?? false)) { - _enqueueLowPerformanceGiftCompensation( - gift: gift, - receiver: u.user, - quantity: quantity, - coins: coins, - ); } else { _giftFxLog( 'skip local play because visual effects disabled ' @@ -1936,52 +1926,10 @@ class _GiftPageState extends State with TickerProviderStateMixin { } } - void _enqueueLowPerformanceGiftCompensation({ - required SocialChatGiftRes gift, - required SocialChatUserProfile? receiver, - required int quantity, - required num coins, - }) { - final sender = AccountStorage().getCurrentUser()?.userProfile; - final roomId = rtcProvider?.currenRoom?.roomProfile?.roomProfile?.id ?? ""; - _enqueueGiftFloatingMessage( - SCFloatingMessage( - type: 1, - priority: 900, - userId: sender?.id ?? "", - toUserId: receiver?.id ?? "", - userAvatarUrl: sender?.userAvatar ?? "", - toUserAvatarUrl: receiver?.userAvatar ?? "", - userName: sender?.userNickname ?? "", - toUserName: receiver?.userNickname ?? "", - giftUrl: gift.giftPhoto ?? "", - giftId: gift.id, - giftTab: _floatingGiftTabFor(gift), - number: quantity, - coins: coins, - roomId: roomId, - ), - dedupKey: _giftFloatingDedupKey( - roomId: roomId, - senderId: sender?.id, - receiverId: receiver?.id, - giftId: gift.id, - quantity: quantity, - ), - ); - } - void _enqueueGiftFloatingMessage( SCFloatingMessage message, { String? dedupKey, }) { - if (SCGlobalConfig.isLowPerformanceDevice) { - OverlayManager().addLowPerformanceCompensationMessage( - message, - dedupKey: dedupKey, - ); - return; - } OverlayManager().addMessage(message); } diff --git a/lib/modules/room_game/views/baishun_loading_view.dart b/lib/modules/room_game/views/baishun_loading_view.dart index 3363bcb..cbf3984 100644 --- a/lib/modules/room_game/views/baishun_loading_view.dart +++ b/lib/modules/room_game/views/baishun_loading_view.dart @@ -6,24 +6,24 @@ class BaishunLoadingView extends StatelessWidget { const BaishunLoadingView({ super.key, this.message = 'Loading game...', + this.backgroundColor = const Color(0xFF081915), }); final String message; + final Color backgroundColor; @override Widget build(BuildContext context) { return Positioned.fill( child: Container( - color: Colors.black.withValues(alpha: 0.42), + color: backgroundColor, alignment: Alignment.center, child: Container( padding: EdgeInsets.symmetric(horizontal: 22.w, vertical: 18.w), decoration: BoxDecoration( color: const Color(0xFF102D28).withValues(alpha: 0.92), borderRadius: BorderRadius.circular(16.w), - border: Border.all( - color: Colors.white.withValues(alpha: 0.1), - ), + border: Border.all(color: Colors.white.withValues(alpha: 0.1)), ), child: Column( mainAxisSize: MainAxisSize.min, diff --git a/lib/modules/user/my_items/chatbox/bags_chatbox_page.dart b/lib/modules/user/my_items/chatbox/bags_chatbox_page.dart index 6057619..3475e5b 100644 --- a/lib/modules/user/my_items/chatbox/bags_chatbox_page.dart +++ b/lib/modules/user/my_items/chatbox/bags_chatbox_page.dart @@ -295,6 +295,9 @@ class _BagsChatboxPageState res.propsResources?.id ?? "", unload, ); + try { + await profileManager.fetchUserProfileData(loadGuardCount: false); + } catch (_) {} if (!mounted) { return false; } @@ -305,8 +308,11 @@ class _BagsChatboxPageState myChatbox = null; SCTts.show(localizations.successfullyUnloaded); } + profileManager.syncCurrentUserChatBubble( + unload ? null : res.propsResources, + expireTime: res.expireTime?.toString(), + ); setState(() {}); - profileManager.fetchUserProfileData(loadGuardCount: false); return true; } catch (e) { return false; diff --git a/lib/services/audio/rtc_manager.dart b/lib/services/audio/rtc_manager.dart index 423d7f3..f2f0862 100644 --- a/lib/services/audio/rtc_manager.dart +++ b/lib/services/audio/rtc_manager.dart @@ -13,8 +13,6 @@ import 'package:yumi/shared/tools/sc_room_utils.dart'; import 'package:yumi/shared/tools/sc_room_top_layer_guard.dart'; import 'package:yumi/shared/tools/sc_cp_relation_notice_utils.dart'; import 'package:yumi/shared/data_sources/models/message/room_rocket_launch_broadcast_message.dart'; -import 'package:yumi/shared/data_sources/models/message/sc_floating_message.dart'; -import 'package:yumi/shared/data_sources/sources/local/floating_screen_manager.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'; import 'package:yumi/shared/data_sources/sources/repositories/sc_vip_repository_imp.dart'; @@ -3864,46 +3862,6 @@ class RealTimeCommunicationManager extends ChangeNotifier { return ""; } - String _resolveEntryCompensationCover(PropsResources? resource) { - return _firstNonBlankEntryResource([ - resource?.roomSendCoverUrl, - resource?.roomOpenedUrl, - resource?.cover, - resource?.roomNotOpenedUrl, - ]); - } - - void _enqueueLowPerformanceEntryCompensation({ - required Msg joinMsg, - required PropsResources resource, - required String roomId, - }) { - if (!SCGlobalConfig.isLowPerformanceDevice || - !shouldShowRoomVisualEffects || - roomId.isEmpty) { - return; - } - final coverUrl = _resolveEntryCompensationCover(resource); - OverlayManager().addLowPerformanceCompensationMessage( - SCFloatingMessage( - type: 5, - priority: 950, - userId: joinMsg.user?.id ?? "", - roomId: roomId, - userAvatarUrl: joinMsg.user?.userAvatar ?? "", - userName: joinMsg.user?.userNickname ?? "", - giftUrl: coverUrl, - fallbackUrl: coverUrl, - ), - dedupKey: [ - "entry", - roomId, - joinMsg.user?.id ?? "", - resource.id ?? "", - ].join("|"), - ); - } - void _playRoomEntryEffects( Msg joinMsg, { required int entryRequestSerial, @@ -3931,24 +3889,6 @@ class RealTimeCommunicationManager extends ChangeNotifier { type: SCGiftVapSvgaManager.entryEffectType, ); }); - } else if (sourceUrl.isNotEmpty && - SCGlobalConfig.isLowPerformanceDevice && - SCGlobalConfig.isEntryVehicleAnimation && - shouldShowRoomVisualEffects && - _isCurrentRoomEntrySession(entryRequestSerial, roomId)) { - _roomEntryEffectTimer?.cancel(); - _roomEntryEffectTimer = Timer(const Duration(milliseconds: 550), () { - _roomEntryEffectTimer = null; - if (!shouldShowRoomVisualEffects || - !_isCurrentRoomEntrySession(entryRequestSerial, roomId)) { - return; - } - _enqueueLowPerformanceEntryCompensation( - joinMsg: joinMsg, - resource: entryResource, - roomId: roomId, - ); - }); } } if (rtmProvider?.msgUserJoinListener != null) { @@ -5296,11 +5236,10 @@ class RealTimeCommunicationManager extends ChangeNotifier { ); final targetIndex = micGoUpRes.micIndex ?? index; + final selfMicMuted = micGoUpRes.micMute ?? false; final switched = await _switchRoomRtcToBroadcaster( - muted: (micGoUpRes.micMute ?? false) || isMic, - keepAudioPublishing: - ((micGoUpRes.micMute ?? false) || isMic) && - _currentUserPublishingRoomMusic, + muted: selfMicMuted, + keepAudioPublishing: selfMicMuted && _currentUserPublishingRoomMusic, ); if (!switched) { await _switchRoomRtcToAudience(); @@ -5356,6 +5295,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { roomToken: micGoUpRes.roomToken, ); } + isMic = selfMicMuted; _syncSelfMicRuntimeState(); if (roomWheatMap[targetIndex]?.micMute ?? false) { ///房主上麦自动解禁麦位 diff --git a/lib/services/audio/rtm_manager.dart b/lib/services/audio/rtm_manager.dart index 27bbacb..e01ff20 100644 --- a/lib/services/audio/rtm_manager.dart +++ b/lib/services/audio/rtm_manager.dart @@ -256,13 +256,6 @@ class RealTimeMessagingManager extends ChangeNotifier { SCFloatingMessage message, { String? dedupKey, }) { - if (SCGlobalConfig.isLowPerformanceDevice) { - OverlayManager().addLowPerformanceCompensationMessage( - message, - dedupKey: dedupKey, - ); - return; - } OverlayManager().addMessage(message); } @@ -283,23 +276,6 @@ class RealTimeMessagingManager extends ChangeNotifier { ].join("|"); } - String _entryFloatingDedupKey({ - required String? roomId, - required String? userId, - required String? resourceId, - }) { - return ["entry", roomId ?? "", userId ?? "", resourceId ?? ""].join("|"); - } - - String _resolveEntryCompensationCover(PropsResources? resource) { - return _firstNonBlank([ - resource?.roomSendCoverUrl, - resource?.roomOpenedUrl, - resource?.cover, - resource?.roomNotOpenedUrl, - ]); - } - String _firstNonBlank(Iterable values) { for (final value in values) { final text = value?.trim(); @@ -6387,29 +6363,6 @@ class RealTimeMessagingManager extends ChangeNotifier { priority: SCGiftVapSvgaManager.entryEffectPriority, type: SCGiftVapSvgaManager.entryEffectType, ); - } else if (SCGlobalConfig.isLowPerformanceDevice && - SCGlobalConfig.isEntryVehicleAnimation && - shouldShowRoomVisualEffects) { - final roomId = - rtcProvider.currenRoom?.roomProfile?.roomProfile?.id ?? ""; - final coverUrl = _resolveEntryCompensationCover(entryResource); - OverlayManager().addLowPerformanceCompensationMessage( - SCFloatingMessage( - type: 5, - priority: 950, - userId: msg.user?.id ?? "", - roomId: roomId, - userAvatarUrl: msg.user?.userAvatar ?? "", - userName: msg.user?.userNickname ?? "", - giftUrl: coverUrl, - fallbackUrl: coverUrl, - ), - dedupKey: _entryFloatingDedupKey( - roomId: roomId, - userId: msg.user?.id, - resourceId: entryResource.id, - ), - ); } } } else if (msg.type == SCRoomMsgType.gift) { @@ -6460,46 +6413,6 @@ class RealTimeMessagingManager extends ChangeNotifier { 'giftId=${gift.id} giftName=${gift.giftName}', ); SCGiftVapSvgaManager().play(giftSourceUrl); - } else if (!scIsCpGift(gift) && - SCGlobalConfig.isLowPerformanceDevice && - SCGlobalConfig.isGiftSpecialEffects && - rtcProvider.shouldShowRoomVisualEffects) { - final roomId = - (msg.msg?.trim().isNotEmpty ?? false) - ? msg.msg ?? "" - : rtcProvider - .currenRoom - ?.roomProfile - ?.roomProfile - ?.id ?? - ""; - final quantity = msg.number ?? 0; - final coins = quantity * (gift.giftCandy ?? 0); - _enqueueGiftFloatingMessage( - SCFloatingMessage( - type: 1, - priority: 900, - userId: msg.user?.id ?? "", - toUserId: msg.toUser?.id ?? "", - userAvatarUrl: msg.user?.userAvatar ?? "", - userName: msg.user?.userNickname ?? "", - toUserName: msg.toUser?.userNickname ?? "", - toUserAvatarUrl: msg.toUser?.userAvatar ?? "", - giftUrl: gift.giftPhoto, - giftId: gift.id, - giftTab: _floatingGiftTabFor(gift), - number: quantity, - coins: coins, - roomId: roomId, - ), - dedupKey: _giftFloatingDedupKey( - roomId: roomId, - senderId: msg.user?.id, - receiverId: msg.toUser?.id, - giftId: gift.id, - quantity: quantity, - ), - ); } else { _giftFxLog( 'skip player play because visual effects disabled ' diff --git a/lib/services/auth/user_profile_manager.dart b/lib/services/auth/user_profile_manager.dart index add84ed..d5adb4e 100644 --- a/lib/services/auth/user_profile_manager.dart +++ b/lib/services/auth/user_profile_manager.dart @@ -14,6 +14,7 @@ import 'package:yumi/shared/business_logic/models/res/login_res.dart'; import 'package:yumi/shared/business_logic/models/res/room_user_card_res.dart'; import 'package:yumi/shared/business_logic/models/res/sc_user_identity_res.dart'; import 'package:yumi/shared/business_logic/models/res/sc_vip_res.dart'; +import 'package:yumi/shared/data_sources/models/enum/sc_props_type.dart'; import 'package:yumi/shared/tools/sc_cp_relation_level_utils.dart'; import 'package:yumi/shared/tools/sc_cp_relation_notice_utils.dart'; @@ -92,6 +93,32 @@ class SocialChatUserProfileManager extends ChangeNotifier { notifyListeners(); } + void syncCurrentUserChatBubble( + PropsResources? chatBubble, { + String? expireTime, + }) { + final profile = currentUserProfile; + if (profile == null) { + return; + } + + final useProps = [ + ...?profile.useProps?.where( + (item) => item.propsResources?.type != SCPropsType.CHAT_BUBBLE.name, + ), + ]; + if (chatBubble != null) { + useProps.add( + UseProps( + expireTime: expireTime ?? "4102444800000", + propsResources: chatBubble, + userId: profile.id, + ), + ); + } + syncCurrentUserProfile(profile.copyWith(useProps: useProps)); + } + Future fetchUserProfileData({ bool loadGuardCount = true, bool refreshFamilyData = false, diff --git a/lib/shared/data_sources/sources/local/floating_screen_manager.dart b/lib/shared/data_sources/sources/local/floating_screen_manager.dart index b9739a9..c2f36f5 100644 --- a/lib/shared/data_sources/sources/local/floating_screen_manager.dart +++ b/lib/shared/data_sources/sources/local/floating_screen_manager.dart @@ -26,9 +26,7 @@ import 'package:yumi/ui_kit/widgets/svga/sc_svga_asset_widget.dart'; typedef FloatingScreenManager = OverlayManager; class OverlayManager { - static const int _maxLowPerformanceCompensationQueueLength = 8; static const int _maxDeferredRegionRedPacketCount = 12; - static const Duration _compensationDedupWindow = Duration(seconds: 3); static const Duration _redPacketFloatingDedupWindow = Duration(minutes: 30); static const Duration _rocketFloatingFallbackDedupWindow = Duration( seconds: 30, @@ -43,7 +41,6 @@ class OverlayManager { (a, b) => b.priority.compareTo(a.priority), ); final List _deferredRegionRedPacketMessages = []; - final Map _recentCompensationKeys = {}; final Map _recentFloatingKeys = {}; final Map _stackedOverlayEntries = {}; final Map _stackedMessages = {}; @@ -84,28 +81,6 @@ class OverlayManager { } } - void addLowPerformanceCompensationMessage( - SCFloatingMessage message, { - String? dedupKey, - }) { - if (_isDisposed || - _isSuppressed || - !SCGlobalConfig.isLowPerformanceDevice || - SCGlobalConfig.isFloatingBroadcastClosed) { - return; - } - final key = dedupKey ?? _compensationKeyFor(message); - if (_isRecentCompensationDuplicate(key)) { - return; - } - _rememberCompensationKey(key); - _trimLowPerformanceCompensationQueue(); - _enqueueMessage( - message, - debugLabel: 'low_performance_compensation_${message.type ?? -1}', - ); - } - void _enqueueMessage( SCFloatingMessage message, { required String debugLabel, @@ -123,27 +98,6 @@ class OverlayManager { ); } - bool _isRecentCompensationDuplicate(String key) { - _pruneRecentCompensationKeys(); - final recentTime = _recentCompensationKeys[key]; - if (recentTime == null) { - return false; - } - return DateTime.now().difference(recentTime) < _compensationDedupWindow; - } - - void _rememberCompensationKey(String key) { - _recentCompensationKeys[key] = DateTime.now(); - _pruneRecentCompensationKeys(); - } - - void _pruneRecentCompensationKeys() { - final now = DateTime.now(); - _recentCompensationKeys.removeWhere( - (_, time) => now.difference(time) > _compensationDedupWindow, - ); - } - bool _isRecentFloatingDuplicate(SCFloatingMessage message) { _pruneRecentFloatingKeys(); final key = _floatingDedupKeyFor(message); @@ -261,33 +215,6 @@ class OverlayManager { return _redPacketFloatingDedupWindow; } - String _compensationKeyFor(SCFloatingMessage message) { - return [ - message.type, - message.roomId, - message.userId, - message.toUserId, - message.giftId, - message.number, - message.giftUrl, - ].join('|'); - } - - void _trimLowPerformanceCompensationQueue() { - if (_messageQueue.length < _maxLowPerformanceCompensationQueueLength) { - return; - } - final retained = - _messageQueue.unorderedElements.cast().toList() - ..sort((a, b) => b.priority.compareTo(a.priority)); - _messageQueue.clear(); - for (final message in retained.take( - _maxLowPerformanceCompensationQueueLength - 1, - )) { - _messageQueue.add(message); - } - } - Future _warmMessageImages(SCFloatingMessage message) async { unawaited( warmImageResource( @@ -671,7 +598,7 @@ class OverlayManager { SCGlobalConfig.floatingBroadcastScope = scope; return; } - final defaultEffectsEnabled = !SCGlobalConfig.isLowPerformanceDevice; + const defaultEffectsEnabled = true; final isLegacyFloatingAnimationInGlobal = DataPersistence.getBool( SCGlobalConfig.legacyFloatingAnimationInGlobalStorageKey(account), defaultValue: defaultEffectsEnabled, @@ -752,7 +679,6 @@ class OverlayManager { _removeAllStackedMessages(); _messageQueue.clear(); _deferredRegionRedPacketMessages.clear(); - _recentCompensationKeys.clear(); _isPlaying = false; _isProcessing = false; } diff --git a/lib/shared/tools/sc_lucky_gift_win_sound_player.dart b/lib/shared/tools/sc_lucky_gift_win_sound_player.dart index baeb138..28fe3c6 100644 --- a/lib/shared/tools/sc_lucky_gift_win_sound_player.dart +++ b/lib/shared/tools/sc_lucky_gift_win_sound_player.dart @@ -1,14 +1,20 @@ +import 'dart:async'; + import 'package:audioplayers/audioplayers.dart'; import 'package:yumi/shared/data_sources/sources/local/data_persistence.dart'; class SCLuckyGiftWinSoundPlayer { static const String assetPath = "sc_images/room/anim/luck_gift/lucky_gift_win.mp3"; - static const Duration _sameEventDedupeWindow = Duration(seconds: 3); + static const Duration _stopDelay = Duration(milliseconds: 3200); + static const double _volume = 0.75; static final AudioPlayer _player = AudioPlayer(); - static String? _lastEventKey; - static DateTime? _lastPlayedAt; + static bool _loaded = false; + static bool _playing = false; + static Future? _loadFuture; + static Future? _startFuture; + static Timer? _stopTimer; static String buildEventKey({ String? giftId, @@ -26,25 +32,75 @@ class SCLuckyGiftWinSoundPlayer { static Future play({String? eventKey}) async { if (DataPersistence.getPlayGiftMusic()) { + unawaited(stop()); return; } - final normalizedEventKey = (eventKey ?? '').trim(); - final now = DateTime.now(); - final lastPlayedAt = _lastPlayedAt; - if (normalizedEventKey.isNotEmpty && - normalizedEventKey == _lastEventKey && - lastPlayedAt != null && - now.difference(lastPlayedAt) < _sameEventDedupeWindow) { - return; - } - - _lastEventKey = normalizedEventKey.isEmpty ? null : normalizedEventKey; - _lastPlayedAt = now; try { - await _player.stop(); - await _player.play(AssetSource(assetPath)); - } catch (error) {} + await _ensureLoaded(); + _extendStopWindow(); + + if (_playing || _startFuture != null) { + return; + } + + _startFuture = _startPlayback(); + await _startFuture; + } catch (error) { + _startFuture = null; + } + _startFuture = null; + } + + static Future stop() async { + _stopTimer?.cancel(); + _stopTimer = null; + try { + if (_player.state != PlayerState.stopped) { + await _player.stop(); + } + } catch (error) { + _playing = false; + return; + } + _playing = false; + } + + static Future _ensureLoaded() { + if (_loaded) { + return Future.value(); + } + final loadFuture = _loadFuture; + if (loadFuture != null) { + return loadFuture; + } + _loadFuture = _load(); + return _loadFuture!; + } + + static Future _load() async { + try { + await _player.setReleaseMode(ReleaseMode.loop); + await _player.setVolume(_volume); + await _player.setSource(AssetSource(assetPath)); + _loaded = true; + } catch (error) { + _loadFuture = null; + rethrow; + } + } + + static Future _startPlayback() async { + await _player.seek(Duration.zero); + await _player.resume(); + _playing = true; + } + + static void _extendStopWindow() { + _stopTimer?.cancel(); + _stopTimer = Timer(_stopDelay, () { + unawaited(stop()); + }); } static String _formatNum(num? value) { diff --git a/lib/shared/tools/sc_room_utils.dart b/lib/shared/tools/sc_room_utils.dart index 0f8244c..24b6447 100644 --- a/lib/shared/tools/sc_room_utils.dart +++ b/lib/shared/tools/sc_room_utils.dart @@ -288,7 +288,7 @@ class SCChatRoomHelper { } static void roomSCGlobalConfig(String roomId) { - final defaultEffectsEnabled = !SCGlobalConfig.isLowPerformanceDevice; + const defaultEffectsEnabled = true; final account = AccountStorage().getCurrentUser()?.userProfile?.account; SCGlobalConfig .isGiftSpecialEffects = SCGlobalConfig.clampVisualEffectPreference( diff --git a/lib/ui_kit/widgets/bag/props_bag_chatbox_detail_dialog.dart b/lib/ui_kit/widgets/bag/props_bag_chatbox_detail_dialog.dart index 1d44c88..fbe95fb 100644 --- a/lib/ui_kit/widgets/bag/props_bag_chatbox_detail_dialog.dart +++ b/lib/ui_kit/widgets/bag/props_bag_chatbox_detail_dialog.dart @@ -1,5 +1,3 @@ -import 'package:extended_image/extended_image.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_debouncer/flutter_debouncer.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -70,7 +68,11 @@ class _PropsBagChatboxDetailDialogState ], ), SizedBox(height: 25.w), - netImage(url: widget.res.propsResources?.cover??"",width: 80.w,height: 25.w), + netImage( + url: widget.res.propsResources?.cover ?? "", + width: 80.w, + height: 25.w, + ), SizedBox(height: 30.w), GestureDetector( child: Container( @@ -136,6 +138,11 @@ class _PropsBagChatboxDetailDialogState } void _use(BagsListRes res, bool unload) { + final localizations = SCAppLocalizations.of(context)!; + final profileManager = Provider.of( + context, + listen: false, + ); SCLoadingManager.show(); SCStoreRepositoryImp() .switchPropsUse( @@ -144,18 +151,25 @@ class _PropsBagChatboxDetailDialogState unload, ) .then((value) async { - await Provider.of( - context, - listen: false, - ).fetchUserProfileData(loadGuardCount: false); + try { + await profileManager.fetchUserProfileData(loadGuardCount: false); + } catch (_) {} + if (!mounted) { + SCLoadingManager.hide(); + return; + } + profileManager.syncCurrentUserChatBubble( + unload ? null : res.propsResources, + expireTime: res.expireTime?.toString(), + ); Future.delayed(Duration(milliseconds: 400), () { SCLoadingManager.hide(); SmartDialog.dismiss(tag: "showPropsDetail"); }); if (!unload) { - SCTts.show(SCAppLocalizations.of(context)!.successfulWear); + SCTts.show(localizations.successfulWear); } else { - SCTts.show(SCAppLocalizations.of(context)!.successfullyUnloaded); + SCTts.show(localizations.successfullyUnloaded); } }) .catchError((e) { diff --git a/lib/ui_kit/widgets/room/anim/room_entrance_screen.dart b/lib/ui_kit/widgets/room/anim/room_entrance_screen.dart index 39e4f10..9218637 100644 --- a/lib/ui_kit/widgets/room/anim/room_entrance_screen.dart +++ b/lib/ui_kit/widgets/room/anim/room_entrance_screen.dart @@ -65,10 +65,6 @@ class _RoomAnimationQueueScreenState extends State { } void _enqueueVipEntryFloatingMessage(Msg msg) { - if (SCGlobalConfig.isLowPerformanceDevice && - ((msg.user?.getMountains()?.sourceUrl ?? "").trim().isNotEmpty)) { - return; - } final floatPicture = msg.user?.getFloatPicture(); final floatPictureUrl = _resolveVipFloatPictureUrl(floatPicture); final floatPictureFallbackUrl = _resolveVipFloatPictureFallbackUrl( @@ -86,33 +82,16 @@ class _RoomAnimationQueueScreenState extends State { if (roomId.isEmpty) { return; } - final isLowPerformance = SCGlobalConfig.isLowPerformanceDevice; - final displayUrl = - isLowPerformance && floatPictureFallbackUrl.isNotEmpty - ? floatPictureFallbackUrl - : floatPictureUrl; final floatingMessage = SCFloatingMessage( type: 5, userId: msg.user?.id, roomId: roomId, userAvatarUrl: msg.user?.userAvatar, userName: msg.user?.userNickname, - giftUrl: displayUrl, + giftUrl: floatPictureUrl, fallbackUrl: floatPictureFallbackUrl, priority: 900, ); - if (isLowPerformance) { - OverlayManager().addLowPerformanceCompensationMessage( - floatingMessage, - dedupKey: [ - "entry_float", - roomId, - msg.user?.id ?? "", - floatPicture?.id ?? "", - ].join("|"), - ); - return; - } OverlayManager().addMessage(floatingMessage); } diff --git a/sc_images/room/anim/luck_gift/lucky_gift_win.mp3 b/sc_images/room/anim/luck_gift/lucky_gift_win.mp3 index 974ce34..44ea112 100644 Binary files a/sc_images/room/anim/luck_gift/lucky_gift_win.mp3 and b/sc_images/room/anim/luck_gift/lucky_gift_win.mp3 differ