// SPDX-FileCopyrightText: 2026 Kaede Akino // SPDX-License-Identifier: GPL-3.0-only import Foundation import TermindDomain /// Persist settings before changing the controls or the application-wide transfer queue. @Observable public final class SFTPSettingsModel { public private(set) var preferences = SFTPPreferences() public private(set) var storageError: String? private let persistence: (any SFTPPreferencesPersisting)? public var didChange: ((SFTPPreferences) -> Void)? public init(persistence: (any SFTPPreferencesPersisting)? = nil) { self.persistence = persistence do { if let persistence { preferences = try persistence.loadSFTP().normalized } } catch { storageError = error.localizedDescription } } @discardableResult public func set(_ value: Int, for keyPath: WritableKeyPath) -> Bool { var next = preferences next[keyPath: keyPath] = value next = next.normalized guard next != preferences else { return true } do { try persistence?.saveSFTP(next) applyRemoteSnapshot(next) return true } catch { storageError = error.localizedDescription return false } } @discardableResult public func setStrategy(_ value: SFTPConcurrencyStrategy) -> Bool { var next = preferences next.strategy = value guard next != preferences else { return true } do { try persistence?.saveSFTP(next) applyRemoteSnapshot(next) return true } catch { storageError = error.localizedDescription return false } } public func applyRemoteSnapshot(_ value: SFTPPreferences) { let next = value.normalized let changed = preferences != next preferences = next storageError = nil if changed { didChange?(next) } } }