Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e9ddfbc

Browse files
committed
codervpn abstraction
1 parent e8de69e commit e9ddfbc

File tree

4 files changed

+103
-30
lines changed

4 files changed

+103
-30
lines changed

Desktop/CoderVPN.swift

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import SwiftUI
2+
3+
protocol CoderVPN: ObservableObject {
4+
var state: CoderVPNState { get }
5+
var data: [AgentRow] { get }
6+
func start() async
7+
func stop() async
8+
}
9+
10+
enum CoderVPNState: Equatable {
11+
case disabled
12+
case connecting
13+
case disconnecting
14+
case connected
15+
case failed(String)
16+
}

Desktop/DesktopApp.swift

+1-7
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,7 @@ import SwiftUI
44
struct DesktopApp: App {
55
var body: some Scene {
66
MenuBarExtra {
7-
VPNMenu(workspaces: [
8-
WorkspaceRowContents(name: "dogfood2", status: .red, copyableDNS: "asdf.coder"),
9-
WorkspaceRowContents(name: "testing-a-very-long-name", status: .green, copyableDNS: "asdf.coder"),
10-
WorkspaceRowContents(name: "opensrc", status: .yellow, copyableDNS: "asdf.coder"),
11-
WorkspaceRowContents(name: "gvisor", status: .gray, copyableDNS: "asdf.coder"),
12-
WorkspaceRowContents(name: "example", status: .gray, copyableDNS: "asdf.coder")
13-
]).frame(width: 256)
7+
VPNMenu(vpnService: PreviewVPN()).frame(width: 256)
148
} label: {
159
let image: NSImage = {
1610
let ratio = $0.size.height / $0.size.width
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import SwiftUI
2+
3+
class PreviewVPN: Desktop.CoderVPN {
4+
@Published var state: Desktop.CoderVPNState = .disabled
5+
@Published var data: [Desktop.AgentRow] = [
6+
AgentRow(id: UUID(), name: "dogfood2", status: .red, copyableDNS: "asdf.coder"),
7+
AgentRow(id: UUID(), name: "testing-a-very-long-name", status: .green, copyableDNS: "asdf.coder"),
8+
AgentRow(id: UUID(), name: "opensrc", status: .yellow, copyableDNS: "asdf.coder"),
9+
AgentRow(id: UUID(), name: "gvisor", status: .gray, copyableDNS: "asdf.coder"),
10+
AgentRow(id: UUID(), name: "example", status: .gray, copyableDNS: "asdf.coder")
11+
]
12+
func start() async {
13+
await MainActor.run {
14+
state = .connecting
15+
}
16+
do {
17+
try await Task.sleep(nanoseconds: 1_000_000_000)
18+
} catch {
19+
await MainActor.run {
20+
state = .failed("Timed out starting CoderVPN")
21+
}
22+
return
23+
}
24+
await MainActor.run {
25+
state = .connected
26+
}
27+
}
28+
29+
func stop() async {
30+
await MainActor.run {
31+
state = .disconnecting
32+
}
33+
do {
34+
try await Task.sleep(nanoseconds: 1_000_000_000) // Simulate network delay
35+
} catch {
36+
await MainActor.run {
37+
state = .failed("Timed out stopping CoderVPN")
38+
}
39+
return
40+
}
41+
await MainActor.run {
42+
state = .disabled
43+
}
44+
}
45+
}

Desktop/VPNMenu.swift

+41-23
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,45 @@
11
import SwiftUI
22

3-
struct VPNMenu: View {
4-
@State private var isVPNOn: Bool = false
5-
let workspaces: [WorkspaceRowContents]
3+
struct VPNMenu<Conn: CoderVPN>: View {
4+
@ObservedObject var vpnService: Conn
5+
66
var body: some View {
77
// Main stack
88
VStack(alignment: .leading) {
99
// CoderVPN Stack
1010
VStack(alignment: .leading, spacing: 10) {
1111
HStack {
12-
Toggle(isOn: self.$isVPNOn) {
12+
Toggle(isOn: Binding(
13+
get: { self.vpnService.state == .connected || self.vpnService.state == .connecting },
14+
set: { isOn in Task {
15+
if isOn { await self.vpnService.start() } else { await self.vpnService.stop() }
16+
}
17+
}
18+
)) {
1319
Text("CoderVPN")
1420
.frame(maxWidth: .infinity, alignment: .leading)
1521
}.toggleStyle(.switch)
22+
.disabled(self.vpnService.state == .connecting || self.vpnService.state == .disconnecting)
1623
}
1724
Divider()
18-
Text("Workspaces")
25+
Text("Workspace Agents")
1926
.font(.headline)
2027
.foregroundColor(.gray)
21-
if !isVPNOn {
22-
Text("Enable CoderVPN to see workspaces").font(.body).foregroundColor(.gray)
28+
if self.vpnService.state == .disabled {
29+
Text("Enable CoderVPN to see agents").font(.body).foregroundColor(.gray)
30+
} else if self.vpnService.state == .connecting || self.vpnService.state == .disconnecting {
31+
HStack {
32+
Spacer()
33+
ProgressView(
34+
self.vpnService.state == .connecting ? "Starting CoderVPN..." : "Stopping CoderVPN..."
35+
).padding()
36+
Spacer()
37+
}
2338
}
2439
}.padding([.horizontal, .top], 15)
25-
if isVPNOn {
26-
ForEach(workspaces) { workspace in
27-
WorkspaceRowView(workspace: workspace).padding(.horizontal, 5)
40+
if self.vpnService.state == .connected {
41+
ForEach(self.vpnService.data) { workspace in
42+
AgentRowView(workspace: workspace).padding(.horizontal, 5)
2843
}
2944
}
3045
// Trailing stack
@@ -33,32 +48,39 @@ struct VPNMenu: View {
3348
RowButtonView {
3449
Text("Create workspace")
3550
EmptyView()
51+
} action: {
52+
// TODO
3653
}
3754
Divider().padding([.horizontal], 10).padding(.vertical, 4)
3855
RowButtonView {
3956
Text("About")
57+
} action: {
58+
// TODO
4059
}
4160
RowButtonView {
4261
Text("Preferences")
62+
} action: {
63+
// TODO
4364
}
4465
RowButtonView {
4566
Text("Sign out")
67+
} action: {
68+
// TODO
4669
}
4770
}.padding([.horizontal, .bottom], 5)
4871
}.padding(.bottom, 5)
49-
5072
}
5173
}
5274

53-
struct WorkspaceRowContents: Identifiable {
54-
let id = UUID()
75+
struct AgentRow: Identifiable {
76+
let id: UUID
5577
let name: String
5678
let status: Color
5779
let copyableDNS: String
5880
}
5981

60-
struct WorkspaceRowView: View {
61-
let workspace: WorkspaceRowContents
82+
struct AgentRowView: View {
83+
let workspace: AgentRow
6284
@State private var nameIsSelected: Bool = false
6385
@State private var copyIsSelected: Bool = false
6486

@@ -117,9 +139,11 @@ struct WorkspaceRowView: View {
117139
struct RowButtonView<Label: View>: View {
118140
@State private var isSelected: Bool = false
119141
@ViewBuilder var label: () -> Label
142+
var action: () -> Void
143+
120144
var body: some View {
121145
Button {
122-
// TODO: Action
146+
action()
123147
} label: {
124148
HStack(spacing: 0) {
125149
label()
@@ -137,11 +161,5 @@ struct RowButtonView<Label: View>: View {
137161
}
138162

139163
#Preview {
140-
VPNMenu(workspaces: [
141-
WorkspaceRowContents(name: "dogfood2", status: .red, copyableDNS: "asdf.coder"),
142-
WorkspaceRowContents(name: "testing-a-very-long-name", status: .green, copyableDNS: "asdf.coder"),
143-
WorkspaceRowContents(name: "opensrc", status: .yellow, copyableDNS: "asdf.coder"),
144-
WorkspaceRowContents(name: "gvisor", status: .gray, copyableDNS: "asdf.coder"),
145-
WorkspaceRowContents(name: "example", status: .gray, copyableDNS: "asdf.coder")
146-
]).frame(width: 256)
164+
VPNMenu(vpnService: PreviewVPN()).frame(width: 256)
147165
}

0 commit comments

Comments
 (0)