diff --git a/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift b/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift index e1418a11a..b2394c429 100644 --- a/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift +++ b/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift @@ -21,20 +21,23 @@ import SwiftUI extension View { /// Preview a media file using a QuickLook Preview Controller. The preview is interactive with /// the dismiss gesture working as expected if it was presented from UIKit. - func interactiveQuickLook(item: Binding) -> some View { - modifier(InteractiveQuickLookModifier(item: item)) + func interactiveQuickLook(item: Binding, shouldHideControls: Bool = false) -> some View { + modifier(InteractiveQuickLookModifier(item: item, shouldHideControls: shouldHideControls)) } } private struct InteractiveQuickLookModifier: ViewModifier { @Binding var item: MediaPreviewItem? + let shouldHideControls: Bool @State private var dismissalPublisher = PassthroughSubject() func body(content: Content) -> some View { content.background { if let item { - MediaPreviewViewController(previewItem: item, dismissalPublisher: dismissalPublisher) { self.item = nil } + MediaPreviewViewController(previewItem: item, + shouldHideControls: shouldHideControls, + dismissalPublisher: dismissalPublisher) { self.item = nil } } else { // Work around QLPreviewController dismissal issues, see below. let _ = dismissalPublisher.send(()) @@ -45,11 +48,15 @@ private struct InteractiveQuickLookModifier: ViewModifier { private struct MediaPreviewViewController: UIViewControllerRepresentable { let previewItem: MediaPreviewItem + let shouldHideControls: Bool let dismissalPublisher: PassthroughSubject let onDismiss: () -> Void func makeUIViewController(context: Context) -> PreviewHostingController { - PreviewHostingController(previewItem: previewItem, dismissalPublisher: dismissalPublisher, onDismiss: onDismiss) + PreviewHostingController(previewItem: previewItem, + shouldHideControls: shouldHideControls, + dismissalPublisher: dismissalPublisher, + onDismiss: onDismiss) } func updateUIViewController(_ uiViewController: PreviewHostingController, context: Context) { } @@ -60,6 +67,7 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { /// animations and interactions which don't work if you represent it directly to SwiftUI 🤷‍♂️ class PreviewHostingController: UIViewController, QLPreviewControllerDataSource, QLPreviewControllerDelegate { let previewItem: MediaPreviewItem + let shouldHideControls: Bool let dismissalPublisher: PassthroughSubject let onDismiss: () -> Void @@ -67,8 +75,12 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { var previewController: QLPreviewController? - init(previewItem: MediaPreviewItem, dismissalPublisher: PassthroughSubject, onDismiss: @escaping () -> Void) { + init(previewItem: MediaPreviewItem, + shouldHideControls: Bool, + dismissalPublisher: PassthroughSubject, + onDismiss: @escaping () -> Void) { self.previewItem = previewItem + self.shouldHideControls = shouldHideControls self.dismissalPublisher = dismissalPublisher self.onDismiss = onDismiss @@ -96,7 +108,7 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { guard self.previewController == nil else { return } - let previewController = QLPreviewController() + let previewController = (shouldHideControls ? NoControlsPreviewController() : QLPreviewController()) previewController.dataSource = self previewController.delegate = self present(previewController, animated: true) @@ -135,6 +147,28 @@ class MediaPreviewItem: NSObject, QLPreviewItem { } } +private class NoControlsPreviewController: QLPreviewController { + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + guard let navigationController = children.first as? UINavigationController else { + return + } + + // Remove top file details bar + navigationController.navigationBar.isHidden = true + + // Remove the toolbars and their buttons + navigationController.view.subviews.compactMap { $0 as? UIToolbar }.forEach { toolbar in + toolbar.subviews.forEach { item in + item.isHidden = true + } + + toolbar.isHidden = true + } + } +} + // MARK: - Previews struct PreviewView_Previews: PreviewProvider { @@ -143,6 +177,8 @@ struct PreviewView_Previews: PreviewProvider { title: "Important Document") static var previews: some View { - MediaPreviewViewController(previewItem: previewItem, dismissalPublisher: .init()) { } + MediaPreviewViewController(previewItem: previewItem, + shouldHideControls: false, + dismissalPublisher: .init()) { } } } diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index 3675d6d3e..6484f4e80 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -64,7 +64,7 @@ struct RoomDetailsScreen: View { } } .track(screen: .roomDetails) - .interactiveQuickLook(item: $context.mediaPreviewItem) + .interactiveQuickLook(item: $context.mediaPreviewItem, shouldHideControls: true) } // MARK: - Private diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift index e17da6335..e54ba7f42 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift @@ -31,7 +31,7 @@ struct RoomMemberDetailsScreen: View { .alert(item: $context.ignoreUserAlert, actions: blockUserAlertActions, message: blockUserAlertMessage) .alert(item: $context.alertInfo) .track(screen: .user) - .interactiveQuickLook(item: $context.mediaPreviewItem) + .interactiveQuickLook(item: $context.mediaPreviewItem, shouldHideControls: true) } // MARK: - Private