From f6831ec02bf9f0daa27eb0f65e25803a0ea11917 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Tue, 16 May 2023 11:25:28 -0400 Subject: [PATCH] Add QuickLook fallback for showing unknown attachments in the gallery Closes #169 --- Tusker.xcodeproj/project.pbxproj | 4 ++ .../GalleryViewController.swift | 2 +- .../GalleryFallbackViewController.swift | 71 +++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 Tusker/Screens/Large Image/GalleryFallbackViewController.swift diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index e5fc1915..b1a2861c 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -304,6 +304,7 @@ D6D79F532A0FFE3200AB2315 /* ToggleableButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F522A0FFE3200AB2315 /* ToggleableButton.swift */; }; D6D79F572A1160B800AB2315 /* AccountDisplayNameLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F562A1160B800AB2315 /* AccountDisplayNameLabel.swift */; }; D6D79F592A13293200AB2315 /* BackgroundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F582A13293200AB2315 /* BackgroundManager.swift */; }; + D6D79F5B2A13D22B00AB2315 /* GalleryFallbackViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D79F5A2A13D22B00AB2315 /* GalleryFallbackViewController.swift */; }; D6D94955298963A900C59229 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D94954298963A900C59229 /* Colors.swift */; }; D6D9498D298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D9498C298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift */; }; D6D9498F298EB79400C59229 /* CopyableLable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D9498E298EB79400C59229 /* CopyableLable.swift */; }; @@ -706,6 +707,7 @@ D6D79F522A0FFE3200AB2315 /* ToggleableButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleableButton.swift; sourceTree = ""; }; D6D79F562A1160B800AB2315 /* AccountDisplayNameLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDisplayNameLabel.swift; sourceTree = ""; }; D6D79F582A13293200AB2315 /* BackgroundManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundManager.swift; sourceTree = ""; }; + D6D79F5A2A13D22B00AB2315 /* GalleryFallbackViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GalleryFallbackViewController.swift; sourceTree = ""; }; D6D94954298963A900C59229 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; }; D6D9498C298CBB4000C59229 /* TrendingStatusCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingStatusCollectionViewCell.swift; sourceTree = ""; }; D6D9498E298EB79400C59229 /* CopyableLable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyableLable.swift; sourceTree = ""; }; @@ -1092,6 +1094,7 @@ D6C94D862139E62700CB5196 /* LargeImageViewController.swift */, D681A299249AD62D0085E54E /* LargeImageContentView.swift */, 041160FE22B442870030A9B7 /* LoadingLargeImageViewController.swift */, + D6D79F5A2A13D22B00AB2315 /* GalleryFallbackViewController.swift */, ); path = "Large Image"; sourceTree = ""; @@ -2148,6 +2151,7 @@ D6E77D0B286D426E00D8B732 /* TrendingLinkCardCollectionViewCell.swift in Sources */, D6114E1127F899B30080E273 /* TrendingLinksViewController.swift in Sources */, D65B4B58297203A700DABDFB /* ReportSelectRulesView.swift in Sources */, + D6D79F5B2A13D22B00AB2315 /* GalleryFallbackViewController.swift in Sources */, D6C3F4FB299035650009FCFF /* TrendsViewController.swift in Sources */, D6B81F442560390300F6E31D /* MenuController.swift in Sources */, D691771129A2B76A0054D7EF /* MainActor+Unsafe.swift in Sources */, diff --git a/Tusker/Screens/Attachment Gallery/GalleryViewController.swift b/Tusker/Screens/Attachment Gallery/GalleryViewController.swift index 321647fe..b887b031 100644 --- a/Tusker/Screens/Attachment Gallery/GalleryViewController.swift +++ b/Tusker/Screens/Attachment Gallery/GalleryViewController.swift @@ -109,7 +109,7 @@ class GalleryViewController: UIPageViewController, UIPageViewControllerDataSourc vc.shrinkGestureEnabled = false return vc default: - fatalError() + return UINavigationController(rootViewController: GalleryFallbackViewController(attachment: attachment)) } } diff --git a/Tusker/Screens/Large Image/GalleryFallbackViewController.swift b/Tusker/Screens/Large Image/GalleryFallbackViewController.swift new file mode 100644 index 00000000..bd993d39 --- /dev/null +++ b/Tusker/Screens/Large Image/GalleryFallbackViewController.swift @@ -0,0 +1,71 @@ +// +// GalleryFallbackViewController.swift +// Tusker +// +// Created by Shadowfacts on 5/16/23. +// Copyright © 2023 Shadowfacts. All rights reserved. +// + +import UIKit +import QuickLook +import Pachyderm + +class GalleryFallbackViewController: QLPreviewController { + + private let attachment: Attachment + private let previewItem: GalleryPreviewItem + + private var loadAttachmentTask: Task? + + deinit { + loadAttachmentTask?.cancel() + } + + init(attachment: Attachment) { + self.attachment = attachment + self.previewItem = GalleryPreviewItem() + + super.init(nibName: nil, bundle: nil) + + dataSource = self + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + if previewItem.previewItemURL == nil, + loadAttachmentTask == nil { + loadAttachmentTask = Task { + do { + let (data, _) = try await URLSession.shared.data(from: attachment.url) + let url = FileManager.default.temporaryDirectory.appendingPathComponent(attachment.url.lastPathComponent) + try data.write(to: url) + try Task.checkCancellation() + previewItem.previewItemURL = url + refreshCurrentPreviewItem() + } catch { + return + } + } + } + } + +} + +extension GalleryFallbackViewController: QLPreviewControllerDataSource { + func numberOfPreviewItems(in controller: QLPreviewController) -> Int { + return 1 + } + + func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem { + return previewItem + } +} + +private class GalleryPreviewItem: NSObject, QLPreviewItem { + var previewItemURL: URL? = nil +}