From 53d27627254ef9dd1c0ce8782352a120962c7444 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 10 Sep 2024 18:00:33 +0300 Subject: [PATCH 1/2] Fixes #3243 - Bring back default controls for QuickLook based media viewers --- .../InteractiveQuickLook.swift | 41 ++++--------------- .../View/RoomDetailsScreen.swift | 2 +- .../View/RoomMemberDetailsScreen.swift | 2 +- .../View/UserProfileScreen.swift | 2 +- 4 files changed, 10 insertions(+), 37 deletions(-) diff --git a/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift b/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift index 695777e578..38d8f654a5 100644 --- a/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift +++ b/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift @@ -12,22 +12,19 @@ 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, shouldHideControls: Bool = false) -> some View { - modifier(InteractiveQuickLookModifier(item: item, shouldHideControls: shouldHideControls)) + func interactiveQuickLook(item: Binding) -> some View { + modifier(InteractiveQuickLookModifier(item: item)) } } 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, - shouldHideControls: shouldHideControls, dismissalPublisher: dismissalPublisher) { self.item = nil } } else { // Work around QLPreviewController dismissal issues, see below. @@ -39,13 +36,11 @@ 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, - shouldHideControls: shouldHideControls, dismissalPublisher: dismissalPublisher, onDismiss: onDismiss) } @@ -58,7 +53,6 @@ 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 onDismiss: () -> Void private var dismissalObserver: AnyCancellable? @@ -66,11 +60,9 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { var previewController: QLPreviewController? init(previewItem: MediaPreviewItem, - shouldHideControls: Bool, dismissalPublisher: PassthroughSubject, onDismiss: @escaping () -> Void) { self.previewItem = previewItem - self.shouldHideControls = shouldHideControls self.onDismiss = onDismiss super.init(nibName: nil, bundle: nil) @@ -100,7 +92,7 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { guard self.previewController == nil else { return } - let previewController = (shouldHideControls ? NoControlsPreviewController() : QLPreviewController()) + let previewController = QLPreviewController() previewController.dataSource = self previewController.delegate = self present(previewController, animated: true) @@ -120,6 +112,10 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { // MARK: QLPreviewControllerDelegate + func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode { + .disabled + } + func previewControllerDidDismiss(_ controller: QLPreviewController) { onDismiss() } @@ -139,28 +135,6 @@ 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 { @@ -170,7 +144,6 @@ struct PreviewView_Previews: PreviewProvider { static var previews: some View { 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 ff6c5d59e8..aece688444 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -57,7 +57,7 @@ struct RoomDetailsScreen: View { .navigationTitle(L10n.screenRoomDetailsTitle) .navigationBarTitleDisplayMode(.inline) .track(screen: .RoomDetails) - .interactiveQuickLook(item: $context.mediaPreviewItem, shouldHideControls: true) + .interactiveQuickLook(item: $context.mediaPreviewItem) } // MARK: - Private diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift index 39c2cda68c..32e555d905 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift @@ -24,7 +24,7 @@ struct RoomMemberDetailsScreen: View { .alert(item: $context.ignoreUserAlert, actions: blockUserAlertActions, message: blockUserAlertMessage) .alert(item: $context.alertInfo) .track(screen: .User) - .interactiveQuickLook(item: $context.mediaPreviewItem, shouldHideControls: true) + .interactiveQuickLook(item: $context.mediaPreviewItem) } // MARK: - Private diff --git a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift index 5d76819a6e..413ad55ed1 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift @@ -21,7 +21,7 @@ struct UserProfileScreen: View { .toolbar { toolbar } .alert(item: $context.alertInfo) .track(screen: .User) - .interactiveQuickLook(item: $context.mediaPreviewItem, shouldHideControls: true) + .interactiveQuickLook(item: $context.mediaPreviewItem) } // MARK: - Private From e7989f8d0d31fc45cf6a3b6bd82e905b4ef888f7 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 11 Sep 2024 12:08:58 +0300 Subject: [PATCH 2/2] Make editing configurable --- .../FilePreviewScreen/InteractiveQuickLook.swift | 15 ++++++++++++--- .../View/RoomDetailsScreen.swift | 2 +- .../View/RoomMemberDetailsScreen.swift | 2 +- .../View/UserProfileScreen.swift | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift b/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift index 38d8f654a5..422a68419e 100644 --- a/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift +++ b/ElementX/Sources/Screens/FilePreviewScreen/InteractiveQuickLook.swift @@ -12,19 +12,22 @@ 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, allowEditing: Bool = true) -> some View { + modifier(InteractiveQuickLookModifier(item: item, allowEditing: allowEditing)) } } private struct InteractiveQuickLookModifier: ViewModifier { @Binding var item: MediaPreviewItem? + let allowEditing: Bool + @State private var dismissalPublisher = PassthroughSubject() func body(content: Content) -> some View { content.background { if let item { MediaPreviewViewController(previewItem: item, + allowEditing: allowEditing, dismissalPublisher: dismissalPublisher) { self.item = nil } } else { // Work around QLPreviewController dismissal issues, see below. @@ -36,11 +39,13 @@ private struct InteractiveQuickLookModifier: ViewModifier { private struct MediaPreviewViewController: UIViewControllerRepresentable { let previewItem: MediaPreviewItem + let allowEditing: Bool let dismissalPublisher: PassthroughSubject let onDismiss: () -> Void func makeUIViewController(context: Context) -> PreviewHostingController { PreviewHostingController(previewItem: previewItem, + allowEditing: allowEditing, dismissalPublisher: dismissalPublisher, onDismiss: onDismiss) } @@ -53,6 +58,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 allowEditing: Bool let onDismiss: () -> Void private var dismissalObserver: AnyCancellable? @@ -60,9 +66,11 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { var previewController: QLPreviewController? init(previewItem: MediaPreviewItem, + allowEditing: Bool, dismissalPublisher: PassthroughSubject, onDismiss: @escaping () -> Void) { self.previewItem = previewItem + self.allowEditing = allowEditing self.onDismiss = onDismiss super.init(nibName: nil, bundle: nil) @@ -113,7 +121,7 @@ private struct MediaPreviewViewController: UIViewControllerRepresentable { // MARK: QLPreviewControllerDelegate func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode { - .disabled + allowEditing ? .createCopy : .disabled } func previewControllerDidDismiss(_ controller: QLPreviewController) { @@ -144,6 +152,7 @@ struct PreviewView_Previews: PreviewProvider { static var previews: some View { MediaPreviewViewController(previewItem: previewItem, + allowEditing: false, dismissalPublisher: .init()) { } } } diff --git a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift index aece688444..73a8446f98 100644 --- a/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomDetailsScreen/View/RoomDetailsScreen.swift @@ -57,7 +57,7 @@ struct RoomDetailsScreen: View { .navigationTitle(L10n.screenRoomDetailsTitle) .navigationBarTitleDisplayMode(.inline) .track(screen: .RoomDetails) - .interactiveQuickLook(item: $context.mediaPreviewItem) + .interactiveQuickLook(item: $context.mediaPreviewItem, allowEditing: false) } // MARK: - Private diff --git a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift index 32e555d905..1861cd1deb 100644 --- a/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift +++ b/ElementX/Sources/Screens/RoomMemberDetailsScreen/View/RoomMemberDetailsScreen.swift @@ -24,7 +24,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, allowEditing: false) } // MARK: - Private diff --git a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift index 413ad55ed1..43201a3bb4 100644 --- a/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift +++ b/ElementX/Sources/Screens/UserProfileScreen/View/UserProfileScreen.swift @@ -21,7 +21,7 @@ struct UserProfileScreen: View { .toolbar { toolbar } .alert(item: $context.alertInfo) .track(screen: .User) - .interactiveQuickLook(item: $context.mediaPreviewItem) + .interactiveQuickLook(item: $context.mediaPreviewItem, allowEditing: false) } // MARK: - Private