diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-11-27 23:38:04 +0100 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-11-27 23:38:04 +0100 |
| commit | 213710bf5bd6413c747bf126db50816ef5de5a6e (patch) | |
| tree | 912f8cf87955a08077c92fea8ad934f50b7ab975 /Hotline/macOS/Files/FilePreviewQuickLookView.swift | |
| parent | f466b21dc02f78c984ba6748e703f6780a7a0db4 (diff) | |
| parent | 6a95b53616a4abfa306ddce43151cf4fefbd20ed (diff) | |
Merge remote-tracking branch 'upstream/main'
Diffstat (limited to 'Hotline/macOS/Files/FilePreviewQuickLookView.swift')
| -rw-r--r-- | Hotline/macOS/Files/FilePreviewQuickLookView.swift | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/Hotline/macOS/Files/FilePreviewQuickLookView.swift b/Hotline/macOS/Files/FilePreviewQuickLookView.swift new file mode 100644 index 0000000..a504a7a --- /dev/null +++ b/Hotline/macOS/Files/FilePreviewQuickLookView.swift @@ -0,0 +1,114 @@ +import SwiftUI +import UniformTypeIdentifiers + +struct FilePreviewQuickLookView: View { + enum FilePreviewFocus: Hashable { + case window + } + + @Environment(\.controlActiveState) private var controlActiveState + @Environment(\.colorScheme) private var colorScheme + @Environment(\.dismiss) private var dismiss + + @Binding var info: PreviewFileInfo? + @State private var preview: FilePreviewState? = nil + + @FocusState private var focusField: FilePreviewFocus? + + var body: some View { + Group { + if self.preview?.state != .loaded { + VStack(alignment: .center, spacing: 0) { + Spacer() + ProgressView(value: max(0.0, min(1.0, self.preview?.progress ?? 0.0))) + .focusable(false) + .progressViewStyle(.circular) + .controlSize(.extraLarge) + .frame(maxWidth: 300, alignment: .center) + .padding(.bottom, 48) + Spacer() + } + .background(Color(nsColor: .textBackgroundColor)) + .frame(minWidth: 350, maxWidth: .infinity, minHeight: 150, maxHeight: .infinity) + .padding() + } + else { + if let fileURL = self.preview?.fileURL { + QuickLookPreviewView(fileURL: fileURL) + .frame(minWidth: 400, maxWidth: .infinity, minHeight: 400, maxHeight: .infinity) + } + else { + VStack(alignment: .center, spacing: 0) { + Spacer() + + Image(systemName: "eye.trianglebadge.exclamationmark") + .resizable() + .scaledToFit() + .frame(maxWidth: .infinity) + .frame(height: 48) + .padding(.bottom) + Group { + Text("This file type is not previewable") + .bold() + Text("Try downloading and opening this file in another application.") + .foregroundStyle(Color.secondary) + } + .font(.system(size: 14.0)) + .frame(maxWidth: 300) + .multilineTextAlignment(.center) + + Spacer() + Spacer() + } + .frame(minWidth: 350, maxWidth: .infinity, minHeight: 150, maxHeight: .infinity) + .padding() + } + } + } + .focusable() + .focusEffectDisabled() + .background(Color(nsColor: .textBackgroundColor)) + .focused(self.$focusField, equals: .window) + .navigationTitle(self.info?.name ?? "File Preview") + .applyNavigationDocumentIfPresent(self.preview?.fileURL) + .toolbar { + if let fileURL = self.preview?.fileURL { + if let info = info { + ToolbarItem(placement: .primaryAction) { + Button { + FileManager.default.copyToDownloads(from: fileURL, using: info.name, bounceDock: true) + } label: { + Label("Download File...", systemImage: "arrow.down") + } + .help("Download File") + } + } + } + } + .task { + if let info = self.info { + self.preview = FilePreviewState(info: info) + self.preview?.download() + } + } + .onAppear { + guard self.info != nil else { + self.dismiss() + return + } + + self.focusField = .window + } + .onDisappear { + self.preview?.cancel() + self.preview?.cleanup() + self.dismiss() + } + .onChange(of: self.preview?.state) { + if self.preview?.state == .failed { + self.dismiss() + } + } + .preferredColorScheme(.dark) + } +} |