android, desktop, ios: simplify pending-invitee preview selection

Collapse the four nested branches in addChatItem's preview pick into a
single "keep the current preview" predicate: the new item wins by default,
and only the comparison criterion changes for a pending invitee. Same
behaviour, addresses review feedback (4 branches for 2 outcomes).
This commit is contained in:
Narasimha-sc
2026-07-20 19:31:30 +00:00
parent 627598d5b3
commit 5bcba9e0b2
3 changed files with 26 additions and 41 deletions
+10 -17
View File
@@ -658,24 +658,17 @@ final class ChatModel: ObservableObject {
if let i = getChatIndex(cInfo.id) {
// update preview
if cInfo.groupChatScope() == nil || cInfo.groupInfo?.membership.memberPending ?? false {
chats[i].chatItems = switch cInfo {
case .group:
if let currentPreviewItem = chats[i].chatItems.first {
// Pending invitee: surface the latest support message (broker vs local itemTs
// aren't comparable); don't let a no-content event re-cover an already-shown message.
if cInfo.groupInfo?.membership.memberPending ?? false {
(cItem.content.msgContent != nil || currentPreviewItem.content.msgContent == nil) ? [cItem] : [currentPreviewItem]
} else if cItem.meta.itemTs >= currentPreviewItem.meta.itemTs {
[cItem]
} else {
[currentPreviewItem]
}
} else {
[cItem]
}
default:
[cItem]
let memberPending = cInfo.groupInfo?.membership.memberPending ?? false
let currentPreviewItem: ChatItem? = if case .group = cInfo { chats[i].chatItems.first } else { nil }
// the new item becomes the preview unless it is older - or, for a pending invitee, unless it is
// a no-content event that would re-cover an already shown support message (broker vs local
// itemTs aren't comparable there, so content presence is the criterion instead)
let keptPreviewItem = currentPreviewItem.flatMap { current in
(memberPending
? cItem.content.msgContent == nil && current.content.msgContent != nil
: cItem.meta.itemTs < current.meta.itemTs) ? current : nil
}
chats[i].chatItems = [keptPreviewItem ?? cItem]
if case .rcvNew = cItem.meta.itemStatus {
unreadCollector.changeUnreadCounter(cInfo.id, by: 1, unreadMentions: cItem.meta.userMention ? 1 : 0)
}
@@ -541,26 +541,15 @@ object ChatModel {
chat = chats[i]
// update preview (for chat from main scope to show new items for invitee in pending status)
if (cInfo.groupChatScope() == null || cInfo.groupInfo_?.membership?.memberPending == true) {
val newPreviewItem = when (cInfo) {
is ChatInfo.Group -> {
val currentPreviewItem = chat.chatItems.firstOrNull()
if (currentPreviewItem != null) {
// Pending invitee: surface the latest support message (broker vs local itemTs aren't
// comparable); don't let a no-content event re-cover an already-shown message.
if (cInfo.groupInfo_?.membership?.memberPending == true) {
if (cItem.content.msgContent != null || currentPreviewItem.content.msgContent == null) cItem else currentPreviewItem
} else if (cItem.meta.itemTs >= currentPreviewItem.meta.itemTs) {
cItem
} else {
currentPreviewItem
}
} else {
cItem
}
}
else -> cItem
}
val memberPending = cInfo.groupInfo_?.membership?.memberPending == true
val currentPreviewItem = if (cInfo is ChatInfo.Group) chat.chatItems.firstOrNull() else null
// the new item becomes the preview unless it is older - or, for a pending invitee, unless it is
// a no-content event that would re-cover an already shown support message (broker vs local
// itemTs aren't comparable there, so content presence is the criterion instead)
val newPreviewItem = currentPreviewItem?.takeIf {
if (memberPending) cItem.content.msgContent == null && it.content.msgContent != null
else cItem.meta.itemTs < it.meta.itemTs
} ?: cItem
val wasUnread = chat.unreadTag
chats[i] = chat.copy(
chatItems = arrayListOf(newPreviewItem),
@@ -158,11 +158,14 @@ Sent items win only because their `itemTs` is the same device's local clock.
**Fix (two parts):** for a pending invitee, (1) **bypass the cross-clock comparison** so the
support message surfaces, and (2) **prefer a message over a no-content event** so an event can't
re-cover an already-shown message (Kotlin + iOS):
re-cover an already-shown message (Kotlin + iOS). Expressed as a single *keep the current
preview* predicate — the new item wins by default, and only the criterion for keeping the old
one changes with `memberPending` (no extra branches per outcome):
```
if (memberPending)
if (cItem.content.msgContent != null || currentPreviewItem.content.msgContent == null) cItem else currentPreviewItem
else if (cItem.meta.itemTs >= currentPreviewItem.meta.itemTs) cItem else currentPreviewItem
newPreviewItem = currentPreviewItem?.takeIf {
if (memberPending) cItem.content.msgContent == null && it.content.msgContent != null
else cItem.meta.itemTs < it.meta.itemTs
} ?: cItem
```
Part (2) (`5b37cf881`) fixes a follow-up symptom — **"reviewed by admins" reappearing after the
first message**: a pending invitee's member-support no-content events arrive as new chat items in