diff --git a/ConversationsClassic/AppData/Client/RosterManager.swift b/ConversationsClassic/AppData/Client/Client+MartinRosters.swift similarity index 98% rename from ConversationsClassic/AppData/Client/RosterManager.swift rename to ConversationsClassic/AppData/Client/Client+MartinRosters.swift index 272732d..4ade0af 100644 --- a/ConversationsClassic/AppData/Client/RosterManager.swift +++ b/ConversationsClassic/AppData/Client/Client+MartinRosters.swift @@ -2,7 +2,7 @@ import Foundation import GRDB import Martin -final class RosterManager: Martin.RosterManager { +final class ClientMartinRosterManager: Martin.RosterManager { func clear(for context: Martin.Context) { do { try Database.shared.dbQueue.write { db in diff --git a/ConversationsClassic/AppData/Client/Client.swift b/ConversationsClassic/AppData/Client/Client.swift index 3584db6..fddbecb 100644 --- a/ConversationsClassic/AppData/Client/Client.swift +++ b/ConversationsClassic/AppData/Client/Client.swift @@ -19,7 +19,7 @@ final class Client: ObservableObject { private var connection: XMPPClient private var connectionCancellable: AnyCancellable? - private var rosterManager = RosterManager() + private var rosterManager = ClientMartinRosterManager() init(credentials: Credentials) { self.credentials = credentials diff --git a/ConversationsClassic/AppData/Stores/RostersStore.swift b/ConversationsClassic/AppData/Stores/RostersStore.swift index 5cdcd80..f0747da 100644 --- a/ConversationsClassic/AppData/Stores/RostersStore.swift +++ b/ConversationsClassic/AppData/Stores/RostersStore.swift @@ -6,16 +6,32 @@ import GRDB final class RostersStore: ObservableObject { @Published private(set) var rosters: [Roster] = [] - init() { - // Task { - // let observation = ValueObservation.tracking(Roster.fetchAll) - // do { - // for try await credentials in observation.values(in: Database.shared.dbQueue) { - // processCredentials(credentials) - // ready = true - // print("Fetched \(credentials.count) credentials") - // } - // } catch {} - // } + private var cancellable: AnyCancellable? + + init(clientsPublisher: Published<[Client]>.Publisher) { + subscribeToClientsStore(clientsPublisher: clientsPublisher) + } + + private func subscribeToClientsStore(clientsPublisher: Published<[Client]>.Publisher) { + let rostersPublisher = ValueObservation.tracking(Roster.fetchAll) + .publisher(in: Database.shared.dbQueue) + .receive(on: DispatchQueue.main) + .catch { _ in Just([]) } + + cancellable = clientsPublisher + .flatMap { clients in + Publishers.MergeMany(clients.map { $0.$state }) + .prepend(clients.map { $0.state }) + .collect() + } + .combineLatest(rostersPublisher) + .sink { [weak self] clientStates, rosters in + self?.handleUpdates(clientStates: clientStates, rosters: rosters) + } + } + + private func handleUpdates(clientStates: [ClientState], rosters: [Roster]) { + self.rosters = rosters + print("Client States: \(clientStates.count), Rosters: \(rosters.count)") } } diff --git a/ConversationsClassic/View/Contacts/ContactsScreen.swift b/ConversationsClassic/View/Contacts/ContactsScreen.swift index f730823..64ade2e 100644 --- a/ConversationsClassic/View/Contacts/ContactsScreen.swift +++ b/ConversationsClassic/View/Contacts/ContactsScreen.swift @@ -2,6 +2,7 @@ import SwiftUI struct ContactsScreen: View { @EnvironmentObject var clientsStore: ClientsStore + @StateObject var rostersStore = RostersStore(clientsPublisher: ClientsStore.shared.$clients) // @State private var addPanelPresented = false // @State private var isErrorAlertPresented = false // @State private var errorAlertMessage = ""