5
5
// Created by Michael on 2/14/25.
6
6
//
7
7
8
- import SwiftUI
9
8
import SwiftData
9
+ import SwiftUI
10
10
11
11
struct ContentView : View {
12
12
@Environment ( \. modelContext) private var modelContext
13
13
@Environment ( \. dismiss) private var dismiss
14
-
14
+
15
15
@Query private var items : [ DjangoFilesSession ]
16
16
@State private var showingEditor = false
17
- @State private var columnVisibility = NavigationSplitViewVisibility . detailOnly
17
+ @State private var columnVisibility = NavigationSplitViewVisibility
18
+ . detailOnly
18
19
@State private var selectedServer : DjangoFilesSession ?
19
- @State private var selectedSession : DjangoFilesSession ? // Track session for settings
20
+ @State private var selectedSession : DjangoFilesSession ? // Track session for settings
20
21
@State private var needsRefresh = false // Added to handle refresh after adding server
21
- @State private var itemToDelete : DjangoFilesSession ? // Track item to be deleted
22
- @State private var showingDeleteAlert = false // Track if delete alert is showing
23
-
22
+ @State private var itemToDelete : DjangoFilesSession ? // Track item to be deleted
23
+ @State private var showingDeleteAlert = false // Track if delete alert is showing
24
+
24
25
@State private var token : String ?
25
-
26
+
26
27
@State private var viewingSettings : Bool = false
27
-
28
+
28
29
// stupid work around where we have to show the toolbar on ipad so splitview does not crash due to toolbar state
29
- let toolbarVisibility : Visibility = UIDevice . current. userInterfaceIdiom == . pad ? . visible : . hidden
30
-
30
+ let toolbarVisibility : Visibility =
31
+ UIDevice . current. userInterfaceIdiom == . pad ? . visible : . hidden
32
+
31
33
var body : some View {
32
34
NavigationSplitView ( columnVisibility: $columnVisibility) {
33
35
List ( selection: $selectedServer) {
34
36
ForEach ( items, id: \. self) { item in
35
37
NavigationLink ( value: item) {
36
38
Text ( item. url)
37
- . swipeActions ( ) {
39
+ . swipeActions {
38
40
Button ( role: . destructive) {
39
41
itemToDelete = item
40
42
showingDeleteAlert = true
@@ -56,8 +58,7 @@ struct ContentView: View {
56
58
ToolbarItem {
57
59
Button ( action: {
58
60
self . showingEditor. toggle ( )
59
- } )
60
- {
61
+ } ) {
61
62
Label ( " Add Item " , systemImage: " plus " )
62
63
}
63
64
}
@@ -92,7 +93,7 @@ struct ContentView: View {
92
93
}
93
94
}
94
95
}
95
- . sheet ( isPresented: $showingEditor) {
96
+ . sheet ( isPresented: $showingEditor) {
96
97
SessionEditor ( session: nil )
97
98
. onDisappear {
98
99
if items. count > 0 {
@@ -104,18 +105,21 @@ struct ContentView: View {
104
105
. sheet ( item: $selectedSession) { session in
105
106
SessionSelector ( session: session)
106
107
}
107
- . onAppear ( ) {
108
- selectedServer = items. first ( where: { $0. defaultSession } ) ?? items. first
109
- if items. count == 0 {
108
+ . onAppear {
109
+ selectedServer =
110
+ items. first ( where: { $0. defaultSession } ) ?? items. first
111
+ if items. count == 0 {
110
112
self . showingEditor. toggle ( )
111
113
}
112
114
}
113
115
. frame ( maxWidth: . infinity, maxHeight: . infinity)
114
116
. edgesIgnoringSafeArea ( . all)
115
117
. alert ( " Delete Server " , isPresented: $showingDeleteAlert) {
116
- Button ( " Cancel " , role: . cancel) { }
118
+ Button ( " Cancel " , role: . cancel) { }
117
119
Button ( " Delete " , role: . destructive) {
118
- if let item = itemToDelete, let index = items. firstIndex ( of: item) {
120
+ if let item = itemToDelete,
121
+ let index = items. firstIndex ( of: item)
122
+ {
119
123
deleteItems ( offsets: [ index] )
120
124
if selectedServer == item {
121
125
needsRefresh = true
@@ -124,10 +128,12 @@ struct ContentView: View {
124
128
}
125
129
}
126
130
} message: {
127
- Text ( " Are you sure you want to delete \( URL ( string: itemToDelete? . url ?? " " ) ? . host ?? " this server " ) ? This action cannot be undone. " )
131
+ Text (
132
+ " Are you sure you want to delete \( URL ( string: itemToDelete? . url ?? " " ) ? . host ?? " this server " ) ? This action cannot be undone. "
133
+ )
128
134
}
129
135
}
130
-
136
+
131
137
private func deleteItems( offsets: IndexSet ) {
132
138
withAnimation {
133
139
for index in offsets {
@@ -140,107 +146,111 @@ struct ContentView: View {
140
146
public struct AuthViewContainer : View {
141
147
@Environment ( \. modelContext) private var modelContext
142
148
@Environment ( \. dismiss) private var dismiss
143
- @Environment ( \. presentationMode) private var presentationMode : Binding < PresentationMode >
149
+ @Environment ( \. presentationMode) private var presentationMode :
150
+ Binding < PresentationMode >
144
151
@Query private var items : [ DjangoFilesSession ]
145
-
152
+
146
153
@State private var isAuthViewLoading : Bool = true
147
-
154
+
148
155
var viewingSettings : Binding < Bool >
149
156
let selectedServer : DjangoFilesSession
150
157
var columnVisibility : Binding < NavigationSplitViewVisibility >
151
158
var showingEditor : Binding < Bool >
152
159
var needsRefresh : Binding < Bool >
153
-
160
+
154
161
@State private var authController : AuthController = AuthController ( )
155
-
162
+
156
163
public var body : some View {
157
- if viewingSettings. wrappedValue{
158
- SessionSelector ( session: selectedServer, viewingSelect: viewingSettings)
159
- . onAppear ( ) {
160
- columnVisibility. wrappedValue = . automatic
161
- }
164
+ if viewingSettings. wrappedValue {
165
+ SessionSelector (
166
+ session: selectedServer,
167
+ viewingSelect: viewingSettings
168
+ )
169
+ . onAppear {
170
+ columnVisibility. wrappedValue = . automatic
162
171
}
163
- else if selectedServer. url != " " {
164
- Color . djangoFilesBackground. ignoresSafeArea ( )
165
- . overlay {
172
+ } else if selectedServer. url != " " {
173
+ Color . djangoFilesBackground. ignoresSafeArea ( )
174
+ . overlay {
166
175
AuthView (
167
176
authController: authController,
168
177
httpsUrl: selectedServer. url,
169
- doReset: authController. url? . absoluteString ?? " " != selectedServer. url || !selectedServer. auth,
178
+ doReset: authController. url? . absoluteString ?? " "
179
+ != selectedServer. url || !selectedServer. auth,
170
180
session: selectedServer
171
- )
172
- . onStartedLoading {
173
- isAuthViewLoading = true
181
+ )
182
+ . onStartedLoading {
183
+ isAuthViewLoading = true
184
+ }
185
+ . onCancelled {
186
+ isAuthViewLoading = false
187
+ dismiss ( )
188
+ }
189
+ . onAppear {
190
+ if needsRefresh. wrappedValue {
191
+ authController. reset ( )
192
+ needsRefresh. wrappedValue = false
193
+ }
194
+
195
+ authController. onStartedLoadingAction = {
174
196
}
175
- . onCancelled {
197
+
198
+ authController. onLoadedAction = {
199
+ isAuthViewLoading = false
200
+
201
+ }
202
+ authController. onCancelledAction = {
176
203
isAuthViewLoading = false
177
204
dismiss ( )
178
205
}
179
- . onAppear ( ) {
180
- if needsRefresh. wrappedValue {
181
- authController. reset ( )
182
- needsRefresh. wrappedValue = false
183
- }
184
-
185
- authController. onStartedLoadingAction = {
186
- }
187
-
188
- authController. onLoadedAction = {
189
- isAuthViewLoading = false
190
206
207
+ authController. onSchemeRedirectAction = {
208
+ isAuthViewLoading = false
209
+ guard let resolve = authController. schemeURL else {
210
+ return
191
211
}
192
- authController. onCancelledAction = {
193
- isAuthViewLoading = false
194
- dismiss ( )
195
- }
196
-
197
- authController. onSchemeRedirectAction = {
198
- isAuthViewLoading = false
199
- guard let resolve = authController. schemeURL else {
200
- return
201
- }
202
- switch resolve{
203
- case " serverlist " :
204
- if UIDevice . current. userInterfaceIdiom == . phone{
205
- self . presentationMode. wrappedValue. dismiss ( )
206
- }
207
- columnVisibility. wrappedValue = . all
208
- break
209
- case " serversettings " :
210
- viewingSettings. wrappedValue = true
211
- break
212
- case " logout " :
213
- selectedServer. auth = false
214
- columnVisibility. wrappedValue = . all
215
- modelContext. insert ( selectedServer)
216
- do {
217
- try modelContext. save ( )
218
- } catch {
219
- print ( " Error saving session: \( error) " )
220
- }
212
+ switch resolve {
213
+ case " serverlist " :
214
+ if UIDevice . current. userInterfaceIdiom == . phone
215
+ {
221
216
self . presentationMode. wrappedValue. dismiss ( )
222
- break
223
- default :
224
- return
225
217
}
218
+ columnVisibility. wrappedValue = . all
219
+ break
220
+ case " serversettings " :
221
+ viewingSettings. wrappedValue = true
222
+ break
223
+ case " logout " :
224
+ selectedServer. auth = false
225
+ columnVisibility. wrappedValue = . all
226
+ modelContext. insert ( selectedServer)
227
+ do {
228
+ try modelContext. save ( )
229
+ } catch {
230
+ print ( " Error saving session: \( error) " )
231
+ }
232
+ self . presentationMode. wrappedValue. dismiss ( )
233
+ break
234
+ default :
235
+ return
226
236
}
227
237
}
228
- . overlay {
229
- if isAuthViewLoading {
230
- LoadingView ( ) . frame ( width : 100 , height : 100 )
231
- }
238
+ }
239
+ . overlay {
240
+ if isAuthViewLoading {
241
+ LoadingView ( ) . frame ( width : 100 , height : 100 )
232
242
}
243
+ }
233
244
}
234
245
. ignoresSafeArea ( )
235
246
. edgesIgnoringSafeArea ( . all)
236
247
. frame ( maxWidth: . infinity, maxHeight: . infinity)
237
- }
238
- else {
239
- Text ( " Loading... " )
240
- . onAppear ( ) {
241
- columnVisibility. wrappedValue = . all
242
- }
243
- }
248
+ } else {
249
+ Text ( " Loading... " )
250
+ . onAppear {
251
+ columnVisibility. wrappedValue = . all
252
+ }
253
+ }
244
254
}
245
255
}
246
256
@@ -253,21 +263,25 @@ struct LoadingView: View {
253
263
. stroke ( Color . launchScreenBackground, lineWidth: 5 )
254
264
. rotationEffect ( Angle ( degrees: isLoading ? 360 : 0 ) )
255
265
. opacity ( firstAppear ? 1 : 0 )
256
- . onAppear ( ) {
266
+ . onAppear {
257
267
DispatchQueue . main. async {
258
- if isLoading == false {
259
- withAnimation ( . linear( duration: 1 ) . repeatForever ( autoreverses: false ) ) {
268
+ if isLoading == false {
269
+ withAnimation (
270
+ . linear( duration: 1 ) . repeatForever (
271
+ autoreverses: false
272
+ )
273
+ ) {
260
274
isLoading. toggle ( )
261
275
}
262
276
}
263
- withAnimation ( . easeInOut( duration: 0.25 ) ) {
277
+ withAnimation ( . easeInOut( duration: 0.25 ) ) {
264
278
firstAppear = true
265
279
}
266
280
}
267
281
}
268
- . onDisappear ( ) {
282
+ . onDisappear {
269
283
DispatchQueue . main. async {
270
- withAnimation ( . easeInOut( duration: 0.25 ) ) {
284
+ withAnimation ( . easeInOut( duration: 0.25 ) ) {
271
285
firstAppear = true
272
286
}
273
287
}
0 commit comments