From a80cbe79c27eebebe67df74a5e0d4c6f0ff2ed8d Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Wed, 20 Mar 2024 11:49:00 -0400 Subject: [PATCH] Re-add image analysis interaction See #450 --- .../GalleryContentViewController.swift | 5 +++ ...alleryContentViewControllerContainer.swift | 2 + .../GalleryVC/GalleryItemViewController.swift | 7 ++++ .../ImageGalleryContentViewController.swift | 38 +++++++++++++++++++ .../LoadingGalleryContentViewController.swift | 5 +++ 5 files changed, 57 insertions(+) diff --git a/Packages/GalleryVC/Sources/GalleryVC/GalleryContentViewController.swift b/Packages/GalleryVC/Sources/GalleryVC/GalleryContentViewController.swift index 02da96a3..aedd922d 100644 --- a/Packages/GalleryVC/Sources/GalleryVC/GalleryContentViewController.swift +++ b/Packages/GalleryVC/Sources/GalleryVC/GalleryContentViewController.swift @@ -15,6 +15,8 @@ public protocol GalleryContentViewController: UIViewController { var caption: String? { get } var bottomControlsAccessoryViewController: UIViewController? { get } var canAnimateFromSourceView: Bool { get } + + func setControlsVisible(_ visible: Bool, animated: Bool) } public extension GalleryContentViewController { @@ -25,4 +27,7 @@ public extension GalleryContentViewController { var canAnimateFromSourceView: Bool { true } + + func setControlsVisible(_ visible: Bool, animated: Bool) { + } } diff --git a/Packages/GalleryVC/Sources/GalleryVC/GalleryContentViewControllerContainer.swift b/Packages/GalleryVC/Sources/GalleryVC/GalleryContentViewControllerContainer.swift index e4cf81a4..bee9a173 100644 --- a/Packages/GalleryVC/Sources/GalleryVC/GalleryContentViewControllerContainer.swift +++ b/Packages/GalleryVC/Sources/GalleryVC/GalleryContentViewControllerContainer.swift @@ -9,6 +9,8 @@ import Foundation @MainActor public protocol GalleryContentViewControllerContainer { + var galleryControlsVisible: Bool { get } + func setGalleryContentLoading(_ loading: Bool) func galleryContentChanged() func disableGalleryScrollAndZoom() diff --git a/Packages/GalleryVC/Sources/GalleryVC/GalleryItemViewController.swift b/Packages/GalleryVC/Sources/GalleryVC/GalleryItemViewController.swift index fbc29409..ab583b6f 100644 --- a/Packages/GalleryVC/Sources/GalleryVC/GalleryItemViewController.swift +++ b/Packages/GalleryVC/Sources/GalleryVC/GalleryItemViewController.swift @@ -192,6 +192,8 @@ class GalleryItemViewController: UIViewController { } func addContent() { + content.setControlsVisible(controlsVisible, animated: false) + content.view.translatesAutoresizingMaskIntoConstraints = false if content.parent != self { addChild(content) @@ -229,6 +231,7 @@ class GalleryItemViewController: UIViewController { func updateControlsViews() { topControlsView.transform = CGAffineTransform(translationX: 0, y: visible ? 0 : -topControlsView.bounds.height) bottomControlsView.transform = CGAffineTransform(translationX: 0, y: visible ? 0 : bottomControlsView.bounds.height) + content.setControlsVisible(visible, animated: animated) } if animated { let animator = UIViewPropertyAnimator(duration: 0.2, timingParameters: UISpringTimingParameters()) @@ -396,6 +399,10 @@ class GalleryItemViewController: UIViewController { } extension GalleryItemViewController: GalleryContentViewControllerContainer { + var galleryControlsVisible: Bool { + controlsVisible + } + func setGalleryContentLoading(_ loading: Bool) { if loading { if activityIndicator == nil { diff --git a/Tusker/Screens/Gallery/ImageGalleryContentViewController.swift b/Tusker/Screens/Gallery/ImageGalleryContentViewController.swift index 5e62ec76..c45b6641 100644 --- a/Tusker/Screens/Gallery/ImageGalleryContentViewController.swift +++ b/Tusker/Screens/Gallery/ImageGalleryContentViewController.swift @@ -10,6 +10,7 @@ import UIKit import GalleryVC import Pachyderm import TuskerComponents +@preconcurrency import VisionKit class ImageGalleryContentViewController: UIViewController, GalleryContentViewController { let url: URL @@ -18,6 +19,12 @@ class ImageGalleryContentViewController: UIViewController, GalleryContentViewCon let image: UIImage let gifController: GIFController? + @available(iOS 16.0, macCatalyst 17.0, *) + private static let analyzer = ImageAnalyzer() + private var _analysisInteraction: AnyObject? + @available(iOS 16.0, macCatalyst 17.0, *) + private var analysisInteraction: ImageAnalysisInteraction? { _analysisInteraction as? ImageAnalysisInteraction } + init(url: URL, caption: String?, originalData: Data?, image: UIImage, gifController: GIFController?) { self.url = url self.caption = caption @@ -40,6 +47,7 @@ class ImageGalleryContentViewController: UIViewController, GalleryContentViewCon let imageView = GIFImageView(image: image) imageView.translatesAutoresizingMaskIntoConstraints = false imageView.contentMode = .scaleAspectFit + imageView.isUserInteractionEnabled = true view.addSubview(imageView) NSLayoutConstraint.activate([ imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor), @@ -51,6 +59,22 @@ class ImageGalleryContentViewController: UIViewController, GalleryContentViewCon if let gifController { gifController.attach(to: imageView) } + + if gifController == nil, + #available(iOS 16.0, macCatalyst 17.0, *) { + let interaction = ImageAnalysisInteraction(self) + self._analysisInteraction = interaction + interaction.preferredInteractionTypes = .automatic + imageView.addInteraction(interaction) + Task { + do { + let result = try await ImageGalleryContentViewController.analyzer.analyze(image, configuration: ImageAnalyzer.Configuration([.text, .machineReadableCode])) + interaction.analysis = result + } catch { + // if analysis fails, we just don't show anything + } + } + } } override func viewWillAppear(_ animated: Bool) { @@ -76,4 +100,18 @@ class ImageGalleryContentViewController: UIViewController, GalleryContentViewCon return [] } } + + func setControlsVisible(_ visible: Bool, animated: Bool) { + if #available(iOS 16.0, macCatalyst 17.0, *), + let analysisInteraction { + analysisInteraction.setSupplementaryInterfaceHidden(!visible, animated: animated) + } + } +} + +@available(iOS 16.0, macCatalyst 17.0, *) +extension ImageGalleryContentViewController: ImageAnalysisInteractionDelegate { + func interaction(_ interaction: ImageAnalysisInteraction, shouldBeginAt point: CGPoint, for interactionType: ImageAnalysisInteraction.InteractionTypes) -> Bool { + return container?.galleryControlsVisible ?? true + } } diff --git a/Tusker/Screens/Gallery/LoadingGalleryContentViewController.swift b/Tusker/Screens/Gallery/LoadingGalleryContentViewController.swift index 25155730..a7a87af4 100644 --- a/Tusker/Screens/Gallery/LoadingGalleryContentViewController.swift +++ b/Tusker/Screens/Gallery/LoadingGalleryContentViewController.swift @@ -50,6 +50,7 @@ class LoadingGalleryContentViewController: UIViewController, GalleryContentViewC if let wrapped = await provider() { self.wrapped = wrapped wrapped.container = container + wrapped.setControlsVisible(container?.galleryControlsVisible ?? false, animated: false) addChild(wrapped) wrapped.view.translatesAutoresizingMaskIntoConstraints = false @@ -99,4 +100,8 @@ class LoadingGalleryContentViewController: UIViewController, GalleryContentViewC ]) } + func setControlsVisible(_ visible: Bool, animated: Bool) { + wrapped?.setControlsVisible(visible, animated: animated) + } + }