diff options
| author | Christian Cleberg <[email protected]> | 2026-04-15 16:07:09 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-04-15 16:07:09 -0500 |
| commit | 7d5ca0607c091f76aa29cd6fa8c76cfeb1e02ac8 (patch) | |
| tree | eef9213c86b32d3b1b295bf503577fa362d6f1fc /Hutch/Views/Repositories/LinkedFileSheetView.swift | |
| parent | 06c36c4352f47655cb39a5042a7e5fd475c118e1 (diff) | |
| download | hutch-7d5ca0607c091f76aa29cd6fa8c76cfeb1e02ac8.tar.gz hutch-7d5ca0607c091f76aa29cd6fa8c76cfeb1e02ac8.tar.bz2 hutch-7d5ca0607c091f76aa29cd6fa8c76cfeb1e02ac8.zip | |
fix: fixes dead relative links in md/org with a new single-file viewer when tapped
Fixes: https://todo.sr.ht/~ccleberg/hutch/63
Diffstat (limited to 'Hutch/Views/Repositories/LinkedFileSheetView.swift')
| -rw-r--r-- | Hutch/Views/Repositories/LinkedFileSheetView.swift | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/Hutch/Views/Repositories/LinkedFileSheetView.swift b/Hutch/Views/Repositories/LinkedFileSheetView.swift new file mode 100644 index 0000000..4f176be --- /dev/null +++ b/Hutch/Views/Repositories/LinkedFileSheetView.swift @@ -0,0 +1,85 @@ +import SwiftUI + +/// A sheet that fetches and displays a single repository file by path, +/// using the `repository.path()` GraphQL field — one API call, no tree traversal. +struct LinkedFileSheetView: View { + let rid: String + let service: SRHTService + let client: SRHTClient + let request: LinkedFileRequest + + @AppStorage(AppStorageKeys.wrapRepositoryFileLines) private var wrapLines = false + @Environment(\.dismiss) private var dismiss + + @State private var entry: TreeEntry? + @State private var isLoading = true + @State private var error: String? + + var body: some View { + NavigationStack { + Group { + if isLoading { + SRHTLoadingStateView(message: "Loading \(request.fileName)…") + } else if let error { + SRHTErrorStateView( + title: "Couldn't Load File", + message: error, + retryAction: { await load() } + ) + } else if let entry, let object = entry.object { + fileContentView(entry: entry, object: object) + } else { + ContentUnavailableView( + "File Not Found", + systemImage: "doc.questionmark", + description: Text("\(request.path) could not be found in this repository.") + ) + } + } + .navigationTitle(request.fileName) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Button("Done") { dismiss() } + } + } + } + .task { await load() } + } + + private func load() async { + isLoading = true + error = nil + let vm = FileTreeViewModel(repositoryRid: rid, service: service, client: client) + do { + entry = try await vm.fetchLinkedFile(path: request.path, revspec: request.revspec) + } catch { + self.error = error.userFacingMessage + } + isLoading = false + } + + @ViewBuilder + private func fileContentView(entry: TreeEntry, object: GitObject) -> some View { + switch object { + case .textBlob(let blob): + CodeFileTextView( + text: blob.text ?? "", + fileName: entry.name, + wrapLines: wrapLines + ) + case .binaryBlob: + ContentUnavailableView( + "Binary File", + systemImage: "doc.zipper", + description: Text("Binary files cannot be displayed inline.") + ) + default: + ContentUnavailableView( + "Unknown File", + systemImage: "questionmark.folder", + description: Text("This object type cannot be displayed.") + ) + } + } +} |
