Skip to content

Commit 23540e4

Browse files
committed
fix nav stack for changing servers, make shorts copy
1 parent 7b2b37e commit 23540e4

File tree

4 files changed

+166
-187
lines changed

4 files changed

+166
-187
lines changed

Django Files/Views/AlbumList.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ struct AlbumListView: View {
9494
}
9595
}
9696
.navigationDestination(for: DFAlbum.self) { album in
97-
FileListView(server: server, albumID: album.id)
97+
FileListView(server: server, albumID: album.id, navigationPath: $navigationPath)
9898
}
9999
.listStyle(.plain)
100100
.refreshable {

Django Files/Views/FileList.swift

Lines changed: 148 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,6 @@ import SwiftUI
99
import SwiftData
1010
import Foundation
1111

12-
13-
struct FileListNavStack: View {
14-
let server: Binding<DjangoFilesSession?>
15-
16-
@State private var navigationPath = NavigationPath()
17-
18-
var body: some View {
19-
if (server.wrappedValue != nil) {
20-
ZStack {
21-
NavigationStack(path: $navigationPath) {
22-
FileListView(server: server, albumID: nil)
23-
}
24-
}
25-
} else {
26-
Label("No server selected.", systemImage: "exclamationmark.triangle")
27-
}
28-
}
29-
}
30-
3112
struct CustomLabel: LabelStyle {
3213
var spacing: Double = 0.0
3314

@@ -141,6 +122,7 @@ struct FileRowView: View {
141122
struct FileListView: View {
142123
let server: Binding<DjangoFilesSession?>
143124
let albumID: Int?
125+
let navigationPath: Binding<NavigationPath>
144126

145127
@State private var files: [DFFile] = []
146128
@State private var currentPage = 1
@@ -151,7 +133,6 @@ struct FileListView: View {
151133

152134
@State private var previewFile: Bool = true
153135
@State private var selectedFile: DFFile? = nil
154-
@State private var navigationPath = NavigationPath()
155136

156137
@State private var showingDeleteConfirmation = false
157138
@State private var fileIDsToDelete: [Int] = []
@@ -172,197 +153,184 @@ struct FileListView: View {
172153
@State private var redirectURLs: [String: String] = [:]
173154

174155
var body: some View {
175-
if server.wrappedValue != nil {
176-
List {
177-
ForEach(files, id: \.id) { file in
178-
NavigationLink(value: file) {
179-
FileRowView(file: file, isPrivate: file.private, hasPassword: (file.password != ""), hasExpiration: (file.expr != ""), serverURL: URL(string: server.wrappedValue!.url)!)
180-
.contextMenu {
181-
fileContextMenu(for: file, isPreviewing: false, isPrivate: file.private, expirationText: $expirationText, passwordText: $passwordText, fileNameText: $fileNameText)
182-
}
183-
}
184-
.id(file.id)
185-
186-
// If this is the last item and we have more pages, load more when it appears
187-
if hasNextPage && file.id == files.last?.id {
188-
Color.clear
189-
.frame(height: 20)
190-
.onAppear {
191-
loadNextPage()
192-
}
193-
}
156+
List {
157+
ForEach(files, id: \.id) { file in
158+
NavigationLink(value: file) {
159+
FileRowView(file: file, isPrivate: file.private, hasPassword: (file.password != ""), hasExpiration: (file.expr != ""), serverURL: URL(string: server.wrappedValue!.url)!)
160+
.contextMenu {
161+
fileContextMenu(for: file, isPreviewing: false, isPrivate: file.private, expirationText: $expirationText, passwordText: $passwordText, fileNameText: $fileNameText)
162+
}
194163
}
164+
.id(file.id)
195165

196-
if isLoading && hasNextPage {
197-
HStack {
198-
ProgressView()
199-
}
166+
if hasNextPage && file.id == files.last?.id {
167+
Color.clear
168+
.frame(height: 20)
169+
.onAppear {
170+
loadNextPage()
171+
}
200172
}
201173
}
202-
.navigationDestination(for: DFFile.self) { file in
203-
ZStack {
204-
if redirectURLs[file.raw] == nil {
205-
ProgressView()
206-
.onAppear {
207-
Task {
208-
await loadRedirectURL(for: file)
209-
}
174+
175+
if isLoading && hasNextPage {
176+
HStack {
177+
ProgressView()
178+
}
179+
}
180+
}
181+
.navigationDestination(for: DFFile.self) { file in
182+
ZStack {
183+
if redirectURLs[file.raw] == nil {
184+
ProgressView()
185+
.onAppear {
186+
Task {
187+
await loadRedirectURL(for: file)
210188
}
211-
} else {
212-
ContentPreview(mimeType: file.mime, fileURL: URL(string: redirectURLs[file.raw]!))
213-
.navigationTitle(file.name)
214-
.navigationBarTitleDisplayMode(.inline)
215-
.toolbar {
216-
ToolbarItem(placement: .navigationBarTrailing) {
217-
Menu {
218-
fileShareMenu(for: file)
219-
} label: {
220-
Image(systemName: "square.and.arrow.up")
221-
}
189+
}
190+
} else {
191+
ContentPreview(mimeType: file.mime, fileURL: URL(string: redirectURLs[file.raw]!))
192+
.navigationTitle(file.name)
193+
.navigationBarTitleDisplayMode(.inline)
194+
.toolbar {
195+
ToolbarItem(placement: .navigationBarTrailing) {
196+
Menu {
197+
fileShareMenu(for: file)
198+
} label: {
199+
Image(systemName: "square.and.arrow.up")
222200
}
223-
ToolbarItem(placement: .navigationBarTrailing) {
224-
Menu {
225-
fileContextMenu(for: file, isPreviewing: true, isPrivate: file.private, expirationText: $expirationText, passwordText: $passwordText, fileNameText: $fileNameText)
226-
} label: {
227-
Image(systemName: "ellipsis.circle")
228-
}
201+
}
202+
ToolbarItem(placement: .navigationBarTrailing) {
203+
Menu {
204+
fileContextMenu(for: file, isPreviewing: true, isPrivate: file.private, expirationText: $expirationText, passwordText: $passwordText, fileNameText: $fileNameText)
205+
} label: {
206+
Image(systemName: "ellipsis.circle")
229207
}
230208
}
231-
}
209+
}
232210
}
233211
}
234-
.onChange(of: selectedFile) { oldValue, newValue in
235-
if let file = newValue {
236-
navigationPath.append(file)
237-
selectedFile = nil // Reset after navigation
238-
}
212+
}
213+
.listStyle(.plain)
214+
.refreshable {
215+
Task {
216+
await refreshFiles()
239217
}
240-
.alert("Delete File", isPresented: $showingDeleteConfirmation) {
241-
Button("Cancel", role: .cancel) {}
242-
Button("Delete", role: .destructive) {
243-
Task {
244-
await deleteFiles(fileIDs: fileIDsToDelete)
245-
246-
// Return to the file list if we're in a detail view
247-
if navigationPath.count > 0 {
248-
navigationPath.removeLast()
249-
}
218+
}
219+
.navigationTitle(server.wrappedValue != nil ? "Files (\(URL(string: server.wrappedValue!.url)?.host ?? "unknown"))" : "Files")
220+
.toolbar {
221+
ToolbarItem(placement: .navigationBarTrailing) {
222+
Menu {
223+
Button(action: {
224+
showingUploadSheet = true
225+
}) {
226+
Label("Upload File", systemImage: "arrow.up.doc")
250227
}
251-
}
252-
} message: {
253-
Text("Are you sure you want to delete \"\(fileNameToDelete)\"?")
254-
}
255-
.alert("Set File Expiration", isPresented: $showingExpirationDialog) {
256-
TextField("Enter expiration", text: $expirationText)
257-
Button("Cancel", role: .cancel) {
258-
fileToExpire = nil
259-
}
260-
Button("Set") {
261-
if let file = fileToExpire {
262-
let expirationValue = expirationText
228+
Button(action: {
263229
Task {
264-
await setFileExpr(file: file, expr: expirationValue)
265-
await MainActor.run {
266-
expirationText = ""
267-
fileToExpire = nil
268-
}
230+
await uploadClipboard()
269231
}
232+
}) {
233+
Label("Upload Clipboard", systemImage: "clipboard")
234+
}
235+
Button(action: {
236+
// Create a short
237+
}) {
238+
Label("Create Short", systemImage: "link.badge.plus")
270239
}
240+
Button(action: {
241+
// Create an Album
242+
}) {
243+
Label("Create Album", systemImage: "photo.badge.plus")
244+
}
245+
} label: {
246+
Image(systemName: "plus")
271247
}
272-
} message: {
273-
Text("Enter time until file expiration. Examples: 1h, 5days, 2y")
274248
}
275-
.alert("Set File Password", isPresented: $showingPasswordDialog) {
276-
TextField("Enter password", text: $passwordText)
277-
Button("Cancel", role: .cancel) {
278-
fileToPassword = nil
279-
}
280-
Button("Set") {
281-
if let file = fileToPassword {
282-
let passwordValue = passwordText // Capture the value
283-
Task {
284-
await setFilePassword(file: file, password: passwordValue)
285-
// Only clear after the API call completes
286-
await MainActor.run {
287-
passwordText = ""
288-
fileToPassword = nil
289-
}
290-
}
249+
}
250+
.sheet(isPresented: $showingUploadSheet,
251+
onDismiss: { Task { await refreshFiles()} }
252+
) {
253+
if let serverInstance = server.wrappedValue {
254+
FileUploadView(server: serverInstance)
255+
}
256+
}
257+
.alert("Delete File", isPresented: $showingDeleteConfirmation) {
258+
Button("Cancel", role: .cancel) {}
259+
Button("Delete", role: .destructive) {
260+
Task {
261+
await deleteFiles(fileIDs: fileIDsToDelete)
262+
263+
// Return to the file list if we're in a detail view
264+
if navigationPath.wrappedValue.count > 0 {
265+
navigationPath.wrappedValue.removeLast()
291266
}
292267
}
293-
} message: {
294-
Text("Enter a password for the file.")
295268
}
296-
.alert("Rename File", isPresented: $showingRenameDialog) {
297-
TextField("New File Name", text: $fileNameText)
298-
Button("Cancel", role: .cancel) {
299-
fileToRename = nil
300-
}
301-
Button("Set") {
302-
if let file = fileToRename {
303-
let fileNameValue = fileNameText // Capture the value
304-
Task {
305-
await renameFile(file: file, name: fileNameValue)
306-
// Only clear after the API call completes
307-
await MainActor.run {
308-
fileNameText = ""
309-
fileToRename = nil
310-
}
269+
} message: {
270+
Text("Are you sure you want to delete \"\(fileNameToDelete)\"?")
271+
}
272+
.alert("Set File Expiration", isPresented: $showingExpirationDialog) {
273+
TextField("Enter expiration", text: $expirationText)
274+
Button("Cancel", role: .cancel) {
275+
fileToExpire = nil
276+
}
277+
Button("Set") {
278+
if let file = fileToExpire {
279+
let expirationValue = expirationText
280+
Task {
281+
await setFileExpr(file: file, expr: expirationValue)
282+
await MainActor.run {
283+
expirationText = ""
284+
fileToExpire = nil
311285
}
312286
}
313287
}
314-
} message: {
315-
Text("Enter a new name for this file.")
316288
}
317-
.sheet(isPresented: $showingUploadSheet,
318-
onDismiss: { Task { await refreshFiles()} }
319-
) {
320-
if let serverInstance = server.wrappedValue {
321-
FileUploadView(server: serverInstance)
322-
}
289+
} message: {
290+
Text("Enter time until file expiration. Examples: 1h, 5days, 2y")
291+
}
292+
.alert("Set File Password", isPresented: $showingPasswordDialog) {
293+
TextField("Enter password", text: $passwordText)
294+
Button("Cancel", role: .cancel) {
295+
fileToPassword = nil
323296
}
324-
.toolbar {
325-
ToolbarItem(placement: .navigationBarTrailing) {
326-
Menu {
327-
Button(action: {
328-
showingUploadSheet = true
329-
}) {
330-
Label("Upload File", systemImage: "arrow.up.doc")
331-
}
332-
Button(action: {
333-
Task {
334-
await uploadClipboard()
335-
}
336-
}) {
337-
Label("Upload Clipboard", systemImage: "clipboard")
338-
}
339-
Button(action: {
340-
// Create a short
341-
}) {
342-
Label("Create Short", systemImage: "link.badge.plus")
343-
}
344-
Button(action: {
345-
// Create an Album
346-
}) {
347-
Label("Create Album", systemImage: "photo.badge.plus")
297+
Button("Set") {
298+
if let file = fileToPassword {
299+
let passwordValue = passwordText
300+
Task {
301+
await setFilePassword(file: file, password: passwordValue)
302+
await MainActor.run {
303+
passwordText = ""
304+
fileToPassword = nil
348305
}
349-
} label: {
350-
Image(systemName: "plus")
351306
}
352307
}
353308
}
354-
.listStyle(.plain)
355-
.refreshable {
356-
Task {
357-
await refreshFiles()
358-
}
309+
} message: {
310+
Text("Enter a password for the file.")
311+
}
312+
.alert("Rename File", isPresented: $showingRenameDialog) {
313+
TextField("New File Name", text: $fileNameText)
314+
Button("Cancel", role: .cancel) {
315+
fileToRename = nil
359316
}
360-
.navigationTitle(server.wrappedValue != nil ? "Files (\(URL(string: server.wrappedValue!.url)?.host ?? "unknown"))" : "Files")
361-
.onAppear {
362-
loadFiles()
317+
Button("Set") {
318+
if let file = fileToRename {
319+
let fileNameValue = fileNameText
320+
Task {
321+
await renameFile(file: file, name: fileNameValue)
322+
await MainActor.run {
323+
fileNameText = ""
324+
fileToRename = nil
325+
}
326+
}
327+
}
363328
}
364-
} else {
365-
Label("No server selected.", systemImage: "exclamationmark.triangle")
329+
} message: {
330+
Text("Enter a new name for this file.")
331+
}
332+
.onAppear {
333+
loadFiles()
366334
}
367335
}
368336

0 commit comments

Comments
 (0)