修复卡片

This commit is contained in:
zhx 2026-05-25 20:57:28 +08:00
parent a73e2ff14b
commit 07624ac105
2 changed files with 91 additions and 18 deletions

View File

@ -1252,8 +1252,11 @@ class _MessageItem extends StatelessWidget {
}
final isCpInviteMessage =
customData != null && _isCpInvitePayload(customData);
final isExplicitCpResultMessage =
isCpInviteMessage &&
_cpInviteStateFromData(customData) != _CpInviteMessageState.pending;
final cpRelationFormedCard =
isCpInviteMessage ? null : _cpRelationFormedMessageCard();
isExplicitCpResultMessage ? _cpRelationFormedMessageCard() : null;
final cpStatusLineText = _cpStatusLineTextForMessage();
return Container(
margin: EdgeInsets.symmetric(horizontal: 15.w, vertical: 8.w),
@ -1307,7 +1310,8 @@ class _MessageItem extends StatelessWidget {
),
child: cpRelationFormedCard,
)
else if (cpStatusLineText == null || isCpInviteMessage)
else if (cpStatusLineText == null ||
(isCpInviteMessage && !isExplicitCpResultMessage))
Padding(
padding: EdgeInsets.only(
top: cpStatusLineText == null ? 0 : 10.w,
@ -1566,7 +1570,7 @@ class _MessageItem extends StatelessWidget {
if (data == null || !_isCpInvitePayload(data)) {
return null;
}
if (_cpInviteStateForMessage(data) != _CpInviteMessageState.accepted) {
if (_cpInviteStateFromData(data) != _CpInviteMessageState.accepted) {
return null;
}
final cpInvite = _cpInviteFromMessageData(data);
@ -1714,7 +1718,7 @@ class _MessageItem extends StatelessWidget {
final localizations = SCAppLocalizations.of(context)!;
final relationType = _cpRelationTypeFromMessageData(data);
if (state == _CpInviteMessageState.accepted) {
return _cpAcceptedStatusLineText(relationType);
return null;
}
if (state == _CpInviteMessageState.expired) {
if (relationType != "CP") {
@ -1733,19 +1737,34 @@ class _MessageItem extends StatelessWidget {
: "You declined the other party's $relationLabel invitation.";
}
String _cpAcceptedStatusLineText(String relationType) {
final localizations = SCAppLocalizations.of(context)!;
switch (scNormalizeCpRelationType(relationType)) {
case "BROTHER":
return "Have become sworn brothers";
case "SISTERS":
return "Have become sisters";
case "CP":
default:
return localizations.closeFriendsHaveBecome;
String? _cpInviteDialogStatusText(
Map<String, dynamic> data,
RoomCpInviteActionState actionState,
) {
switch (actionState) {
case RoomCpInviteActionState.rejected:
return _cpRejectedStatusText(data);
case RoomCpInviteActionState.expired:
case RoomCpInviteActionState.accepted:
case RoomCpInviteActionState.pending:
return null;
}
}
String _cpRejectedStatusText(Map<String, dynamic> data) {
final localizations = SCAppLocalizations.of(context)!;
final relationType = _cpRelationTypeFromMessageData(data);
if (relationType == "CP") {
return _isCurrentUserCpInviter(data)
? localizations.otherDeclinedCloseFriendInvite
: localizations.youDeclinedCloseFriendInvite;
}
final relationLabel = scCpRelationPossessiveLabel(relationType);
return _isCurrentUserCpInviter(data)
? "The other party declined your $relationLabel invitation."
: "You declined the other party's $relationLabel invitation.";
}
void _showCpInviteDialogFromMessage(
Map<String, dynamic> data,
SCSystemInvitMessageRes? cpInvite,
@ -1896,6 +1915,7 @@ class _MessageItem extends StatelessWidget {
actionState: effectiveActionState,
countdownSeconds: _cpInviteSecondsLeft(data),
descriptionText: _cpInviteDescriptionText(relationType),
statusText: _cpInviteDialogStatusText(data, effectiveActionState),
onAccept:
!isInviter &&
cpInvite != null &&
@ -2097,22 +2117,64 @@ class _MessageItem extends StatelessWidget {
return currentState;
}
final currentTimestamp = message.timestamp ?? 0;
var hasAcceptedSiblingInvite = false;
for (final item in currentConversationMessageList) {
if ((item.timestamp ?? 0) < currentTimestamp) {
continue;
}
final data = _customDataFromMessage(item);
if (data == null || _cpApplyIdFromData(data) != applyId) {
if (data == null || !_isCpInvitePayload(data)) {
continue;
}
final state = _cpInviteStateFromData(data);
if (state != _CpInviteMessageState.pending) {
return state;
final itemApplyId = _cpApplyIdFromData(data);
if (itemApplyId == applyId) {
if (state != _CpInviteMessageState.pending) {
return state;
}
continue;
}
if (state == _CpInviteMessageState.accepted &&
_isSameCpInvitePair(currentData, data)) {
hasAcceptedSiblingInvite = true;
}
}
if (hasAcceptedSiblingInvite) {
return _CpInviteMessageState.rejected;
}
return _CpInviteMessageState.pending;
}
bool _isSameCpInvitePair(
Map<String, dynamic> left,
Map<String, dynamic> right,
) {
final leftInviterIds = _cpInviteInviterIdentityValues(left);
final leftReceiverIds = _cpInviteReceiverIdentityValues(left);
final rightInviterIds = _cpInviteInviterIdentityValues(right);
final rightReceiverIds = _cpInviteReceiverIdentityValues(right);
if (leftInviterIds.isEmpty ||
leftReceiverIds.isEmpty ||
rightInviterIds.isEmpty ||
rightReceiverIds.isEmpty) {
return false;
}
final sameDirection =
_hasAnyCommonCpIdentity(leftInviterIds, rightInviterIds) &&
_hasAnyCommonCpIdentity(leftReceiverIds, rightReceiverIds);
final reversedDirection =
_hasAnyCommonCpIdentity(leftInviterIds, rightReceiverIds) &&
_hasAnyCommonCpIdentity(leftReceiverIds, rightInviterIds);
return sameDirection || reversedDirection;
}
bool _hasAnyCommonCpIdentity(Set<String> left, Set<String> right) {
if (left.isEmpty || right.isEmpty) {
return false;
}
return left.any(right.contains);
}
_CpInviteMessageState? _localCpInviteStateForData(Map<String, dynamic> data) {
return _localCpInviteStateForApplyId(_cpApplyIdFromData(data));
}
@ -2168,7 +2230,10 @@ class _MessageItem extends StatelessWidget {
if (!_isCpInvitePayload(data)) {
return "";
}
final state = _cpInviteStateForMessage(data);
final state = _cpInviteStateFromData(data);
if (state == _CpInviteMessageState.pending) {
return "";
}
final applyId = _cpApplyIdFromData(data);
if (applyId.isEmpty) {
return "";

View File

@ -41,6 +41,7 @@ class RoomCpInviteDialog extends StatefulWidget {
this.titleText,
this.descriptionText,
this.bottomText,
this.statusText,
this.acceptText = 'Accept',
this.rejectText = 'Reject',
this.onAccept,
@ -62,6 +63,7 @@ class RoomCpInviteDialog extends StatefulWidget {
final String? titleText;
final String? descriptionText;
final String? bottomText;
final String? statusText;
final String acceptText;
final String rejectText;
final VoidCallback? onAccept;
@ -82,6 +84,7 @@ class RoomCpInviteDialog extends StatefulWidget {
String? titleText,
String? descriptionText,
String? bottomText,
String? statusText,
String acceptText = 'Accept',
String rejectText = 'Reject',
VoidCallback? onAccept,
@ -108,6 +111,7 @@ class RoomCpInviteDialog extends StatefulWidget {
titleText: titleText,
descriptionText: descriptionText,
bottomText: bottomText,
statusText: statusText,
acceptText: acceptText,
rejectText: rejectText,
onAccept: onAccept,
@ -480,6 +484,10 @@ class _RoomCpInviteDialogState extends State<RoomCpInviteDialog> {
}
String get _statusText {
final statusText = widget.statusText?.trim();
if (statusText != null && statusText.isNotEmpty) {
return statusText;
}
final localizations = SCAppLocalizations.of(context);
switch (widget.actionState) {
case RoomCpInviteActionState.expired: