mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-26 21:25:22 +00:00
Cut views over to ConversationStore; delete legacy store, bridge, resolver
Feature models observe per-conversation objects directly: PublicChatModel forwards the active Conversation's objectWillChange, PrivateInboxModel republishes only for the selected peer's conversation - background appends no longer invalidate foreground views. LegacyConversationStore, the coalescing bridge, and IdentityResolver are deleted (resolver canonicalization proved display-invisible: nothing enumerates direct conversations, lookups are by exact peer ID, and raw keying is strictly more robust - documented as a design deviation). Selection state moves into the store. ChatViewModel.messages/privateChats survive as derived read views for coordinators that genuinely need them; hot paths use a new store-direct privateMessages(for:) witness. Final numbers vs pre-migration baselines: pipeline.privateIngest 9.7k -> 24.0k msg/s (2.5x) pipeline.publicIngest 6.8k -> 13.7k msg/s (2.0x) delivery updates 38k -> 117-133k/s Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,9 @@ import Foundation
|
||||
protocol ChatPrivateConversationContext: AnyObject {
|
||||
// MARK: Conversation state
|
||||
var privateChats: [PeerID: [BitchatMessage]] { get }
|
||||
/// A single private chat's timeline. Witnessed by the store-direct
|
||||
/// lookup on `ChatViewModel` (no `privateChats` dictionary build).
|
||||
func privateMessages(for peerID: PeerID) -> [BitchatMessage]
|
||||
var sentReadReceipts: Set<String> { get }
|
||||
var unreadPrivateMessages: Set<PeerID> { get }
|
||||
var selectedPrivateChatPeer: PeerID? { get }
|
||||
@@ -588,8 +591,8 @@ final class ChatPrivateConversationCoordinator {
|
||||
|
||||
if peerID.id.count == 16, let peerNoiseKey = context.noisePublicKey(for: peerID) {
|
||||
let stableKeyHex = PeerID(hexData: peerNoiseKey)
|
||||
let nostrMessages = context.privateMessages(for: stableKeyHex)
|
||||
if stableKeyHex != peerID,
|
||||
let nostrMessages = context.privateChats[stableKeyHex],
|
||||
!nostrMessages.isEmpty {
|
||||
// Store migration dedups by ID, keeps timestamp order, and
|
||||
// removes the stable-key chat.
|
||||
@@ -767,7 +770,7 @@ final class ChatPrivateConversationCoordinator {
|
||||
func migratePrivateChatsIfNeeded(for peerID: PeerID, senderNickname: String) {
|
||||
let currentFingerprint = context.getFingerprint(for: peerID)
|
||||
|
||||
if context.privateChats[peerID] == nil || context.privateChats[peerID]?.isEmpty == true {
|
||||
if context.privateMessages(for: peerID).isEmpty {
|
||||
// Chats migrated wholesale go through the store's
|
||||
// `migrateConversation` intent; partially-migrated chats keep
|
||||
// their non-recent tail, so the recent messages are copied in
|
||||
@@ -876,3 +879,11 @@ final class ChatPrivateConversationCoordinator {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/// Default for conforming test contexts that model chats as a dictionary;
|
||||
/// `ChatViewModel` overrides with a store-direct lookup.
|
||||
extension ChatPrivateConversationContext {
|
||||
func privateMessages(for peerID: PeerID) -> [BitchatMessage] {
|
||||
privateChats[peerID] ?? []
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user