11import 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+
66var body : some View {
77 // Main stack
88VStack ( alignment: . leading) {
99 // CoderVPN Stack
1010VStack ( alignment: . leading, spacing: 10 ) {
1111HStack {
12- Toggle ( isOn: self . $isVPNOn) {
12+ Toggle ( isOn: Binding (
13+ get: { self . vpnService. state== . connected ||self . vpnService. state== . connecting} ,
14+ set: { isOnin Task {
15+ if isOn{ await self . vpnService. start ( ) } else { await self . vpnService. stop ( ) }
16+ }
17+ }
18+ ) ) {
1319Text ( " CoderVPN " )
1420. frame ( maxWidth: . infinity, alignment: . leading)
1521} . toggleStyle ( . switch)
22+ . disabled ( self . vpnService. state== . connecting ||self . vpnService. state== . disconnecting)
1623}
1724Divider ( )
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 ) { workspacein
27- WorkspaceRowView ( workspace: workspace) . padding ( . horizontal, 5 )
40+ if self . vpnService . state == . connected {
41+ ForEach ( self . vpnService . data ) { workspacein
42+ AgentRowView ( workspace: workspace) . padding ( . horizontal, 5 )
2843}
2944}
3045 // Trailing stack
@@ -33,32 +48,39 @@ struct VPNMenu: View {
3348RowButtonView {
3449Text ( " Create workspace " )
3550EmptyView ( )
51+ } action: {
52+ // TODO
3653}
3754Divider ( ) . padding ( [ . horizontal] , 10 ) . padding ( . vertical, 4 )
3855RowButtonView {
3956Text ( " About " )
57+ } action: {
58+ // TODO
4059}
4160RowButtonView {
4261Text ( " Preferences " )
62+ } action: {
63+ // TODO
4364}
4465RowButtonView {
4566Text ( " 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
5577let name : String
5678let status : Color
5779let 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 {
117139struct RowButtonView < Label: View > : View {
118140@State private var isSelected : Bool = false
119141@ViewBuilder var label : ( ) -> Label
142+ var action : ( ) -> Void
143+
120144var body : some View {
121145Button {
122- // TODO: Action
146+ action ( )
123147} label: {
124148HStack ( spacing: 0 ) {
125149label ( )
@@ -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}