diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt index b9c5d9819d..4286f019e3 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt @@ -215,6 +215,9 @@ class ChatModel(val controller: ChatController) { } fun removeChatItem(cInfo: ChatInfo, cItem: ChatItem) { + if (cItem.isRcvNew) { + decreaseCounterInChat(cInfo.id) + } // update previews val i = getChatIndex(cInfo.id) val chat: Chat @@ -222,10 +225,7 @@ class ChatModel(val controller: ChatController) { chat = chats[i] val pItem = chat.chatItems.lastOrNull() if (pItem?.id == cItem.id) { - chats[i] = chat.copy(chatItems = arrayListOf(ChatItem.defaultDeleted)) - } - if (cItem.isRcvNew) { - decreaseCounterInChat(cInfo.id) + chats[i] = chat.copy(chatItems = arrayListOf(ChatItem.deletedItemDummy)) } } // remove from current chat @@ -1204,9 +1204,10 @@ data class ChatItem ( file = null ) } - + private const val TEMP_DELETED_CHAT_ITEM_ID = -1L - val defaultDeleted: ChatItem + + val deletedItemDummy: ChatItem get() = ChatItem( chatDir = CIDirection.DirectRcv(), meta = CIMeta( diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index ecc86de4dc..db4b13f9c2 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -236,16 +236,19 @@ final class ChatModel: ObservableObject { } func removeChatItem(_ cInfo: ChatInfo, _ cItem: ChatItem) { + if cItem.isRcvNew { + decreaseUnreadCounter(cInfo) + } // update previews if let chat = getChat(cInfo.id) { if let pItem = chat.chatItems.last, pItem.id == cItem.id { - chat.chatItems = [cItem] + chat.chatItems = [ChatItem.deletedItemDummy()] } } // remove from current chat if chatId == cInfo.id { if let i = reversedChatItems.firstIndex(where: { $0.id == cItem.id }) { - if reversedChatItems[i].isRcvNew() == true { + if reversedChatItems[i].isRcvNew { NtfManager.shared.decNtfBadgeCount() } _ = withAnimation { @@ -342,9 +345,7 @@ final class ChatModel: ObservableObject { func markChatItemRead(_ cInfo: ChatInfo, _ cItem: ChatItem) { // update preview - if let i = getChatIndex(cInfo.id) { - chats[i].chatStats.unreadCount = chats[i].chatStats.unreadCount - 1 - } + decreaseUnreadCounter(cInfo) // update current chat if chatId == cInfo.id, let j = reversedChatItems.firstIndex(where: { $0.id == cItem.id }) { reversedChatItems[j].meta.itemStatus = .rcvRead @@ -352,6 +353,12 @@ final class ChatModel: ObservableObject { } } + func decreaseUnreadCounter(_ cInfo: ChatInfo) { + if let i = getChatIndex(cInfo.id) { + chats[i].chatStats.unreadCount = chats[i].chatStats.unreadCount - 1 + } + } + func totalUnreadCount() -> Int { chats.reduce(0, { count, chat in count + chat.chatStats.unreadCount }) } @@ -418,7 +425,7 @@ final class ChatModel: ObservableObject { var unreadBelow = 0 while i < reversedChatItems.count - 1 && !itemsInView.contains(reversedChatItems[i].viewId) { totalBelow += 1 - if reversedChatItems[i].isRcvNew() { + if reversedChatItems[i].isRcvNew { unreadBelow += 1 } i += 1 diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index 0a3a7da0b8..e38b7435f4 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -221,7 +221,7 @@ struct ChatView: View { .onAppear { itemsInView.insert(ci.viewId) loadChatItems(cInfo, ci, proxy) - if ci.isRcvNew() { + if ci.isRcvNew { DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) { if chatModel.chatId == cInfo.id && itemsInView.contains(ci.viewId) { Task { diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index 1540ed6fa1..64a61e2a57 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -1380,7 +1380,7 @@ public struct ChatItem: Identifiable, Decodable { } } - public func isRcvNew() -> Bool { + public var isRcvNew: Bool { if case .rcvNew = meta.itemStatus { return true } return false } @@ -1458,7 +1458,7 @@ public struct ChatItem: Identifiable, Decodable { content: .sndMsgContent(msgContent: .text(text)), quotedItem: quotedItem, file: file - ) + ) } public static func getVoiceMsgContentSample (id: Int64 = 1, text: String = "", fileName: String = "voice.m4a", fileSize: Int64 = 65536, fileStatus: CIFileStatus = .rcvComplete) -> ChatItem { @@ -1468,7 +1468,7 @@ public struct ChatItem: Identifiable, Decodable { content: .rcvMsgContent(msgContent: .voice(text: text, duration: 30)), quotedItem: nil, file: CIFile.getSample(fileName: fileName, fileSize: fileSize, fileStatus: fileStatus) - ) + ) } public static func getFileMsgContentSample (id: Int64 = 1, text: String = "", fileName: String = "test.txt", fileSize: Int64 = 100, fileStatus: CIFileStatus = .rcvComplete) -> ChatItem { @@ -1478,7 +1478,7 @@ public struct ChatItem: Identifiable, Decodable { content: .rcvMsgContent(msgContent: .file(text)), quotedItem: nil, file: CIFile.getSample(fileName: fileName, fileSize: fileSize, fileStatus: fileStatus) - ) + ) } public static func getDeletedContentSample (_ id: Int64 = 1, dir: CIDirection = .directRcv, _ ts: Date = .now, _ text: String = "this item is deleted", _ status: CIStatus = .rcvRead) -> ChatItem { @@ -1488,7 +1488,7 @@ public struct ChatItem: Identifiable, Decodable { content: .rcvDeleted(deleteMode: .cidmBroadcast), quotedItem: nil, file: nil - ) + ) } public static func getIntegrityErrorSample (_ status: CIStatus = .rcvRead, fromMsgId: Int64 = 1, toMsgId: Int64 = 2) -> ChatItem { @@ -1498,7 +1498,7 @@ public struct ChatItem: Identifiable, Decodable { content: .rcvIntegrityError(msgError: .msgSkipped(fromMsgId: fromMsgId, toMsgId: toMsgId)), quotedItem: nil, file: nil - ) + ) } public static func getGroupInvitationSample (_ status: CIGroupInvitationStatus = .pending) -> ChatItem { @@ -1508,7 +1508,7 @@ public struct ChatItem: Identifiable, Decodable { content: .rcvGroupInvitation(groupInvitation: CIGroupInvitation.getSample(status: status), memberRole: .admin), quotedItem: nil, file: nil - ) + ) } public static func getGroupEventSample () -> ChatItem { @@ -1518,7 +1518,7 @@ public struct ChatItem: Identifiable, Decodable { content: .rcvGroupEvent(rcvGroupEvent: .memberAdded(groupMemberId: 1, profile: Profile.sampleData)), quotedItem: nil, file: nil - ) + ) } public static func getChatFeatureSample(_ feature: ChatFeature, _ enabled: FeatureEnabled) -> ChatItem { @@ -1529,7 +1529,27 @@ public struct ChatItem: Identifiable, Decodable { content: content, quotedItem: nil, file: nil - ) + ) + } + + public static func deletedItemDummy() -> ChatItem { + ChatItem( + chatDir: CIDirection.directRcv, + meta: CIMeta( + itemId: -1, + itemTs: .now, + itemText: NSLocalizedString("deleted", comment: "deleted chat item"), + itemStatus: .rcvRead, + createdAt: .now, + updatedAt: .now, + itemDeleted: false, + itemEdited: false, + editable: false + ), + content: .rcvDeleted(deleteMode: .cidmBroadcast), + quotedItem: nil, + file: nil + ) } }