import Foundation enum ConnectField { case host, username, password, folder } enum FieldState { case idle, valid, invalid } @MainActor final class ConnectViewModel: ObservableObject { @Published var host = "" @Published var username = "" @Published var password = "" @Published var remotePath = "/" @Published var selectedProtocol: NASProtocol = .smb @Published var isVerifying = false @Published var isConnected = false @Published var verifyError: String? = nil @Published var showFolderBrowser = false var fieldState: FieldState { isConnected ? .valid : (verifyError != nil ? .invalid : .idle) } var canConnect: Bool { !host.isEmpty && !username.isEmpty && !password.isEmpty && !isVerifying } func verify() async { let service: any NASTransferProtocol = selectedProtocol == .smb ? SMBService() : SFTPService() await verifyWith(transfer: service) } func verifyWith(transfer: any NASTransferProtocol) async { isVerifying = true isConnected = false verifyError = nil let connection = NASConnection( host: host, nasProtocol: selectedProtocol, username: username, password: password, remotePath: remotePath ) do { try await transfer.connect(to: connection.host, port: connection.port, username: connection.username, password: connection.password) transfer.disconnect() isConnected = true ConnectionStore.shared.savedConnection = connection } catch let e as BackupError { verifyError = e.errorDescription } catch { verifyError = error.localizedDescription } isVerifying = false } }