120 lines
4.4 KiB
Swift
120 lines
4.4 KiB
Swift
import Combine
|
|
import Foundation
|
|
import GRDB
|
|
|
|
@MainActor
|
|
final class RostersStore: ObservableObject {
|
|
@Published private(set) var rosters: [Roster] = []
|
|
@Published private(set) var locallyDeletedRosters: [Roster] = []
|
|
|
|
private var cancellable: AnyCancellable?
|
|
|
|
init() {
|
|
let rostersPublisher = ValueObservation.tracking(Roster.fetchAll)
|
|
.publisher(in: Database.shared.dbQueue)
|
|
.receive(on: DispatchQueue.main)
|
|
.catch { _ in Just([]) }
|
|
|
|
cancellable = ClientsStore.shared.$clients
|
|
.map { $0.filter { $0.state != .disabled } } // look rosters only for enabled clients
|
|
.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.filter { !$0.locallyDeleted }
|
|
locallyDeletedRosters = rosters.filter { $0.locallyDeleted }
|
|
print("Client States: \(clientStates.count), Rosters: \(rosters.count)")
|
|
}
|
|
}
|
|
|
|
extension RostersStore {
|
|
enum RosterAddResult {
|
|
case success
|
|
case connectionError
|
|
case serverError
|
|
}
|
|
|
|
func addRoster(_ owner: Credentials, contactJID: String, name _: String?, groups _: [String]) async -> RosterAddResult {
|
|
// check if such roster was already exists or locally deleted
|
|
if var exists = rosters.first(where: { $0.bareJid == owner.bareJid && $0.contactBareJid == contactJID }), exists.locallyDeleted {
|
|
try? await exists.setLocallyDeleted(false)
|
|
return .success
|
|
}
|
|
|
|
// add new roster
|
|
// check that client is enabled and connected
|
|
let clientStorage = ClientsStore.shared
|
|
while !clientStorage.ready {
|
|
await Task.yield()
|
|
}
|
|
print("!! Clients: \(clientStorage.clients.count)")
|
|
guard let client = clientStorage.clients.first(where: { $0.credentials == owner }) else {
|
|
return .connectionError
|
|
}
|
|
guard client.state == .enabled(.connected) else {
|
|
return .connectionError
|
|
}
|
|
// guard let client = ClientsStore.shared.clients.first(where: { $0.credentials == owner }), client.state == .enabled(.connected) else {
|
|
// return .connectionError
|
|
// }
|
|
|
|
// add roster
|
|
do {
|
|
try await client.addRoster(contactJID, name: nil, groups: [])
|
|
return .success
|
|
} catch {
|
|
return .serverError
|
|
}
|
|
|
|
// guard let client = clientsStore.clients.first(where: { $0.credentials == ownerCredentials }), client.state == .enabled(.connected) else {
|
|
// router.showAlert(
|
|
// .alert,
|
|
// title: L10n.Global.Error.title,
|
|
// subtitle: L10n.Contacts.Add.connectionError
|
|
// ) {
|
|
// Button(L10n.Global.ok, role: .cancel) {}
|
|
// }
|
|
// return
|
|
// }
|
|
//
|
|
// router.showModal {
|
|
// LoadingScreen()
|
|
// }
|
|
//
|
|
// do {
|
|
// try await client.addRoster(contactJID, name: nil, groups: [])
|
|
// } catch {
|
|
// router.showAlert(
|
|
// .alert,
|
|
// title: L10n.Global.Error.title,
|
|
// subtitle: L10n.Contacts.Add.serverError
|
|
// ) {
|
|
// Button(L10n.Global.ok, role: .cancel) {}
|
|
// }
|
|
// return
|
|
// }
|
|
//
|
|
// router.dismissModal()
|
|
// router.dismissScreen()
|
|
|
|
// client.addRoster(jid: )
|
|
|
|
// guard let ownerAccount else { return }
|
|
// if let exists = store.state.rostersState.rosters.first(where: { $0.bareJid == ownerAccount.bareJid && $0.contactBareJid == contactJID }), exists.locallyDeleted {
|
|
// store.dispatch(.rostersAction(.unmarkRosterAsLocallyDeleted(ownerJID: ownerAccount.bareJid, contactJID: contactJID)))
|
|
// isPresented = false
|
|
// } else {
|
|
// isShowingLoader = true
|
|
// store.dispatch(.rostersAction(.addRoster(ownerJID: ownerAccount.bareJid, contactJID: contactJID, name: nil, groups: [])))
|
|
// }
|
|
}
|
|
}
|