Skip to content

Commit bd5638d

Browse files
committed
feat: add progress messages when creating sync sessions
1 parent e96fc49 commit bd5638d

File tree

7 files changed

+34
-24
lines changed

7 files changed

+34
-24
lines changed

Coder-Desktop/Coder-Desktop/Preview Content/PreviewFileSync.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import VPNLib
33
@MainActor
44
final class PreviewFileSync: FileSyncDaemon {
55
var logFile: URL = .init(filePath: "~/log.txt")!
6+
var lastPromptMessage: String?
67

78
var sessionState: [VPNLib.FileSyncSession] = []
89

Coder-Desktop/Coder-Desktop/Preview Content/PreviewVPN.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,25 @@ final class PreviewVPN: Coder_Desktop.VPNService {
66
@Published var state: Coder_Desktop.VPNServiceState = .connected
77
@Published var menuState: VPNMenuState = .init(agents: [
88
UUID(): Agent(id: UUID(), name: "dev", status: .error, hosts: ["asdf.coder"], wsName: "dogfood2",
9-
wsID: UUID()),
9+
wsID: UUID(), primaryHost: "asdf.coder"),
1010
UUID(): Agent(id: UUID(), name: "dev", status: .okay, hosts: ["asdf.coder"],
11-
wsName: "testing-a-very-long-name", wsID: UUID()),
11+
wsName: "testing-a-very-long-name", wsID: UUID(), primaryHost: "asdf.coder"),
1212
UUID(): Agent(id: UUID(), name: "dev", status: .warn, hosts: ["asdf.coder"], wsName: "opensrc",
13-
wsID: UUID()),
13+
wsID: UUID(), primaryHost: "asdf.coder"),
1414
UUID(): Agent(id: UUID(), name: "dev", status: .off, hosts: ["asdf.coder"], wsName: "gvisor",
15-
wsID: UUID()),
15+
wsID: UUID(), primaryHost: "asdf.coder"),
1616
UUID(): Agent(id: UUID(), name: "dev", status: .off, hosts: ["asdf.coder"], wsName: "example",
17-
wsID: UUID()),
17+
wsID: UUID(), primaryHost: "asdf.coder"),
1818
UUID(): Agent(id: UUID(), name: "dev", status: .error, hosts: ["asdf.coder"], wsName: "dogfood2",
19-
wsID: UUID()),
19+
wsID: UUID(), primaryHost: "asdf.coder"),
2020
UUID(): Agent(id: UUID(), name: "dev", status: .okay, hosts: ["asdf.coder"],
21-
wsName: "testing-a-very-long-name", wsID: UUID()),
21+
wsName: "testing-a-very-long-name", wsID: UUID(), primaryHost: "asdf.coder"),
2222
UUID(): Agent(id: UUID(), name: "dev", status: .warn, hosts: ["asdf.coder"], wsName: "opensrc",
23-
wsID: UUID()),
23+
wsID: UUID(), primaryHost: "asdf.coder"),
2424
UUID(): Agent(id: UUID(), name: "dev", status: .off, hosts: ["asdf.coder"], wsName: "gvisor",
25-
wsID: UUID()),
25+
wsID: UUID(), primaryHost: "asdf.coder"),
2626
UUID(): Agent(id: UUID(), name: "dev", status: .off, hosts: ["asdf.coder"], wsName: "example",
27-
wsID: UUID()),
27+
wsID: UUID(), primaryHost: "asdf.coder"),
2828
], workspaces: [:])
2929
let shouldFail: Bool
3030
let longError = "This is a long error to test the UI with long error messages"

Coder-Desktop/Coder-Desktop/VPN/MenuState.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ struct Agent: Identifiable, Equatable, Comparable, Hashable {
1818
return lhs.wsName.localizedCompare(rhs.wsName) == .orderedAscending
1919
}
2020

21-
// Hosts arrive sorted by length, the shortest looks best in the UI.
22-
var primaryHost: String? { hosts.first }
21+
let primaryHost: String
2322
}
2423

2524
enum AgentStatus: Int, Equatable, Comparable {
@@ -69,6 +68,9 @@ struct VPNMenuState {
6968
invalidAgents.append(agent)
7069
return
7170
}
71+
// Remove trailing dot if present
72+
let nonEmptyHosts = agent.fqdn.map { $0.hasSuffix(".") ? String($0.dropLast()) : $0 }
73+
7274
// An existing agent with the same name, belonging to the same workspace
7375
// is from a previous workspace build, and should be removed.
7476
agents.filter { $0.value.name == agent.name && $0.value.wsID == wsID }
@@ -81,10 +83,11 @@ struct VPNMenuState {
8183
name: agent.name,
8284
// If last handshake was not within last five minutes, the agent is unhealthy
8385
status: agent.lastHandshake.date > Date.now.addingTimeInterval(-300) ? .okay : .warn,
84-
// Remove trailing dot if present
85-
hosts: agent.fqdn.map { $0.hasSuffix(".") ? String($0.dropLast()) : $0 },
86+
hosts: nonEmptyHosts,
8687
wsName: workspace.name,
87-
wsID: wsID
88+
wsID: wsID,
89+
// Hosts arrive sorted by length, the shortest looks best in the UI.
90+
primaryHost: nonEmptyHosts.first!,
8891
)
8992
}
9093

