@@ -23,6 +23,13 @@ struct FileUploadView: View {
23
23
24
24
@State private var uploadPrivate : Bool = false
25
25
26
+ // Album selection states
27
+ @State private var albums : [ DFAlbum ] = [ ]
28
+ @State private var searchText : String = " "
29
+ @State private var selectedAlbum : DFAlbum ?
30
+ @State private var isLoadingAlbums : Bool = false
31
+ @FocusState private var isSearchFocused : Bool
32
+
26
33
// Audio recording states
27
34
@State private var audioRecorder : AVAudioRecorder ?
28
35
@State private var isRecording : Bool = false
@@ -32,6 +39,60 @@ struct FileUploadView: View {
32
39
NavigationView {
33
40
VStack ( spacing: 20 ) {
34
41
Toggle ( " Make Private " , isOn: $uploadPrivate)
42
+
43
+ // Album Selection
44
+ VStack ( alignment: . leading) {
45
+ TextField ( " Search Albums " , text: $searchText)
46
+ . textFieldStyle ( RoundedBorderTextFieldStyle ( ) )
47
+ . focused ( $isSearchFocused)
48
+ . onChange ( of: searchText) { _, _ in
49
+ if searchText. isEmpty {
50
+ selectedAlbum = nil
51
+ }
52
+ }
53
+
54
+ if !searchText. isEmpty && ( isSearchFocused || selectedAlbum == nil ) {
55
+ ScrollView {
56
+ LazyVStack ( alignment: . leading) {
57
+ ForEach ( albums. filter { album in
58
+ album. name. localizedCaseInsensitiveContains ( searchText)
59
+ } ) { album in
60
+ Button ( action: {
61
+ selectedAlbum = album
62
+ searchText = album. name
63
+ isSearchFocused = false
64
+ } ) {
65
+ Text ( album. name)
66
+ . foregroundColor ( . primary)
67
+ . padding ( . vertical, 8 )
68
+ . frame ( maxWidth: . infinity, alignment: . leading)
69
+ }
70
+ Divider ( )
71
+ }
72
+ }
73
+ }
74
+ . frame ( maxHeight: 200 )
75
+ . background ( Color ( . systemBackground) )
76
+ . cornerRadius ( 8 )
77
+ . shadow ( radius: 2 )
78
+ }
79
+
80
+ if let album = selectedAlbum {
81
+ HStack {
82
+ Text ( " Selected Album: \( album. name) " )
83
+ . foregroundColor ( . secondary)
84
+ Spacer ( )
85
+ Button ( action: {
86
+ selectedAlbum = nil
87
+ searchText = " "
88
+ } ) {
89
+ Image ( systemName: " xmark.circle.fill " )
90
+ . foregroundColor ( . gray)
91
+ }
92
+ }
93
+ . padding ( . vertical, 4 )
94
+ }
95
+ }
35
96
36
97
// Audio Recording Button
37
98
Button ( action: {
@@ -133,6 +194,9 @@ struct FileUploadView: View {
133
194
await uploadPhotos ( newValue)
134
195
}
135
196
}
197
+ . task {
198
+ await loadAlbums ( )
199
+ }
136
200
}
137
201
}
138
202
@@ -147,7 +211,11 @@ struct FileUploadView: View {
147
211
uploadProgress = progress
148
212
}
149
213
150
- _ = await api. uploadFile ( url: tempURL, privateUpload: uploadPrivate, taskDelegate: delegate)
214
+ if let albumId = selectedAlbum? . id {
215
+ _ = await api. uploadFile ( url: tempURL, albums: String ( albumId) , privateUpload: uploadPrivate, taskDelegate: delegate)
216
+ } else {
217
+ _ = await api. uploadFile ( url: tempURL, privateUpload: uploadPrivate, taskDelegate: delegate)
218
+ }
151
219
try ? FileManager . default. removeItem ( at: tempURL)
152
220
}
153
221
@@ -170,7 +238,11 @@ struct FileUploadView: View {
170
238
uploadProgress = ( Double ( index) + progress) / totalItems
171
239
}
172
240
173
- _ = await api. uploadFile ( url: tempURL, privateUpload: uploadPrivate, taskDelegate: delegate)
241
+ if let albumId = selectedAlbum? . id {
242
+ _ = await api. uploadFile ( url: tempURL, albums: String ( albumId) , privateUpload: uploadPrivate, taskDelegate: delegate)
243
+ } else {
244
+ _ = await api. uploadFile ( url: tempURL, privateUpload: uploadPrivate, taskDelegate: delegate)
245
+ }
174
246
try ? FileManager . default. removeItem ( at: tempURL)
175
247
}
176
248
}
@@ -191,7 +263,11 @@ struct FileUploadView: View {
191
263
uploadProgress = ( Double ( index) + progress) / totalFiles
192
264
}
193
265
194
- _ = await api. uploadFile ( url: url, privateUpload: uploadPrivate, taskDelegate: delegate)
266
+ if let albumId = selectedAlbum? . id {
267
+ _ = await api. uploadFile ( url: url, albums: String ( albumId) , privateUpload: uploadPrivate, taskDelegate: delegate)
268
+ } else {
269
+ _ = await api. uploadFile ( url: url, privateUpload: uploadPrivate, taskDelegate: delegate)
270
+ }
195
271
}
196
272
197
273
isUploading = false
@@ -256,13 +332,26 @@ struct FileUploadView: View {
256
332
uploadProgress = progress
257
333
}
258
334
259
- _ = await api. uploadFile ( url: url, privateUpload: uploadPrivate, taskDelegate: delegate)
335
+ if let albumId = selectedAlbum? . id {
336
+ _ = await api. uploadFile ( url: url, albums: String ( albumId) , privateUpload: uploadPrivate, taskDelegate: delegate)
337
+ } else {
338
+ _ = await api. uploadFile ( url: url, privateUpload: uploadPrivate, taskDelegate: delegate)
339
+ }
260
340
try ? FileManager . default. removeItem ( at: url)
261
341
262
342
isUploading = false
263
343
recordingURL = nil
264
344
dismiss ( )
265
345
}
346
+
347
+ private func loadAlbums( ) async {
348
+ isLoadingAlbums = true
349
+ let api = DFAPI ( url: URL ( string: server. url) !, token: server. token)
350
+ if let response = await api. getAlbums ( ) {
351
+ albums = response. albums
352
+ }
353
+ isLoadingAlbums = false
354
+ }
266
355
}
267
356
268
357
class UploadProgressDelegate : NSObject , URLSessionTaskDelegate {
0 commit comments