Merge 6167c9f6eabedf15a39302345935348ef7d1045a into 9b84b361225facd8e623f25d76f889d3dc54a879

This commit is contained in:
Taksh Kothari 2026-08-11 09:05:57 +02:00 committed by GitHub
commit cace62cb94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 4 deletions

View File

@ -87,7 +87,7 @@ final class PrivateChatManager: ObservableObject {
/// This ensures messages from stable Noise keys and temporary Nostr peer IDs are merged.
/// - Parameters:
/// - peerID: The target peer ID to consolidate messages into
/// - peerNickname: The peer's display name (lowercased for matching)
/// - peerNickname: The peer's display name (NFC + lowercased for matching)
/// - persistedReadReceipts: The persisted read receipts set from ChatViewModel (UserDefaults-backed)
/// - Returns: True if any unread messages were found during consolidation
@MainActor
@ -140,13 +140,17 @@ final class PrivateChatManager: ObservableObject {
}
}
// 2. Consolidate from temporary Nostr peer IDs (nostr_* prefixed)
let normalizedNickname = peerNickname.lowercased()
// 2. Consolidate from temporary Nostr peer IDs (nostr_* prefixed).
// Match on NFC so a wire sender typed with combining accents still
// merges into the stored peer nickname (precomposed after #1502).
let normalizedNickname = peerNickname.normalizedNickname.lowercased()
var tempPeerIDsToConsolidate: [PeerID] = []
for (storedPeerID, messages) in privateChats {
if storedPeerID.isGeoDM && storedPeerID != peerID {
let nicknamesMatch = messages.allSatisfy { $0.sender.lowercased() == normalizedNickname }
let nicknamesMatch = messages.allSatisfy {
$0.sender.normalizedNickname.lowercased() == normalizedNickname
}
if nicknamesMatch && !messages.isEmpty {
tempPeerIDsToConsolidate.append(storedPeerID)
}

View File

@ -258,6 +258,44 @@ struct PrivateChatManagerTests {
#expect(!manager.unreadMessages.contains(tempPeerID))
}
@Test @MainActor
func consolidateMessages_movesTemporaryGeoDMHistoryByCanonicalNickname() async {
// Wire sender can arrive NFD while the peer nickname is stored NFC
// (#1502). Consolidation must still merge the temp geo DM thread.
let transport = MockTransport()
let (manager, store) = Self.makeManager(transport: transport)
let peerID = PeerID(str: "0011223344556677")
let tempPeerID = PeerID(nostr_: "0000000000000000000000000000000000000000000000000000000000000042")
let decomposed = "cafe\u{0301}"
let precomposed = "caf\u{00E9}"
store.append(
BitchatMessage(
id: "geo-nfc-msg",
sender: decomposed,
content: "Geo hello",
timestamp: Date(),
isRelay: false,
isPrivate: true,
recipientNickname: "Me",
senderPeerID: tempPeerID
),
to: .directPeer(tempPeerID)
)
store.markUnread(.directPeer(tempPeerID))
let hadUnread = manager.consolidateMessages(
for: peerID,
peerNickname: precomposed,
persistedReadReceipts: []
)
#expect(hadUnread)
#expect(manager.privateChats[tempPeerID] == nil)
#expect(manager.privateChats[peerID]?.count == 1)
#expect(manager.unreadMessages.contains(peerID))
}
@Test @MainActor
func syncReadReceiptsForSentMessages_onlyCopiesDeliveredAndRead() async {
let transport = MockTransport()