conversations-classic-ios/ConversationsClassic/AppData/Store/ClientsStore.swift

78 lines
2.3 KiB
Swift
Raw Normal View History

2024-08-11 00:28:01 +00:00
import Combine
import Foundation
import GRDB
@MainActor
final class ClientsStore: ObservableObject {
static let shared = ClientsStore()
@Published private(set) var ready = false
@Published private(set) var clients: [Client] = []
2024-08-11 20:33:04 +00:00
private let credentialsObservation = ValueObservation.tracking(Credentials.fetchAll)
2024-08-11 19:01:48 +00:00
2024-08-11 20:33:04 +00:00
init() {
2024-08-11 00:28:01 +00:00
Task {
do {
2024-08-11 20:33:04 +00:00
for try await creds in credentialsObservation.values(in: Database.shared.dbQueue) {
processCredentials(creds)
if !ready {
ready = true
}
2024-08-11 00:28:01 +00:00
}
} catch {}
}
}
2024-08-11 19:01:48 +00:00
private func processCredentials(_ credentials: [Credentials]) {
let existsJids = Set(clients.map { $0.credentials.bareJid })
let credentialsJids = Set(credentials.map { $0.bareJid })
let forAdd = credentials.filter { !existsJids.contains($0.bareJid) }
let newClients = forAdd.map { Client(credentials: $0) }
let forRemove = clients.filter { !credentialsJids.contains($0.credentials.bareJid) }
forRemove.forEach { $0.disconnect() }
var updatedClients = clients.filter { credentialsJids.contains($0.credentials.bareJid) }
updatedClients.append(contentsOf: newClients)
clients = updatedClients
}
}
extension ClientsStore {
2024-08-11 20:33:04 +00:00
func tryLogin(_ jidStr: String, _ pass: String) async throws {
// login with fake timeout
async let sleep: Void? = try? await Task.sleep(nanoseconds: 1 * NSEC_PER_SEC)
async let request = try await Client.tryLogin(with: .init(bareJid: jidStr, pass: pass, isActive: true))
let client = try await(request, sleep).0
2024-08-11 00:28:01 +00:00
clients.append(client)
2024-08-11 20:33:04 +00:00
try? await client.credentials.save()
2024-08-11 00:28:01 +00:00
}
2024-08-11 19:01:48 +00:00
func reconnectAll() {
Task {
await withTaskGroup(of: Void.self) { taskGroup in
for client in clients {
taskGroup.addTask {
await client.connect()
}
}
}
}
2024-08-11 00:28:01 +00:00
}
}
2024-08-11 20:33:04 +00:00
extension ClientsStore {
var actualRosters: [Roster] {
get async {
var allRosters: [Roster] = []
for client in clients {
allRosters.append(contentsOf: await client.rosters)
}
return allRosters
}
}
}