mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-10-18 07:33:46 +00:00
Adds a mark-as-read action to the mesh, groups and chats rows in the people sheet, and to the header of an open DM. Clearing the badge sends no read receipt — the unread state is local, so dismissing it should stay local. Badge clearing is alias-aware: ChatUnreadStateResolver.matchingUnreadPeerIDs collects the noise-key, nostr and geoDM-nickname peer IDs that resolve to the same conversation, mirroring hasUnreadMessages. Clearing only the routing peer ID left ghost badges behind on the aliases. Rebased onto current main. The catalog carries only the three new keys, spliced in Xcode's serialization; main's 520 existing keys are untouched. The chats section main gained in #1598 gets the same action.
79 lines
2.4 KiB
Swift
79 lines
2.4 KiB
Swift
import BitFoundation
|
|
import Foundation
|
|
|
|
struct ChatUnreadPeerContext {
|
|
let peerID: PeerID
|
|
let noiseKeyPeerID: PeerID?
|
|
let nostrPeerID: PeerID?
|
|
let nickname: String?
|
|
}
|
|
|
|
enum ChatUnreadStateResolver {
|
|
static func hasUnreadMessages(
|
|
for context: ChatUnreadPeerContext,
|
|
unreadPrivateMessages: Set<PeerID>,
|
|
privateChats: [PeerID: [BitchatMessage]]
|
|
) -> Bool {
|
|
if unreadPrivateMessages.contains(context.peerID) {
|
|
return true
|
|
}
|
|
|
|
if let noiseKeyPeerID = context.noiseKeyPeerID,
|
|
unreadPrivateMessages.contains(noiseKeyPeerID) {
|
|
return true
|
|
}
|
|
|
|
if let nostrPeerID = context.nostrPeerID,
|
|
unreadPrivateMessages.contains(nostrPeerID) {
|
|
return true
|
|
}
|
|
|
|
guard let peerNickname = context.nickname?.lowercased(), !peerNickname.isEmpty else {
|
|
return false
|
|
}
|
|
|
|
return unreadPrivateMessages.contains { unreadPeerID in
|
|
guard unreadPeerID.isGeoDM,
|
|
let firstMessage = privateChats[unreadPeerID]?.first else {
|
|
return false
|
|
}
|
|
return firstMessage.sender.lowercased() == peerNickname
|
|
}
|
|
}
|
|
|
|
/// Peer IDs in `unreadPrivateMessages` that resolve to the same
|
|
/// conversation badge as `hasUnreadMessages(for:)`.
|
|
static func matchingUnreadPeerIDs(
|
|
for context: ChatUnreadPeerContext,
|
|
unreadPrivateMessages: Set<PeerID>,
|
|
privateChats: [PeerID: [BitchatMessage]]
|
|
) -> Set<PeerID> {
|
|
var matching = Set<PeerID>()
|
|
|
|
if unreadPrivateMessages.contains(context.peerID) {
|
|
matching.insert(context.peerID)
|
|
}
|
|
|
|
if let noiseKeyPeerID = context.noiseKeyPeerID,
|
|
unreadPrivateMessages.contains(noiseKeyPeerID) {
|
|
matching.insert(noiseKeyPeerID)
|
|
}
|
|
|
|
if let nostrPeerID = context.nostrPeerID,
|
|
unreadPrivateMessages.contains(nostrPeerID) {
|
|
matching.insert(nostrPeerID)
|
|
}
|
|
|
|
if let peerNickname = context.nickname?.lowercased(), !peerNickname.isEmpty {
|
|
for unreadPeerID in unreadPrivateMessages where unreadPeerID.isGeoDM {
|
|
guard let firstMessage = privateChats[unreadPeerID]?.first else { continue }
|
|
if firstMessage.sender.lowercased() == peerNickname {
|
|
matching.insert(unreadPeerID)
|
|
}
|
|
}
|
|
}
|
|
|
|
return matching
|
|
}
|
|
}
|