修复卡片

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

View File

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