From 342e270a1f453fc67348d399fa1c1475946b291e Mon Sep 17 00:00:00 2001 From: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com> Date: Thu, 18 Jun 2026 15:38:16 +0000 Subject: [PATCH] ios: clamp removeChatItem unread decrement to match Android (avoid negative badge drift) removeChatItem decremented the unread counter unconditionally for an RcvNew item. iOS, unlike Android's self-clamping decreaseCounterInPrimaryContext, could drive the badge negative if the item entered the list via upsertChatItem's addChat path (no increment) and was then deleted unread. Only decrement when the chat's unreadCount > 0. --- apps/ios/Shared/Model/ChatModel.swift | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index dbcf1c94cf..51c7d6d182 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -795,14 +795,15 @@ final class ChatModel: ObservableObject { // update chat list // 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 { + let chat = getChat(cInfo.id) + // clamp: only decrement when there is something to decrement (matches the Android primary-context + // decrement), so deleting an item that never incremented the badge can't drive it negative + if cItem.isRcvNew, let chat, chat.chatStats.unreadCount > 0 { unreadCollector.changeUnreadCounter(cInfo.id, by: -1, unreadMentions: cItem.meta.userMention ? -1 : 0) } // update previews - if let chat = getChat(cInfo.id) { - if let pItem = chat.chatItems.last, pItem.id == cItem.id { - chat.chatItems = [ChatItem.deletedItemDummy()] - } + if let chat, let pItem = chat.chatItems.last, pItem.id == cItem.id { + chat.chatItems = [ChatItem.deletedItemDummy()] } } // remove from current scope