android, desktop, ios: tighten pending-invitee preview comments

This commit is contained in:
Narasimha-sc
2026-06-18 15:26:09 +00:00
parent d0e143d3f6
commit 2db3cb4afa
5 changed files with 15 additions and 25 deletions
+4 -7
View File
@@ -661,9 +661,8 @@ final class ChatModel: ObservableObject {
chats[i].chatItems = switch cInfo {
case .group:
if let currentPreviewItem = chats[i].chatItems.first {
// For a pending invitee, surface the latest support message in the preview (its
// broker-clock itemTs isn't comparable to a locally-stamped group event), but don't
// let a no-content group event re-cover a message already shown ("reviewed by admins").
// 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.hasMsgContent || !currentPreviewItem.content.hasMsgContent) ? [cItem] : [currentPreviewItem]
} else if cItem.meta.itemTs >= currentPreviewItem.meta.itemTs {
@@ -722,8 +721,7 @@ final class ChatModel: ObservableObject {
func upsertChatItem(_ cInfo: ChatInfo, _ cItem: ChatItem) -> Bool {
// update chat list
var itemAdded: Bool = false
// memberPending: a pending invitee's support item may be the main-list preview, so keep it in
// sync on edit/status change too (matching addChatItem)
// memberPending: a support item may be the main-list preview, keep it synced on edit/status (like addChatItem)
if cInfo.groupChatScope() == nil || cInfo.groupInfo?.membership.memberPending ?? false {
if let chat = getChat(cInfo.id) {
if let pItem = chat.chatItems.last {
@@ -795,8 +793,7 @@ final class ChatModel: ObservableObject {
func removeChatItem(_ cInfo: ChatInfo, _ cItem: ChatItem) {
// update chat list
// memberPending: a pending invitee's support item may be the main-list preview, so clear it
// when deleted/moderated too (matching addChatItem)
// memberPending: a support item may be the main-list preview, clear it on delete/moderate (like addChatItem)
if cInfo.groupChatScope() == nil || cInfo.groupInfo?.membership.memberPending ?? false {
if cItem.isRcvNew {
unreadCollector.changeUnreadCounter(cInfo.id, by: -1, unreadMentions: cItem.meta.userMention ? -1 : 0)
@@ -351,9 +351,8 @@ struct ChatPreviewView: View {
let (t, hasSecrets) = messageDraft(draft)
chatPreviewLayout(t, draft: true, hasFilePreview: hasFilePreview, hasSecrets: hasSecrets)
} else if cItem?.content.msgContent == nil, let previewText = chatPreviewInfoText() {
// only a no-content item (a group/connection event) shows the status text; a message
// including caption-less media falls through to render its content (thumbnail shown
// separately), e.g. a pending invitee's photo shows "image" instead of "reviewed by admins"
// status text only for no-content events; any message (incl. caption-less media) renders
// its content (thumbnail shown separately) - e.g. a pending invitee's photo shows "image"
chatPreviewInfoTextLayout(previewText)
} else if let cItem = cItem {
let (t, hasSecrets) = chatItemPreview(cItem)
@@ -520,9 +520,8 @@ object ChatModel {
}
suspend fun addChatItem(rhId: Long?, chatInfo: ChatInfo, cItem: ChatItem) {
// A message sent in a member-support scope ("chat with admins") is added only to that secondary
// context; received items reach both. Mirror it so the send still updates the main chat list
// preview (e.g. a pending invitee's own message) - #5909.
// A member-support send reaches only the active (secondary) context; mirror it to the primary
// so the main-list preview updates (e.g. a pending invitee's own message) - #5909.
if (secondaryContextFilter is SecondaryContextFilter.GroupChatScopeContext && cItem.chatDir.sent) {
chatsContext.addChatItem(rhId, chatInfo, cItem)
}
@@ -546,9 +545,8 @@ object ChatModel {
is ChatInfo.Group -> {
val currentPreviewItem = chat.chatItems.firstOrNull()
if (currentPreviewItem != null) {
// For a pending invitee, surface the latest support message in the preview (its
// broker-clock itemTs isn't comparable to a locally-stamped group event), but don't
// let a no-content group event re-cover a message already shown ("reviewed by admins").
// 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.hasMsgContent || !currentPreviewItem.content.hasMsgContent) cItem else currentPreviewItem
} else if (cItem.meta.itemTs >= currentPreviewItem.meta.itemTs) {
@@ -622,8 +620,7 @@ object ChatModel {
suspend fun upsertChatItem(rhId: Long?, cInfo: ChatInfo, cItem: ChatItem): Boolean {
var itemAdded = false
// update chat list
// memberPending: a pending invitee's support item may be the main-list preview, so keep it in
// sync on edit/status change too (matching addChatItem)
// memberPending: a support item may be the main-list preview, keep it synced on edit/status (like addChatItem)
if (cInfo.groupChatScope() == null || cInfo.groupInfo_?.membership?.memberPending == true) {
val i = getChatIndex(rhId, cInfo.id)
val chat: Chat
@@ -682,8 +679,7 @@ object ChatModel {
fun removeChatItem(rhId: Long?, cInfo: ChatInfo, cItem: ChatItem) {
// update chat list
// memberPending: a pending invitee's support item may be the main-list preview, so clear it
// when deleted/moderated too (matching addChatItem)
// memberPending: a support item may be the main-list preview, clear it on delete/moderate (like addChatItem)
if (cInfo.groupChatScope() == null || cInfo.groupInfo_?.membership?.memberPending == true) {
if (cItem.isRcvNew) {
decreaseCounterInPrimaryContext(rhId, cInfo.id)
@@ -760,8 +760,7 @@ fun ComposeView(
if (updatedItem != null) {
withContext(Dispatchers.Main) {
chatsCtx.upsertChatItem(chat.remoteHostId, cInfo, updatedItem.chatItem)
// an edit in a member-support scope is added only to the active (secondary) context; also
// update the primary context so the main chat list preview reflects the edit (like the send path)
// a member-support edit reaches only the active context; also update primary so the preview reflects it
if (chatsCtx.secondaryContextFilter is SecondaryContextFilter.GroupChatScopeContext) {
chatModel.chatsContext.upsertChatItem(chat.remoteHostId, cInfo, updatedItem.chatItem)
}
@@ -239,9 +239,8 @@ fun ChatPreviewView(
modifier = Modifier.fillMaxWidth()
)
} else if (ci?.content?.msgContent == null && previewText != null) {
// only a no-content item (a group/connection event) shows the status text; a message —
// including caption-less media — falls through to render its content (the media thumbnail is
// shown separately), e.g. a pending invitee's photo shows "image" instead of "reviewed by admins"
// status text only for no-content events; any message (incl. caption-less media) renders its
// content (thumbnail shown separately) - e.g. a pending invitee's photo shows "image", not the status
Text(previewText.first, color = previewText.second)
} else if (ci != null && showChatPreviews) {
val (text: CharSequence, inlineTextContent) = when {