From f025c182115eebb1bf362c618071fa30e78afff4 Mon Sep 17 00:00:00 2001 From: zhx Date: Sat, 23 May 2026 20:09:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/modules/chat/message_chat_page.dart | 13 +-- lib/modules/gift/gift_page.dart | 57 +++++++++++ lib/services/audio/rtm_manager.dart | 122 ++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 8 deletions(-) diff --git a/lib/modules/chat/message_chat_page.dart b/lib/modules/chat/message_chat_page.dart index b588a49..6257849 100644 --- a/lib/modules/chat/message_chat_page.dart +++ b/lib/modules/chat/message_chat_page.dart @@ -1226,7 +1226,7 @@ class _MessageItem extends StatelessWidget { } final customData = _customDataFromMessage(message); if (customData != null && - _isDuplicateCpResultMessageForConversation(customData)) { + _isDuplicateCpInviteMessageForConversation(customData)) { return const SizedBox.shrink(); } final cpRelationFormedCard = _cpRelationFormedMessageCard(); @@ -2007,8 +2007,8 @@ class _MessageItem extends StatelessWidget { return _CpInviteMessageState.pending; } - bool _isDuplicateCpResultMessageForConversation(Map data) { - final currentKey = _cpResultMessageDedupKey(data); + bool _isDuplicateCpInviteMessageForConversation(Map data) { + final currentKey = _cpInviteMessageDedupKey(data); if (currentKey.isEmpty) { return false; } @@ -2025,7 +2025,7 @@ class _MessageItem extends StatelessWidget { if (otherData == null) { continue; } - if (_cpResultMessageDedupKey(otherData) == currentKey) { + if (_cpInviteMessageDedupKey(otherData) == currentKey) { return true; } } @@ -2046,14 +2046,11 @@ class _MessageItem extends StatelessWidget { return identical(item, message); } - String _cpResultMessageDedupKey(Map data) { + String _cpInviteMessageDedupKey(Map data) { if (!_isCpInvitePayload(data)) { return ""; } final state = _cpInviteStateFromData(data); - if (state == _CpInviteMessageState.pending) { - return ""; - } final applyId = _cpApplyIdFromData(data); if (applyId.isEmpty) { return ""; diff --git a/lib/modules/gift/gift_page.dart b/lib/modules/gift/gift_page.dart index caf02c0..4a73946 100644 --- a/lib/modules/gift/gift_page.dart +++ b/lib/modules/gift/gift_page.dart @@ -1550,6 +1550,7 @@ class _GiftPageState extends State with TickerProviderStateMixin { 'roomId=${request.roomId} ' 'elapsedMs=${stopwatch.elapsedMilliseconds}', ); + _showLocalCpInviteWaitingAfterGift(request, sentUsers); if (sentUsers.isNotEmpty) { final giftBatchId = _createGiftBatchId(request); sendGiftMsg( @@ -1598,6 +1599,7 @@ class _GiftPageState extends State with TickerProviderStateMixin { 'balance=$result ' 'elapsedMs=${stopwatch.elapsedMilliseconds}', ); + _showLocalCpInviteWaitingAfterGift(request, request.acceptUsers); if (request.isLuckyGiftRequest) { final giftBatchId = _createGiftBatchId(request); _showLocalLuckyGiftFeedback( @@ -1668,6 +1670,61 @@ class _GiftPageState extends State with TickerProviderStateMixin { unawaited(profileManager?.refreshLoadedCpProfiles()); } + void _showLocalCpInviteWaitingAfterGift( + _GiftSendRequest request, + List sentUsers, + ) { + if (!_isCpGift(request.gift)) { + return; + } + final relationType = request.cpRelationType; + if (relationType == null || relationType.trim().isEmpty) { + _giftFxLog( + 'local cp waiting skipped reason=no_relation_type ' + 'giftId=${request.gift.id} acceptUserIds=${request.acceptUserIds}', + ); + return; + } + if (sentUsers.isEmpty) { + _giftFxLog( + 'local cp waiting skipped reason=no_sent_users ' + 'giftId=${request.gift.id} relationType=$relationType', + ); + return; + } + final receiverProfile = sentUsers.first.user; + if (receiverProfile == null) { + _giftFxLog( + 'local cp waiting skipped reason=no_receiver_profile ' + 'giftId=${request.gift.id} relationType=$relationType', + ); + return; + } + final context = navigatorKey.currentState?.context; + if (context == null) { + _giftFxLog( + 'local cp waiting skipped reason=no_context ' + 'giftId=${request.gift.id} relationType=$relationType', + ); + return; + } + _giftFxLog( + 'local cp waiting trigger ' + 'giftId=${request.gift.id} ' + 'relationType=$relationType ' + 'receiverId=${receiverProfile.id}', + ); + unawaited( + Provider.of( + context, + listen: false, + ).showLocalCpGiftInviteWaiting( + receiverProfile: receiverProfile, + relationType: relationType, + ), + ); + } + Future> _giveBackpackGiftToRecipients( SCChatRoomRepository repository, _GiftSendRequest request, diff --git a/lib/services/audio/rtm_manager.dart b/lib/services/audio/rtm_manager.dart index f8933d5..97cf0c8 100644 --- a/lib/services/audio/rtm_manager.dart +++ b/lib/services/audio/rtm_manager.dart @@ -1013,6 +1013,128 @@ class RealTimeMessagingManager extends ChangeNotifier { return faceUrl.isNotEmpty ? faceUrl : conversation.faceUrl; } + Future showLocalCpGiftInviteWaiting({ + required SocialChatUserProfile? receiverProfile, + required String? relationType, + }) async { + final normalizedRelationType = scNormalizeCpRelationType(relationType); + final receiver = receiverProfile; + final receiverId = receiver?.id?.trim() ?? ""; + if (receiver == null || receiverId.isEmpty) { + _cpInviteLog( + 'skip local gift waiting reason=missing_receiver ' + 'relationType=$normalizedRelationType', + ); + return; + } + + final currentProfile = AccountStorage().getCurrentUser()?.userProfile; + if (currentProfile == null) { + _cpInviteLog( + 'skip local gift waiting reason=no_current_user ' + 'receiverId=$receiverId relationType=$normalizedRelationType', + ); + return; + } + final currentIds = _cpInviteProfileIdentityValues(currentProfile); + final receiverIds = _cpInviteProfileIdentityValues(receiver); + if (currentIds.any(receiverIds.contains)) { + _cpInviteLog( + 'skip local gift waiting reason=self_recipient ' + 'receiverId=$receiverId relationType=$normalizedRelationType', + ); + return; + } + + final applyId = await _latestCpGiftApplyId( + receiverId, + relationType: normalizedRelationType, + ); + if (applyId == null || applyId.isEmpty) { + _cpInviteLog( + 'skip local gift waiting reason=no_waiting_apply ' + 'receiverId=$receiverId relationType=$normalizedRelationType', + ); + return; + } + if (!await _isCpInviteApplyWaitingForAutoPopup(applyId)) { + return; + } + if (!_shownCpInviteMessageKeys.add(applyId)) { + _cpInviteLog( + 'skip duplicated local gift waiting applyId=$applyId ' + 'receiverId=$receiverId relationType=$normalizedRelationType', + ); + return; + } + + final context = navigatorKey.currentState?.context; + if (context == null || !context.mounted) { + _cpInviteLog( + 'skip local gift waiting reason=no_context ' + 'applyId=$applyId receiverId=$receiverId', + ); + return; + } + + final currentName = _cpInviteDisplayName( + nickname: currentProfile.userNickname, + account: currentProfile.account, + fallback: currentProfile.id, + ); + final receiverName = _cpInviteDisplayName( + nickname: receiver.userNickname, + account: receiver.account, + fallback: receiverId, + ); + _cpInviteLog( + 'show local gift waiting applyId=$applyId ' + 'receiverId=$receiverId relationType=$normalizedRelationType', + ); + await RoomCpInviteDialog.show( + context, + inviter: RoomCpInviteDialogUser( + name: currentName, + avatarUrl: currentProfile.userAvatar ?? "", + headdress: currentProfile.getHeaddress()?.sourceUrl ?? "", + headdressCover: currentProfile.getHeaddress()?.cover ?? "", + ), + receiver: RoomCpInviteDialogUser( + name: receiverName, + avatarUrl: receiver.userAvatar ?? "", + headdress: receiver.getHeaddress()?.sourceUrl ?? "", + headdressCover: receiver.getHeaddress()?.cover ?? "", + ), + style: RoomCpInviteDialogStyle.waiting, + countdownSeconds: 86399, + descriptionText: _cpInviteWaitingDescriptionText(normalizedRelationType), + onClose: () { + _cpInviteLog('close local gift waiting applyId=$applyId'); + }, + onTimeout: () { + _cpInviteLog('timeout local gift waiting applyId=$applyId'); + }, + ); + } + + Future _latestCpGiftApplyId( + String receiverId, { + required String relationType, + }) async { + try { + return await SCAccountRepository().cpRelationshipApplyId( + receiverId, + relationType: relationType, + ); + } catch (error) { + _cpInviteLog( + 'query local gift apply failed receiverId=$receiverId ' + 'relationType=$relationType error=$error', + ); + return null; + } + } + Future _handleIncomingCpBuildMessage(V2TimMessage? message) async { final data = _decodeCpSystemMessageData(message); if (data == null) {