diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-11-27 23:38:04 +0100 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-11-27 23:38:04 +0100 |
| commit | 213710bf5bd6413c747bf126db50816ef5de5a6e (patch) | |
| tree | 912f8cf87955a08077c92fea8ad934f50b7ab975 /Hotline/State/AppState.swift | |
| parent | f466b21dc02f78c984ba6748e703f6780a7a0db4 (diff) | |
| parent | 6a95b53616a4abfa306ddce43151cf4fefbd20ed (diff) | |
Merge remote-tracking branch 'upstream/main'
Diffstat (limited to 'Hotline/State/AppState.swift')
| -rw-r--r-- | Hotline/State/AppState.swift | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/Hotline/State/AppState.swift b/Hotline/State/AppState.swift new file mode 100644 index 0000000..e268ba2 --- /dev/null +++ b/Hotline/State/AppState.swift @@ -0,0 +1,114 @@ +import SwiftUI + +extension EnvironmentValues { + @Entry var appState: AppState = AppState.shared +} + +@Observable +final class AppState { + static let shared = AppState() + + private init() { + + } + + var bonjourState = BonjourState() + + var activeHotline: HotlineState? = nil + var activeServerState: ServerState? = nil + + var cloudKitReady: Bool = false + + // MARK: - Transfers + + /// All active transfers across all servers + /// Transfers persist even if you disconnect from the server + var transfers: [TransferInfo] = [] + + @ObservationIgnored private var transferClients: [UUID: HotlineTransferClient] = [:] + + /// Track download tasks by reference number for cancellation + @ObservationIgnored private var transferTasks: [UUID: Task<Void, Never>] = [:] + + /// Add a transfer to the transfer list + @MainActor + func addTransfer(_ transfer: TransferInfo) { + self.transfers.append(transfer) + } + + /// Cancel a transfer by transfer ID + @MainActor + func cancelTransfer(id: UUID) { + guard let transferIndex = self.transfers.firstIndex(where: { $0.id == id }) else { + return + } + + // Cancel the task if it exists + if let task = self.transferTasks[id] { + task.cancel() + self.transferTasks.removeValue(forKey: id) + } + + if let client = self.transferClients[id] { + client.cancel() + self.transferClients.removeValue(forKey: id) + } + + // Remove from transfers list + self.transfers.remove(at: transferIndex) + } + + /// Cancel specified transfers + @MainActor + func cancelTransfers(ids: [UUID]) { + for transferID in ids { + self.cancelTransfer(id: transferID) + } + } + + /// Cancel all active transfers + @MainActor + func cancelAllTransfers() { + for (_, task) in self.transferTasks { + task.cancel() + } + self.transferTasks.removeAll() + + for (_, client) in self.transferClients { + client.cancel() + } + self.transferClients.removeAll() + + // Clear transfers + self.transfers.removeAll() + } + + /// Remove all completed transfers + @MainActor + func sweepTransfers() { + for t in self.transfers { + if t.done { + self.cancelTransfer(id: t.id) + } + } + } + + /// Register a transfer task + @MainActor + func registerTransferTask(_ task: Task<Void, Never>, transferID: UUID) { + self.transferTasks[transferID] = task + } + + @MainActor + func registerTransferTask(_ task: Task<Void, Never>, transferID: UUID, client: HotlineTransferClient) { + self.transferTasks[transferID] = task + self.transferClients[transferID] = client + } + + /// Unregister a download task (called on completion/failure) + @MainActor + func unregisterTransferTask(for transferID: UUID) { + self.transferTasks.removeValue(forKey: transferID) + self.transferClients.removeValue(forKey: transferID) + } +} |