-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathFileSyncSessionModal.swift
100 lines (95 loc) · 3.8 KB
/
FileSyncSessionModal.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import SwiftUI
import VPNLib
struct FileSyncSessionModal<VPN: VPNService, FS: FileSyncDaemon>: View {
var existingSession: FileSyncSession?
@Environment(\.dismiss) private var dismiss
@EnvironmentObject private var vpn: VPN
@EnvironmentObject private var fileSync: FS
@State private var localPath: String = ""
@State private var chosenAgent: String?
@State private var remotePath: String = ""
@State private var loading: Bool = false
@State private var createError: DaemonError?
var body: some View {
let agents = vpn.menuState.onlineAgents
VStack(spacing: 0) {
Form {
Section {
HStack(spacing: 5) {
TextField("Local Path", text: $localPath)
Spacer()
Button {
let panel = NSOpenPanel()
panel.directoryURL = FileManager.default.homeDirectoryForCurrentUser
panel.allowsMultipleSelection = false
panel.canChooseDirectories = true
panel.canChooseFiles = false
if panel.runModal() == .OK {
localPath = panel.url?.path(percentEncoded: false) ?? "<none>"
}
} label: {
Image(systemName: "folder")
}
}
}
Section {
Picker("Workspace", selection: $chosenAgent) {
ForEach(agents, id: \.id) { agent in
Text(agent.primaryHost!).tag(agent.primaryHost!)
}
// HACK: Silence error logs for no-selection.
Divider().tag(nil as String?)
}
}
Section {
TextField("Remote Path", text: $remotePath)
}
}.formStyle(.grouped).scrollDisabled(true).padding(.horizontal)
Divider()
HStack {
Spacer()
Button("Cancel", action: { dismiss() }).keyboardShortcut(.cancelAction)
Button(existingSession == nil ? "Add" : "Save") { Task { await submit() }}
.keyboardShortcut(.defaultAction)
.disabled(localPath.isEmpty || remotePath.isEmpty || chosenAgent == nil)
}.padding(20)
}.onAppear {
if let existingSession {
localPath = existingSession.alphaPath
chosenAgent = agents.first { $0.primaryHost == existingSession.agentHost }?.primaryHost
remotePath = existingSession.betaPath
} else {
// Set the picker to the first agent by default
chosenAgent = agents.first?.primaryHost
}
}.disabled(loading)
.alert("Error", isPresented: Binding(
get: { createError != nil },
set: { if !$0 { createError = nil } }
)) {} message: {
Text(createError?.description ?? "An unknown error occurred.")
}
}
func submit() async {
createError = nil
guard let chosenAgent else {
return
}
loading = true
defer { loading = false }
do throws(DaemonError) {
if let existingSession {
try await fileSync.deleteSessions(ids: [existingSession.id])
}
try await fileSync.createSession(
localPath: localPath,
agentHost: chosenAgent,
remotePath: remotePath
)
} catch {
createError = error
return
}
dismiss()
}
}