diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 76d05b1..6ebc174 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -346,15 +346,15 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin" SPEC CHECKSUMS: - app_links: 585674be3c6661708e6cd794ab4f39fb9d8356f9 + app_links: 3dbc685f76b1693c66a6d9dd1e9ab6f73d97dc0a AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73 AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f - audioplayers_darwin: f15e209a3e856d1a7edcf98dc029f484fead2242 - device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d + audioplayers_darwin: 835ced6edd4c9fc8ebb0a7cc9e294a91d99917d5 + device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896 Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e - firebase_auth: 5342db41af2ba5ed32a6177d9e326eecbebda912 - firebase_core: 99a37263b3c27536063a7b601d9e2a49400a433c - firebase_crashlytics: 986773c0c7ea4c3f5a4ead141b58522fcd9dfdb1 + firebase_auth: 50af8366c87bb88c80ebeae62eb60189c7246b9b + firebase_core: 995454a784ff288be5689b796deb9e9fa3601818 + firebase_crashlytics: 30dcd6dfd2fe895c0848af46722a4227346c19aa FirebaseAppCheckInterop: 06fe5a3799278ae4667e6c432edd86b1030fa3df FirebaseAuth: a6575e5fbf46b046c58dc211a28a5fbdd8d4c83b FirebaseAuthInterop: 7087d7a4ee4bc4de019b2d0c240974ed5d89e2fd @@ -366,47 +366,47 @@ SPEC CHECKSUMS: FirebaseRemoteConfigInterop: 1c6135e8a094cc6368949f5faeeca7ee8948b8aa FirebaseSessions: b9a92c1c51bbb81e78fc3142cda6d925d700f8e7 Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 - flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e - fluttertoast: 21eecd6935e7064cc1fcb733a4c5a428f3f24f0f - google_sign_in_ios: 7411fab6948df90490dc4620ecbcabdc3ca04017 + flutter_image_compress_common: 1697a328fd72bfb335507c6bca1a65fa5ad87df1 + fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1 + google_sign_in_ios: b48bb9af78576358a168361173155596c845f0b9 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 GoogleSignIn: ce8c89bb9b37fb624b92e7514cc67335d1e277e4 GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1 GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6 HydraAsync: 8d589bd725b0224f899afafc9a396327405f8063 - image_cropper: a3291c624a953049bc6a02e1f8c8ceb162a24b25 - image_picker_ios: 4f2f91b01abdb52842a8e277617df877e40f905b - in_app_purchase_storekit: 2342c0a5da86593124d08dd13d920f39a52b273a + image_cropper: 655b3ba703c9e15e3111e79151624d6154288774 + image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326 + in_app_purchase_storekit: 22cca7d08eebca9babdf4d07d0baccb73325d3c8 libpag: 98742fad4b3ac2a2ee31e383d2483495fb9a5fb4 libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 - on_audio_query_ios: e5afb0d4b42cfa3e8762d8ec1953540cb4f02100 - package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - pag: ff30ba5e4be59380a5ddac6b183905729be15a3c - permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 + on_audio_query_ios: 28a780e2d0d85d92d500ba6e12c6c8167022b2fa + package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 + pag: f01aa9017ab0e04a83ba4a20d6070a50f0ac9da8 + permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851 RecaptchaInterop: 11e0b637842dfb48308d242afc3f448062325aba SDWebImage: e9fc87c1aab89a8ab1bbd74eba378c6f53be8abf SDWebImageWebPCoder: 0e06e365080397465cc73a7a9b472d8a3bd0f377 - shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6 - sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440 - sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d + shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb + sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418 + sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 SwiftyBeaver: 84069991dd5dca07d7069100985badaca7f0ce82 - tancent_vap: eceaaf095167d102727cf799c75891057834c311 - tencent_cloud_chat_sdk: 546bb906bbe585814e3d2d33afdb91f09c0eac44 - tencent_rtc_sdk: 1ca5201f7bddc691a3a95486325ad6dc792a273d + tancent_vap: fa8ad93814a9f950514a7074c662d2c937084c68 + tencent_cloud_chat_sdk: 55e5fffe20f6b7937a26a674ccccb639563a9790 + tencent_rtc_sdk: f77558b6b436a149d378557c2a837f73c09061bc TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863 TXCustomBeautyProcesserPlugin: 099393b941cb40eda12b3a80bf6c0319957b1cfd TXIMSDK_Plus_iOS_XCFramework: 5d1933192fb3b7ef2fe933f1623de4a0486a7fe2 TXLiteAVSDK_Professional: e792e6084a208ecef6196c5f28237ad8078b4d7c - url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa - video_player_avfoundation: e54d03b3b19f64f2c557354f72ce538387541ba6 - video_thumbnail: c4e2a3c539e247d4de13cd545344fd2d26ffafd1 - wakelock_plus: 76957ab028e12bfa4e66813c99e46637f367fc7e - webview_flutter_wkwebview: 29eb20d43355b48fe7d07113835b9128f84e3af4 + url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b + video_player_avfoundation: 3453f792138786248960ca029747fcd9f318ef52 + video_thumbnail: b637e0ad5f588ca9945f6e2c927f73a69a661140 + wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556 + webview_flutter_wkwebview: 8ebf4fded22593026f7dbff1fbff31ea98573c8d PODFILE CHECKSUM: a6f49a93e5f85201a2efdadcd7cf184b0e310894 diff --git a/lib/modules/gift/gift_page.dart b/lib/modules/gift/gift_page.dart index ccd86bf..eb74d7f 100644 --- a/lib/modules/gift/gift_page.dart +++ b/lib/modules/gift/gift_page.dart @@ -19,7 +19,6 @@ import 'package:yumi/shared/tools/sc_gift_vap_svga_manager.dart'; import 'package:yumi/shared/data_sources/sources/local/user_manager.dart'; import 'package:yumi/shared/data_sources/sources/remote/net/api.dart'; import 'package:yumi/shared/data_sources/sources/repositories/sc_room_repository_imp.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/tools/sc_cp_gift_relation_utils.dart'; import 'package:yumi/main.dart'; @@ -1520,8 +1519,6 @@ class _GiftPageState extends State with TickerProviderStateMixin { 'giftType=$giftType', ); - await _showCpGiftRelationCheckToastIfNeeded(request); - try { final repository = SCChatRoomRepository(); _giftFxLog( @@ -1728,49 +1725,6 @@ class _GiftPageState extends State with TickerProviderStateMixin { ); } - Future _showCpGiftRelationCheckToastIfNeeded( - _GiftSendRequest request, - ) async { - final relationType = request.cpRelationType; - if (relationType == null || relationType.trim().isEmpty) { - return; - } - final acceptUserId = request.acceptUserIds - .map((userId) => userId.trim()) - .firstWhere((userId) => userId.isNotEmpty, orElse: () => ''); - if (acceptUserId.isEmpty) { - return; - } - try { - final result = await SCAccountRepository().cpGiftRelationCheck( - acceptUserId: acceptUserId, - relationType: relationType, - ); - final message = result.msg.trim(); - _giftFxLog( - 'cp gift relation check ' - 'acceptUserId=$acceptUserId ' - 'relationType=$relationType ' - 'status=${result.status} ' - 'msg=$message ' - 'userCount=${result.userRelationCount}/${result.maxRelationCount} ' - 'acceptCount=${result.acceptUserRelationCount}/${result.maxRelationCount}', - ); - if (!result.status && - message.isNotEmpty && - message.toUpperCase() != 'OK') { - SCTts.show(message); - } - } catch (error) { - _giftFxLog( - 'cp gift relation check skipped ' - 'acceptUserId=$acceptUserId ' - 'relationType=$relationType ' - 'error=$error', - ); - } - } - Future> _giveBackpackGiftToRecipients( SCChatRoomRepository repository, _GiftSendRequest request, diff --git a/lib/modules/room/voice_room_page.dart b/lib/modules/room/voice_room_page.dart index 95a6390..6272115 100644 --- a/lib/modules/room/voice_room_page.dart +++ b/lib/modules/room/voice_room_page.dart @@ -7,7 +7,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:yumi/app_localizations.dart'; import 'package:yumi/app/constants/sc_global_config.dart'; -import 'package:yumi/main.dart' show modalRouteObserver; +import 'package:yumi/main.dart' show routeObserver; import 'package:yumi/ui_kit/components/sc_compontent.dart'; import 'package:yumi/services/audio/rtc_manager.dart'; import 'package:yumi/ui_kit/widgets/room/room_bottom_widget.dart'; @@ -83,7 +83,7 @@ class _VoiceRoomPageState extends State bool _roomProviderRebuildScheduled = false; bool _roomRouteVisibleScheduled = false; bool _roomVisualEffectsEnsureScheduled = false; - ModalRoute? _routeObserverRoute; + PageRoute? _routeObserverRoute; SCRoomTopLayerGuardLease? _coveredRouteGuardLease; bool _roomRouteVisible = false; @@ -91,9 +91,6 @@ class _VoiceRoomPageState extends State void initState() { super.initState(); _tabController = TabController(length: _chatTabCount, vsync: this); - SCRoomTopLayerGuard().activeListenable.addListener( - _handleRoomTopLayerGuardChanged, - ); _tabController.addListener(_handleTabChange); _subscription = eventBus.on().listen(( event, @@ -123,12 +120,12 @@ class _VoiceRoomPageState extends State context.read().attachRtcProvider(rtcProvider); } final route = ModalRoute.of(context); - if (route != null && _routeObserverRoute != route) { + if (route is PageRoute && _routeObserverRoute != route) { if (_routeObserverRoute != null) { - modalRouteObserver.unsubscribe(this); + routeObserver.unsubscribe(this); } _routeObserverRoute = route; - modalRouteObserver.subscribe(this, route); + routeObserver.subscribe(this, route); if (route.isCurrent) { _scheduleRoomRouteVisible(); } else { @@ -140,10 +137,7 @@ class _VoiceRoomPageState extends State @override void dispose() { - SCRoomTopLayerGuard().activeListenable.removeListener( - _handleRoomTopLayerGuardChanged, - ); - modalRouteObserver.unsubscribe(this); + routeObserver.unsubscribe(this); _routeObserverRoute = null; _releaseCoveredRouteGuard(); _setRoomRouteVisible(false); @@ -215,13 +209,6 @@ class _VoiceRoomPageState extends State _coveredRouteGuardLease = null; } - void _handleRoomTopLayerGuardChanged() { - if (!SCRoomTopLayerGuard().isActive || !mounted) { - return; - } - _clearTransientRoomVisualEffects(reason: 'room_top_layer_guard'); - } - void _setRoomRouteVisible(bool visible) { if (_roomRouteVisible == visible) { return; diff --git a/lib/modules/user/profile/person_detail_page.dart b/lib/modules/user/profile/person_detail_page.dart index afd92bd..1dbc1a8 100644 --- a/lib/modules/user/profile/person_detail_page.dart +++ b/lib/modules/user/profile/person_detail_page.dart @@ -1588,7 +1588,7 @@ class _PersonDetailPageState extends State with RouteAware { if (payload.rightUserId.trim().isEmpty) { return; } - const cancelText = 'unbing'; + const cancelText = 'unbind'; SCLoadingManager.show(context: context); late final _ProfileRelationProgressData progress; try { @@ -1629,7 +1629,10 @@ class _PersonDetailPageState extends State with RouteAware { Future<_ProfileRelationProgressData> _loadProfileRelationProgressData( _ProfileRelationProgressPayload payload, ) async { - final partnerUserId = payload.rightUserId.trim(); + final partnerUserId = _counterpartUserIdForCurrentUser( + leftUserId: payload.leftUserId, + rightUserId: payload.rightUserId, + ); final fallback = _ProfileRelationProgressData.fallback(payload); if (partnerUserId.isEmpty) { return fallback; @@ -1666,11 +1669,34 @@ class _PersonDetailPageState extends State with RouteAware { } } + String _counterpartUserIdForCurrentUser({ + required String leftUserId, + required String rightUserId, + }) { + final currentUserId = + AccountStorage().getCurrentUser()?.userProfile?.id?.trim() ?? ""; + final leftId = leftUserId.trim(); + final rightId = rightUserId.trim(); + if (currentUserId.isEmpty) { + return rightId; + } + if (currentUserId == leftId) { + return rightId; + } + if (currentUserId == rightId) { + return leftId; + } + return rightId; + } + Future _showProfileRelationDismissConfirm( _ProfileRelationProgressPayload payload, { int? dismissCost, }) async { - final partnerUserId = payload.rightUserId.trim(); + final partnerUserId = _counterpartUserIdForCurrentUser( + leftUserId: payload.leftUserId, + rightUserId: payload.rightUserId, + ); if (partnerUserId.isEmpty) { return; } diff --git a/lib/services/audio/rtc_manager.dart b/lib/services/audio/rtc_manager.dart index c5495a4..55e052c 100644 --- a/lib/services/audio/rtc_manager.dart +++ b/lib/services/audio/rtc_manager.dart @@ -544,10 +544,7 @@ class RealTimeCommunicationManager extends ChangeNotifier { int? get previewRoomSeatCount => _previewRoomSeatCount; bool get shouldShowRoomVisualEffects => - currenRoom != null && - _roomVisualEffectsEnabled && - _voiceRoomRouteVisible && - !SCRoomTopLayerGuard().isActive; + currenRoom != null && _roomVisualEffectsEnabled && _voiceRoomRouteVisible; void _startVoiceRoomForegroundService() { final roomProfile = currenRoom?.roomProfile?.roomProfile; diff --git a/lib/services/audio/rtm_manager.dart b/lib/services/audio/rtm_manager.dart index d7b1b44..b7fcfb3 100644 --- a/lib/services/audio/rtm_manager.dart +++ b/lib/services/audio/rtm_manager.dart @@ -3100,7 +3100,10 @@ class RealTimeMessagingManager extends ChangeNotifier { } } - void _enqueueCpRelationBroadcastFloatingIfNeeded(Msg msg) { + void _enqueueCpRelationBroadcastFloatingIfNeeded( + Msg msg, { + bool isRegionBroadcast = false, + }) { if (msg.type != SCRoomMsgType.cpSystemNotice) { return; } @@ -3108,8 +3111,7 @@ class RealTimeMessagingManager extends ChangeNotifier { if (action != "RELATION_ESTABLISHED" && action != "RELATION_JOINED_ROOM") { return; } - if (!_isLiveCpRelationBroadcastMessage(msg) || - !_shouldShowCpRelationBroadcastFloating(msg.groupId ?? "")) { + if (!_isLiveCpRelationBroadcastMessage(msg)) { return; } final relationType = scNormalizeCpRelationType(msg.role); @@ -3132,6 +3134,8 @@ class RealTimeMessagingManager extends ChangeNotifier { giftTab: relationType, displayText: msg.msg ?? "", durationSeconds: 5, + broadcastScope: + isRegionBroadcast ? SCFloatingMessage.broadcastScopeRegion : '', ), ); } @@ -3187,23 +3191,6 @@ class RealTimeMessagingManager extends ChangeNotifier { return DateTime.now().millisecondsSinceEpoch - timestamp < 60000; } - bool _shouldShowCpRelationBroadcastFloating(String groupId) { - final normalizedGroupId = groupId.trim(); - final currentContext = context; - if (normalizedGroupId.isEmpty || - currentContext == null || - !currentContext.mounted || - !_isCurrentVoiceRoomGroup(normalizedGroupId)) { - return false; - } - final rtcProvider = Provider.of( - currentContext, - listen: false, - ); - return rtcProvider.shouldShowRoomVisualEffects && - rtcProvider.isVoiceRoomRouteVisible; - } - String _roomMsgUserId(SocialChatUserProfile? profile) { return _firstCpInviteValue([profile?.id, profile?.account]) ?? ""; } @@ -6044,6 +6031,34 @@ class RealTimeMessagingManager extends ChangeNotifier { if (isRegionBroadcastGroup) { _handleRegionGiftBroadcast(data["data"]); } + } else if (type == SCRoomMsgType.cpSystemNotice) { + final payload = data["data"] ?? data; + final payloadMap = _broadcastPayloadMap(payload); + if (payloadMap.isEmpty) { + return; + } + final msg = Msg.fromJson(payloadMap); + msg.type ??= SCRoomMsgType.cpSystemNotice; + msg.groupId = _firstNonBlank([ + msg.groupId, + _payloadText(payloadMap["groupId"]), + _payloadText(payloadMap["roomId"]), + _payloadText(data["groupId"]), + _payloadText(data["roomId"]), + ]); + msg.noticeAction ??= data["noticeAction"]?.toString(); + if ((msg.role ?? "").trim().isEmpty) { + msg.role = _firstNonBlank([ + _payloadText(payloadMap["role"]), + _payloadText(payloadMap["relationType"]), + _payloadText(data["role"]), + _payloadText(data["relationType"]), + ]); + } + _enqueueCpRelationBroadcastFloatingIfNeeded( + msg, + isRegionBroadcast: isRegionBroadcastGroup, + ); } else if (type == SCRoomMsgType.inviteRoom) { ///邀请进入房间 var fdata = data["data"]; diff --git a/lib/services/auth/user_profile_manager.dart b/lib/services/auth/user_profile_manager.dart index 25ca1dd..add84ed 100644 --- a/lib/services/auth/user_profile_manager.dart +++ b/lib/services/auth/user_profile_manager.dart @@ -631,10 +631,7 @@ class SocialChatUserProfileManager extends ChangeNotifier { required String relationType, String? fallbackText, }) async { - if (!_isCurrentUserId(userId)) { - return null; - } - final partnerUserId = _cpPartnerUserId(userId, cpPair); + final partnerUserId = _cpPartnerUserIdForCurrentUser(cpPair); if (partnerUserId.isEmpty) { return null; } @@ -659,14 +656,21 @@ class SocialChatUserProfileManager extends ChangeNotifier { } } - String _cpPartnerUserId(String userId, CPRes cpPair) { - final currentId = userId.trim(); + String _cpPartnerUserIdForCurrentUser(CPRes cpPair) { + final currentUserId = + AccountStorage().getCurrentUser()?.userProfile?.id?.trim() ?? ""; + if (currentUserId.isEmpty) { + return ""; + } final meUserId = cpPair.meUserId?.trim() ?? ""; final cpUserId = cpPair.cpUserId?.trim() ?? ""; - if (currentId.isNotEmpty && currentId == cpUserId) { + if (currentUserId == meUserId) { + return cpUserId; + } + if (currentUserId == cpUserId) { return meUserId; } - return cpUserId; + return ""; } bool _hasCpPair(CPRes? pair) { 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 28d1a20..0de5dc8 100644 --- a/lib/shared/data_sources/sources/local/floating_screen_manager.dart +++ b/lib/shared/data_sources/sources/local/floating_screen_manager.dart @@ -803,10 +803,22 @@ class OverlayManager { return message.type == 2 && message.isRegionBroadcast; } + bool _isRegionCpGiftMessage(SCFloatingMessage message) { + return message.type == 1 && + message.isRegionBroadcast && + scIsCpGiftTab(message.giftTab); + } + + bool _isRegionCpRelationMessage(SCFloatingMessage message) { + return message.type == 6 && message.isRegionBroadcast; + } + bool _isCrossRoomRegionFloatingMessage(SCFloatingMessage message) { return _isRegionRedPacketMessage(message) || _isRegionRoomRocketMessage(message) || - _isRegionGameWinMessage(message); + _isRegionGameWinMessage(message) || + _isRegionCpGiftMessage(message) || + _isRegionCpRelationMessage(message); } bool _shouldDeferRegionRedPacketMessage( @@ -931,15 +943,20 @@ class OverlayManager { currentRoomId.isNotEmpty && messageRoomId.isNotEmpty && currentRoomId == messageRoomId; + final isGlobalStackedBroadcast = + message.type == 4 || + message.type == 3 || + message.type == 6 || + _isRegionCpGiftMessage(message); if (isCurrentVisibleRoom) { - // 区域红包/火箭在当前房间仍然需要展示;区域礼物当前房间由 RTM 层跳过,避免和房间 IM 礼物飘屏重复。 - return message.type == 4 || message.type == 3 || message.type == 2; + // 区域红包/火箭/CP 类飘窗在当前房间仍然需要展示;普通区域礼物当前房间由 RTM 层跳过,避免和房间 IM 礼物飘屏重复。 + return isGlobalStackedBroadcast || message.type == 2; } final isCurrentRoomMessage = currentRoomId.isNotEmpty && messageRoomId.isNotEmpty && currentRoomId == messageRoomId; - if ((message.type == 4 || message.type == 3 || message.type == 2) && + if ((isGlobalStackedBroadcast || message.type == 2) && isCurrentRoomMessage) { return false; } @@ -952,11 +969,10 @@ class OverlayManager { } return SCGlobalConfig.isFloatingBroadcastAll && _homeRootTabsVisible; } - if ((message.type == 4 || message.type == 3) && - rtcProvider.shouldShowRoomVisualEffects) { + if (isGlobalStackedBroadcast && rtcProvider.shouldShowRoomVisualEffects) { return true; } - if (message.type == 4 || message.type == 3) { + if (isGlobalStackedBroadcast) { return _homeRootTabsVisible; } if (SCGlobalConfig.isFloatingBroadcastRoomOnly) { diff --git a/lib/shared/data_sources/sources/repositories/sc_user_repository_impl.dart b/lib/shared/data_sources/sources/repositories/sc_user_repository_impl.dart index 5186700..0137aa1 100644 --- a/lib/shared/data_sources/sources/repositories/sc_user_repository_impl.dart +++ b/lib/shared/data_sources/sources/repositories/sc_user_repository_impl.dart @@ -1524,25 +1524,12 @@ class SCAccountRepository implements SocialChatUserRepository { String relationType = 'CP', }) async { final query = {"acceptUserId": acceptUserId, "relationType": relationType}; - _cpDebugLog('giftRelationCheck request query=$query'); - try { - final result = await http.get( - "/user/cp-relationship/gift-relation/check", - queryParams: query, - extra: const {BaseNetworkClient.silentErrorToastKey: true}, - fromJson: SCCpGiftRelationCheckRes.fromJson, - ); - _cpDebugLog( - 'giftRelationCheck response query=$query ' - 'status=${result.status} msg=${result.msg} ' - 'userFull=${result.userRelationFull} ' - 'acceptFull=${result.acceptUserRelationFull}', - ); - return result; - } catch (error) { - _cpDebugLog('giftRelationCheck failed query=$query error=$error'); - rethrow; - } + return http.get( + "/user/cp-relationship/gift-relation/check", + queryParams: query, + extra: const {BaseNetworkClient.silentErrorToastKey: true}, + fromJson: SCCpGiftRelationCheckRes.fromJson, + ); } ///user/cp/cabin diff --git a/lib/shared/tools/sc_room_top_layer_guard.dart b/lib/shared/tools/sc_room_top_layer_guard.dart index e926b9e..6fcf9f1 100644 --- a/lib/shared/tools/sc_room_top_layer_guard.dart +++ b/lib/shared/tools/sc_room_top_layer_guard.dart @@ -5,9 +5,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.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'; class SCRoomTopLayerGuard { static const int _maxDeferredActions = 16; @@ -56,11 +53,6 @@ class SCRoomTopLayerGuard { } _activeListenable.value = true; OverlayManager().beginSuppressFloatingScreens(reason: reason); - SCRoomEffectScheduler().beginSuppressEffects(reason: reason); - SCRoomEffectScheduler().clearDeferredTasks(reason: reason); - RoomEntranceHelper.clearQueue(); - SCGiftVapSvgaManager().stopPlayback(); - SCGiftVapSvgaManager().pauseAnim(); if (!keepDialogTags.contains(_redPacketOpenDialogTag)) { unawaited(SmartDialog.dismiss(tag: _redPacketOpenDialogTag)); } @@ -81,8 +73,6 @@ class SCRoomTopLayerGuard { return; } OverlayManager().endSuppressFloatingScreens(reason: reason); - SCRoomEffectScheduler().endSuppressEffects(reason: reason); - SCGiftVapSvgaManager().resumeAnim(); _activeListenable.value = false; _drainDeferredActions(); } diff --git a/lib/ui_kit/widgets/room/cp/room_cp_progress_dialog.dart b/lib/ui_kit/widgets/room/cp/room_cp_progress_dialog.dart index a8934a3..1f526a5 100644 --- a/lib/ui_kit/widgets/room/cp/room_cp_progress_dialog.dart +++ b/lib/ui_kit/widgets/room/cp/room_cp_progress_dialog.dart @@ -37,7 +37,7 @@ class RoomCpProgressDialog extends StatelessWidget { this.targetValue = 1, this.expAwayText = '0', this.nextLevelText = 'Lv. 1', - this.cancelText = 'unbing', + this.cancelText = 'unbind', this.dismissTag = dialogTag, this.onCancel, }); @@ -68,7 +68,7 @@ class RoomCpProgressDialog extends StatelessWidget { double targetValue = 1, String expAwayText = '0', String nextLevelText = 'Lv. 1', - String cancelText = 'unbing', + String cancelText = 'unbind', String dismissTag = dialogTag, VoidCallback? onCancel, }) async { @@ -495,7 +495,7 @@ class _CancelButton extends StatelessWidget { fit: BoxFit.fill, ), Text( - text.trim().isEmpty ? 'unbing' : text.trim(), + text.trim().isEmpty ? 'unbind' : text.trim(), maxLines: 1, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, diff --git a/lib/ui_kit/widgets/room/floating/floating_cp_relation_screen_widget.dart b/lib/ui_kit/widgets/room/floating/floating_cp_relation_screen_widget.dart index 9c80fdf..6b74083 100644 --- a/lib/ui_kit/widgets/room/floating/floating_cp_relation_screen_widget.dart +++ b/lib/ui_kit/widgets/room/floating/floating_cp_relation_screen_widget.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:yumi/shared/data_sources/models/message/sc_floating_message.dart'; @@ -157,7 +159,7 @@ class _FloatingCpRelationScreenWidgetState } final explicitText = widget.message.displayText?.trim() ?? ""; if (explicitText.isNotEmpty) { - return _stripSystemNotificationPrefix(explicitText); + return _stripSystemNotificationPrefix(_repairMojibake(explicitText)); } return _stripSystemNotificationPrefix( scBuildCpRelationEstablishedNotice( @@ -169,7 +171,7 @@ class _FloatingCpRelationScreenWidgetState } String _shortName(String? value) { - final text = value?.trim() ?? ""; + final text = _repairMojibake(value?.trim() ?? ""); if (text.length <= 14) { return text; } @@ -188,7 +190,7 @@ class _FloatingCpRelationScreenWidgetState } String _stripSystemNotificationPrefix(String text) { - return text + return _repairMojibake(text) .replaceFirst( RegExp( r'^\s*[\[\【]\s*sys(?:tem|term)\s+notification\s*[\]\】]\s*', @@ -199,6 +201,35 @@ class _FloatingCpRelationScreenWidgetState .trim(); } + String _repairMojibake(String value) { + final text = value.trim(); + if (text.isEmpty || !_looksLikeMojibake(text)) { + return text; + } + try { + final repaired = utf8.decode(latin1.encode(text), allowMalformed: true); + return _mojibakeScore(repaired) < _mojibakeScore(text) ? repaired : text; + } catch (_) { + return text; + } + } + + bool _looksLikeMojibake(String value) { + return value.contains('Ã') || + value.contains('Â') || + value.contains('â') || + value.contains('ð') || + value.contains('�'); + } + + int _mojibakeScore(String value) { + var score = 0; + for (final marker in const ['Ã', 'Â', 'â', 'ð', '�']) { + score += marker.allMatches(value).length; + } + return score; + } + List _relationColors(String? relationType) { switch (scNormalizeCpRelationType(relationType)) { case "BROTHER": diff --git a/lib/ui_kit/widgets/room/room_user_info_card.dart b/lib/ui_kit/widgets/room/room_user_info_card.dart index 687d202..3129d86 100644 --- a/lib/ui_kit/widgets/room/room_user_info_card.dart +++ b/lib/ui_kit/widgets/room/room_user_info_card.dart @@ -612,16 +612,16 @@ class _RoomUserInfoCardState extends State { ) { return SizedBox( width: double.infinity, - height: 16.w, + height: 20.w, child: Center( child: SCUserBadgeStrip( userId: userId, fallbackBadges: _roomCardFallbackBadges(ref, profile), displayScope: SCUserBadgeDisplayScope.short, - height: 16.w, - badgeHeight: 16.w, - longBadgeWidth: 32.w, - spacing: 4.w, + height: 20.w, + badgeHeight: 20.w, + longBadgeWidth: 44.w, + spacing: 5.w, maxBadges: 3, wrap: false, reserveSpace: false, @@ -1633,7 +1633,7 @@ class _RoomUserInfoCardState extends State { SocialChatUserProfile? profile, ) async { final cp = _cpProfileData(profile); - const cancelText = 'unbing'; + const cancelText = 'unbind'; SCLoadingManager.show(); late final _RoomCpProgressData progress; try { @@ -1673,7 +1673,10 @@ class _RoomUserInfoCardState extends State { } Future<_RoomCpProgressData> _loadCpProgressData(_RoomProfileCpData cp) async { - final partnerUserId = cp.rightUserId.trim(); + final partnerUserId = _counterpartUserIdForCurrentUser( + leftUserId: cp.leftUserId, + rightUserId: cp.rightUserId, + ); final fallback = _RoomCpProgressData.fallback(cp); if (partnerUserId.isEmpty) { return fallback; @@ -1707,13 +1710,36 @@ class _RoomUserInfoCardState extends State { } } + String _counterpartUserIdForCurrentUser({ + required String leftUserId, + required String rightUserId, + }) { + final currentUserId = + AccountStorage().getCurrentUser()?.userProfile?.id?.trim() ?? ""; + final leftId = leftUserId.trim(); + final rightId = rightUserId.trim(); + if (currentUserId.isEmpty) { + return rightId; + } + if (currentUserId == leftId) { + return rightId; + } + if (currentUserId == rightId) { + return leftId; + } + return rightId; + } + Future _showCpDismissConfirm( BuildContext context, _RoomProfileCpData cp, { int? dismissCost, }) async { final l10n = SCAppLocalizations.of(context)!; - final partnerUserId = cp.rightUserId.trim(); + final partnerUserId = _counterpartUserIdForCurrentUser( + leftUserId: cp.leftUserId, + rightUserId: cp.rightUserId, + ); if (partnerUserId.isEmpty) { return; }