diff --git a/bitchat/Services/PrivateChatManager.swift b/bitchat/Services/PrivateChatManager.swift index c5579125..e7d924db 100644 --- a/bitchat/Services/PrivateChatManager.swift +++ b/bitchat/Services/PrivateChatManager.swift @@ -39,9 +39,10 @@ final class PrivateChatManager: ObservableObject { /// - Parameters: /// - peerID: The target peer ID to consolidate messages into /// - peerNickname: The peer's display name (lowercased for matching) + /// - persistedReadReceipts: The persisted read receipts set from ChatViewModel (UserDefaults-backed) /// - Returns: True if any unread messages were found during consolidation @MainActor - func consolidateMessages(for peerID: PeerID, peerNickname: String) -> Bool { + func consolidateMessages(for peerID: PeerID, peerNickname: String, persistedReadReceipts: Set) -> Bool { guard let meshService = meshService else { return false } var hasUnreadMessages = false @@ -74,9 +75,10 @@ final class PrivateChatManager: ObservableObject { privateChats[peerID]?.append(updatedMessage) // Check for recent unread messages (< 60s, not sent by us, not already read) + // Use persistedReadReceipts to correctly identify already-read messages after app restart if message.senderPeerID != meshService.myPeerID { let messageAge = Date().timeIntervalSince(message.timestamp) - if messageAge < 60 && !sentReadReceipts.contains(message.id) { + if messageAge < 60 && !persistedReadReceipts.contains(message.id) { hasUnreadMessages = true } } diff --git a/bitchat/ViewModels/ChatViewModel.swift b/bitchat/ViewModels/ChatViewModel.swift index 2cc75de3..9533d8bb 100644 --- a/bitchat/ViewModels/ChatViewModel.swift +++ b/bitchat/ViewModels/ChatViewModel.swift @@ -2560,7 +2560,8 @@ final class ChatViewModel: ObservableObject, BitchatDelegate, CommandContextProv } // Consolidate messages from different peer ID representations (stable Noise key, temp Nostr IDs) - _ = privateChatManager.consolidateMessages(for: peerID, peerNickname: peerNickname) + // Pass persisted sentReadReceipts to correctly identify already-read messages after app restart + _ = privateChatManager.consolidateMessages(for: peerID, peerNickname: peerNickname, persistedReadReceipts: sentReadReceipts) // Trigger handshake if needed (mesh peers only). Skip for Nostr geohash conv keys. if !peerID.isGeoDM && !peerID.isGeoChat {