Work-around issue with QLPreviewController not supporting swipe-to-dismiss and pinch-to-dismiss when presented from SwiftUI by creating a transparent UIViewController wrapper around QLPreviewController that presents it using UIKit instead. (#452) close #106
Co-authored-by: Greg <greg@cromulentlabs.com>
This commit is contained in:
parent
be802980c5
commit
b1b9e658c9
|
@ -53,9 +53,10 @@ struct IceCubesApp: App {
|
|||
.environmentObject(theme)
|
||||
.environmentObject(watcher)
|
||||
.environmentObject(PushNotificationsService.shared)
|
||||
.sheet(item: $quickLook.url, content: { url in
|
||||
.fullScreenCover(item: $quickLook.url, content: { url in
|
||||
QuickLookPreview(selectedURL: url, urls: quickLook.urls)
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
.background(TransparentBackground())
|
||||
})
|
||||
}
|
||||
.commands {
|
||||
|
|
|
@ -12,61 +12,81 @@ struct QuickLookPreview: UIViewControllerRepresentable {
|
|||
let selectedURL: URL
|
||||
let urls: [URL]
|
||||
|
||||
func makeUIViewController(context: Context) -> UINavigationController {
|
||||
let controller = AppQLPreviewController()
|
||||
controller.dataSource = context.coordinator
|
||||
controller.delegate = context.coordinator
|
||||
let nav = UINavigationController(rootViewController: controller)
|
||||
return nav
|
||||
func makeUIViewController(context: Context) -> UIViewController {
|
||||
return AppQLPreviewController(selectedURL: selectedURL, urls: urls)
|
||||
}
|
||||
|
||||
func updateUIViewController(
|
||||
_: UINavigationController, context _: Context
|
||||
_: UIViewController, context _: Context
|
||||
) {}
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
return Coordinator(parent: self)
|
||||
class AppQLPreviewController: UIViewController {
|
||||
let selectedURL: URL
|
||||
let urls: [URL]
|
||||
|
||||
var qlController : QLPreviewController?
|
||||
|
||||
init(selectedURL: URL, urls: [URL]) {
|
||||
self.selectedURL = selectedURL
|
||||
self.urls = urls
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
class Coordinator: NSObject, QLPreviewControllerDataSource, QLPreviewControllerDelegate {
|
||||
let parent: QuickLookPreview
|
||||
|
||||
init(parent: QuickLookPreview) {
|
||||
self.parent = parent
|
||||
}
|
||||
|
||||
func numberOfPreviewItems(in _: QLPreviewController) -> Int {
|
||||
return parent.urls.count
|
||||
}
|
||||
|
||||
func previewController(_: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
|
||||
return parent.urls[index] as QLPreviewItem
|
||||
}
|
||||
|
||||
func previewController(_: QLPreviewController, editingModeFor _: QLPreviewItem) -> QLPreviewItemEditingMode {
|
||||
.createCopy
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
if self.qlController == nil {
|
||||
self.qlController = QLPreviewController()
|
||||
self.qlController?.dataSource = self
|
||||
self.qlController?.delegate = self
|
||||
self.qlController?.currentPreviewItemIndex = urls.firstIndex(of: selectedURL) ?? 0
|
||||
self.present(self.qlController!, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AppQLPreviewController: QLPreviewController {
|
||||
private var closeButton: UIBarButtonItem {
|
||||
.init(
|
||||
title: NSLocalizedString("action.done", comment: ""),
|
||||
style: .plain,
|
||||
target: self,
|
||||
action: #selector(onCloseButton)
|
||||
)
|
||||
extension AppQLPreviewController : QLPreviewControllerDataSource {
|
||||
func numberOfPreviewItems(in _: QLPreviewController) -> Int {
|
||||
return self.urls.count
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
if UIDevice.current.userInterfaceIdiom != .pad {
|
||||
navigationItem.rightBarButtonItem = closeButton
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func onCloseButton() {
|
||||
dismiss(animated: true)
|
||||
func previewController(_: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
|
||||
return self.urls[index] as QLPreviewItem
|
||||
}
|
||||
}
|
||||
|
||||
extension AppQLPreviewController : QLPreviewControllerDelegate {
|
||||
func previewController(_: QLPreviewController, editingModeFor _: QLPreviewItem) -> QLPreviewItemEditingMode {
|
||||
.createCopy
|
||||
}
|
||||
|
||||
func previewControllerWillDismiss(_ controller: QLPreviewController) {
|
||||
self.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
struct TransparentBackground: UIViewControllerRepresentable {
|
||||
public func makeUIViewController(context: Context) -> UIViewController {
|
||||
return TransparentController()
|
||||
}
|
||||
|
||||
public func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
|
||||
}
|
||||
|
||||
class TransparentController: UIViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
view.backgroundColor = .clear
|
||||
}
|
||||
|
||||
override func willMove(toParent parent: UIViewController?) {
|
||||
super.willMove(toParent: parent)
|
||||
parent?.view?.backgroundColor = .clear
|
||||
parent?.modalPresentationStyle = .overCurrentContext
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,9 @@ public class QuickLook: ObservableObject {
|
|||
public init() {}
|
||||
|
||||
public func prepareFor(urls: [URL], selectedURL: URL) async {
|
||||
withAnimation {
|
||||
var transaction = Transaction(animation: .default)
|
||||
transaction.disablesAnimations = true
|
||||
withTransaction(transaction) {
|
||||
isPreparing = true
|
||||
}
|
||||
do {
|
||||
|
@ -27,18 +29,18 @@ public class QuickLook: ObservableObject {
|
|||
}
|
||||
return paths
|
||||
})
|
||||
self.urls = paths
|
||||
url = paths.first(where: { $0.lastPathComponent == selectedURL.lastPathComponent })
|
||||
withAnimation {
|
||||
withTransaction(transaction) {
|
||||
self.urls = paths
|
||||
url = paths.first(where: { $0.lastPathComponent == selectedURL.lastPathComponent })
|
||||
isPreparing = false
|
||||
}
|
||||
} catch {
|
||||
withAnimation {
|
||||
withTransaction(transaction) {
|
||||
isPreparing = false
|
||||
self.urls = []
|
||||
url = nil
|
||||
latestError = error
|
||||
}
|
||||
self.urls = []
|
||||
url = nil
|
||||
latestError = error
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue