Files
Kisani/Features/Connect/ConnectViewModel.swift

117 lines
3.5 KiB
Swift
Raw Normal View History

import Foundation
enum ConnectField { case host, username, password }
enum ConnectStep: Equatable {
case credentials // not yet authenticated
case folder // authenticated, no destination chosen
case ready // authenticated + valid destination chosen
}
@MainActor
final class ConnectViewModel: ObservableObject {
@Published var host: String
@Published var username: String
@Published var password: String
@Published var remotePath: String
@Published var selectedProtocol: NASProtocol
@Published var isVerifying = false
@Published var isConnected: Bool
@Published var verifyError: String? = nil
@Published var showFolderBrowser = false
init() {
if let conn = ConnectionStore.shared.savedConnection {
host = conn.host
username = conn.username
password = conn.password
remotePath = conn.remotePath
selectedProtocol = conn.nasProtocol
isConnected = true
} else {
host = ""
username = ""
password = ""
remotePath = "/"
selectedProtocol = .smb
isConnected = false
}
}
var step: ConnectStep {
guard isConnected else { return .credentials }
return remotePath == "/" ? .folder : .ready
}
var canProceed: Bool {
switch step {
case .credentials:
return !host.trimmingCharacters(in: .whitespaces).isEmpty
&& !username.isEmpty
&& !password.isEmpty
&& !isVerifying
case .folder, .ready:
return true
}
}
var statusMessage: String {
switch step {
case .credentials:
return verifyError != nil ? verifyError! : "Enter your NAS credentials"
case .folder:
return "Authenticated · select a destination folder"
case .ready:
return "Ready to sync"
}
}
var statusIsError: Bool { verifyError != nil && step == .credentials }
var statusIsPositive: Bool { step == .folder || step == .ready }
func proceed() async {
switch step {
case .credentials:
await verify()
case .folder:
showFolderBrowser = true
case .ready:
break // navigation handled in the view
}
}
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.trimmingCharacters(in: .whitespaces),
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
}
}