@@ -10,7 +10,7 @@ struct FileSyncConfig<VPN: VPNService, FS: FileSyncDaemon>: View {
1010 @State private var editingSession : FileSyncSession ?
1111
1212 @State private var loading : Bool = false
13- @State private var deleteError : DaemonError ?
13+ @State private var actionError : DaemonError ?
1414 @State private var isVisible : Bool = false
1515 @State private var dontRetry : Bool = false
1616
@@ -50,14 +50,14 @@ struct FileSyncConfig<VPN: VPNService, FS: FileSyncDaemon>: View {
5050 FileSyncSessionModal < VPN , FS > ( existingSession: session)
5151 . frame ( width: 700 )
5252 } . alert ( " Error " , isPresented: Binding (
53- get: { deleteError != nil } ,
53+ get: { actionError != nil } ,
5454 set: { isPresented in
5555 if !isPresented {
56- deleteError = nil
56+ actionError = nil
5757 }
5858 }
5959 ) ) { } message: {
60- Text ( deleteError ? . description ?? " An unknown error occurred. " )
60+ Text ( actionError ? . description ?? " An unknown error occurred. " )
6161 } . alert ( " Error " , isPresented: Binding (
6262 // We only show the alert if the file config window is open
6363 // Users will see the alert symbol on the menu bar to prompt them to
@@ -118,7 +118,7 @@ struct FileSyncConfig<VPN: VPNService, FS: FileSyncDaemon>: View {
118118 addingNewSession = true
119119 } label: {
120120 Image ( systemName: " plus " )
121- . frame ( width: 24 , height: 24 )
121+ . frame ( width: 24 , height: 24 ) . help ( " Create " )
122122 } . disabled ( vpn. menuState. agents. isEmpty)
123123 Divider ( )
124124 Button {
@@ -133,43 +133,72 @@ struct FileSyncConfig<VPN: VPNService, FS: FileSyncDaemon>: View {
133133 await fileSync. stop ( )
134134 }
135135 } catch {
136- deleteError = error
136+ actionError = error
137137 }
138138 selection = nil
139139 }
140140 } label: {
141- Image ( systemName: " minus " ) . frame ( width: 24 , height: 24 )
141+ Image ( systemName: " minus " ) . frame ( width: 24 , height: 24 ) . help ( " Delete " )
142142 } . disabled ( selection == nil )
143- if let selection {
144- if let selectedSession = fileSync. sessionState. first ( where: { $0. id == selection } ) {
145- Divider ( )
146- Button {
147- Task {
148- // TODO: Support pausing & resuming multiple sessions at once
149- loading = true
150- defer { loading = false }
143+ sessionControls
144+ }
145+ . buttonStyle ( . borderless)
146+ }
147+ . background ( . primary. opacity ( 0.04 ) )
148+ . fixedSize ( horizontal: false , vertical: true )
149+ }
150+
151+ var sessionControls : some View {
152+ Group {
153+ if let selection {
154+ if let selectedSession = fileSync. sessionState. first ( where: { $0. id == selection } ) {
155+ Divider ( )
156+ Button {
157+ Task {
158+ // TODO: Support pausing & resuming multiple sessions at once
159+ loading = true
160+ defer { loading = false }
161+ do throws ( DaemonError) {
151162 switch selectedSession. status {
152- case . paused:
163+ case . paused, . error( . haltedOnRootEmptied) ,
164+ . error( . haltedOnRootDeletion) ,
165+ . error( . haltedOnRootTypeChange) :
153166 try await fileSync. resumeSessions ( ids: [ selectedSession. id] )
154167 default :
155168 try await fileSync. pauseSessions ( ids: [ selectedSession. id] )
156169 }
170+ } catch {
171+ actionError = error
157172 }
158- } label: {
159- switch selectedSession. status {
160- case . paused:
161- Image ( systemName: " play " ) . frame ( width: 24 , height: 24 )
162- default :
163- Image ( systemName: " pause " ) . frame ( width: 24 , height: 24 )
173+ }
174+ } label: {
175+ switch selectedSession. status {
176+ case . paused, . error( . haltedOnRootEmptied) ,
177+ . error( . haltedOnRootDeletion) ,
178+ . error( . haltedOnRootTypeChange) :
179+ Image ( systemName: " play " ) . frame ( width: 24 , height: 24 ) . help ( " Pause " )
180+ default :
181+ Image ( systemName: " pause " ) . frame ( width: 24 , height: 24 ) . help ( " Resume " )
182+ }
183+ }
184+ Divider ( )
185+ Button {
186+ Task {
187+ // TODO: Support restarting multiple sessions at once
188+ loading = true
189+ defer { loading = false }
190+ do throws ( DaemonError) {
191+ try await fileSync. resetSessions ( ids: [ selectedSession. id] )
192+ } catch {
193+ actionError = error
164194 }
165195 }
196+ } label: {
197+ Image ( systemName: " arrow.clockwise " ) . frame ( width: 24 , height: 24 ) . help ( " Reset " )
166198 }
167199 }
168200 }
169- . buttonStyle ( . borderless)
170201 }
171- . background ( . primary. opacity ( 0.04 ) )
172- . fixedSize ( horizontal: false , vertical: true )
173202 }
174203}
175204
0 commit comments