@@ -135,9 +138,7 @@ struct VPNMenuState {
135138
return items.sorted()
136139
}
137140

138-
var onlineAgents: [Agent] {
139-
agents.map(\.value).filter { $0.primaryHost != nil }
140-
}
141+
var onlineAgents: [Agent] { agents.map(\.value) }
141142

142143
mutating func clear() {
143144
agents.removeAll()

Coder-Desktop/Coder-Desktop/Views/FileSync/FileSyncSessionModal.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct FileSyncSessionModal<VPN: VPNService, FS: FileSyncDaemon>: View {
4040
Section {
4141
Picker("Workspace", selection: $remoteHostname) {
4242
ForEach(agents, id: \.id) { agent in
43-
Text(agent.primaryHost!).tag(agent.primaryHost!)
43+
Text(agent.primaryHost).tag(agent.primaryHost)
4444
}
4545
// HACK: Silence error logs for no-selection.
4646
Divider().tag(nil as String?)
@@ -62,6 +62,9 @@ struct FileSyncSessionModal<VPN: VPNService, FS: FileSyncDaemon>: View {
6262
Divider()
6363
HStack {
6464
Spacer()
65+
if let lastMessage = fileSync.lastPromptMessage {
66+
Text(lastMessage).foregroundStyle(.secondary)
67+
}
6568
Button("Cancel", action: { dismiss() }).keyboardShortcut(.cancelAction)
6669
Button(existingSession == nil ? "Add" : "Save") { Task { await submit() }}
6770
.keyboardShortcut(.defaultAction)

Coder-Desktop/Coder-Desktop/Views/VPN/VPNMenuItem.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ struct MenuItemView: View {
6666

6767
private var itemName: AttributedString {
6868
let name = switch item {
69-
case let .agent(agent): agent.primaryHost ?? "\(item.wsName).\(state.hostnameSuffix)"
69+
case let .agent(agent): agent.primaryHost
7070
case .offlineWorkspace: "\(item.wsName).\(state.hostnameSuffix)"
7171
}
7272

@@ -103,10 +103,10 @@ struct MenuItemView: View {
103103
}
104104
Spacer()
105105
}.buttonStyle(.plain)
106-
if case let .agent(agent) = item, let copyableDNS = agent.primaryHost {
106+
if case let .agent(agent) = item {
107107
Button {
108108
NSPasteboard.general.clearContents()
109-
NSPasteboard.general.setString(copyableDNS, forType: .string)
109+
NSPasteboard.general.setString(agent.primaryHost, forType: .string)
110110
} label: {
111111
Image(systemName: "doc.on.doc")
112112
.symbolVariant(.fill)
@@ -143,7 +143,6 @@ struct MenuItemView: View {
143143
// If this menu item is an agent, and the user is logged in
144144
if case let .agent(agent) = item,
145145
let client = state.client,
146-
let host = agent.primaryHost,
147146
let baseAccessURL = state.baseAccessURL,
148147
// Like the CLI, we'll re-use the existing session token to populate the URL
149148
let sessionToken = state.sessionToken
@@ -166,7 +165,7 @@ struct MenuItemView: View {
166165
.flatMap(\.self)
167166
.first(where: { $0.id == agent.id })
168167
{
169-
apps = agentToApps(logger, wsAgent, host, baseAccessURL, sessionToken)
168+
apps = agentToApps(logger, wsAgent, agent.primaryHost, baseAccessURL, sessionToken)
170169
} else {
171170
logger.error("Could not find agent '\(agent.id)' in workspace '\(item.wsName)' resources")
172171
}

Coder-Desktop/VPNLib/FileSync/FileSyncDaemon.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public protocol FileSyncDaemon: ObservableObject {
1111
var state: DaemonState { get }
1212
var sessionState: [FileSyncSession] { get }
1313
var logFile: URL { get }
14+
var lastPromptMessage: String? { get }
1415
func tryStart() async
1516
func stop() async
1617
func refreshSessions() async
@@ -47,6 +48,8 @@ public class MutagenDaemon: FileSyncDaemon {
4748

4849
public let logFile: URL
4950

51+
@Published public var lastPromptMessage: String?
52+
5053
// Managing sync sessions could take a while, especially with prompting
5154
let sessionMgmtReqTimeout: TimeAmount = .seconds(15)
5255

Coder-Desktop/VPNLib/FileSync/FileSyncPrompting.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ extension MutagenDaemon {
2828
try initResp.ensureValid(first: true, allowPrompts: allowPrompts)
2929

3030
Task.detached(priority: .background) {
31+
defer { Task { @MainActor in self.lastPromptMessage = nil } }
3132
do {
3233
while let msg = try await iter.next() {
3334
try msg.ensureValid(first: false, allowPrompts: allowPrompts)
@@ -39,6 +40,8 @@ extension MutagenDaemon {
3940
}
4041
// Any other messages that require a non-empty response will
4142
// cause the create op to fail, showing an error. This is ok for now.
43+
} else {
44+
Task { @MainActor in self.lastPromptMessage = msg.message }
4245
}
4346
try await stream.requestStream.send(reply)
4447
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy