// // ImageGalleryContentViewController.swift // Tusker // // Created by Shadowfacts on 3/17/24. // Copyright © 2024 Shadowfacts. All rights reserved. // import UIKit import GalleryVC import Pachyderm import TuskerComponents @preconcurrency import VisionKit class ImageGalleryContentViewController: UIViewController, GalleryContentViewController { let url: URL let caption: String? let originalData: Data? 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 self.originalData = originalData self.image = image self.gifController = gifController super.init(nibName: nil, bundle: nil) preferredContentSize = image.size } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() 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), imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor), imageView.topAnchor.constraint(equalTo: view.topAnchor), imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) 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) { super.viewWillAppear(animated) if let gifController { gifController.startAnimating() } } // MARK: GalleryContentViewController var container: (any GalleryVC.GalleryContentViewControllerContainer)? var contentSize: CGSize { image.size } var activityItemsForSharing: [Any] { if let data = originalData ?? image.pngData() { return [ImageActivityItemSource(data: data, url: url, image: image)] } else { 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 } }