mirror of
https://github.com/mastodon/mastodon-ios.git
synced 2024-12-16 10:48:49 +01:00
Add Live Text support to MediaPreviewImageView
This commit is contained in:
parent
35f6732ad9
commit
ac28c2ee4f
@ -9,6 +9,7 @@ import os.log
|
||||
import func AVFoundation.AVMakeRect
|
||||
import UIKit
|
||||
import FLAnimatedImage
|
||||
import VisionKit
|
||||
|
||||
final class MediaPreviewImageView: UIScrollView {
|
||||
|
||||
@ -28,9 +29,21 @@ final class MediaPreviewImageView: UIScrollView {
|
||||
tapGestureRecognizer.numberOfTapsRequired = 2
|
||||
return tapGestureRecognizer
|
||||
}()
|
||||
|
||||
|
||||
private var containerFrame: CGRect?
|
||||
|
||||
|
||||
private var _interaction: UIInteraction? = {
|
||||
if #available(iOS 16.0, *) {
|
||||
return ImageAnalysisInteraction()
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
@available(iOS 16.0, *)
|
||||
var liveTextInteraction: ImageAnalysisInteraction {
|
||||
_interaction as! ImageAnalysisInteraction
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
_init()
|
||||
@ -55,10 +68,14 @@ extension MediaPreviewImageView {
|
||||
maximumZoomScale = 4.0
|
||||
|
||||
addSubview(imageView)
|
||||
|
||||
|
||||
doubleTapGestureRecognizer.addTarget(self, action: #selector(MediaPreviewImageView.doubleTapGestureRecognizerHandler(_:)))
|
||||
imageView.addGestureRecognizer(doubleTapGestureRecognizer)
|
||||
|
||||
if #available(iOS 16.0, *) {
|
||||
liveTextInteraction.isSupplementaryInterfaceHidden = true
|
||||
imageView.addInteraction(liveTextInteraction)
|
||||
}
|
||||
|
||||
delegate = self
|
||||
}
|
||||
|
||||
@ -129,6 +146,26 @@ extension MediaPreviewImageView {
|
||||
|
||||
centerScrollViewContents()
|
||||
contentOffset = CGPoint(x: -contentInset.left, y: -contentInset.top)
|
||||
|
||||
if #available(iOS 16.0, *) {
|
||||
Task.detached(priority: .userInitiated) {
|
||||
do {
|
||||
let analysis = try await ImageAnalyzer.shared.analyze(image, configuration: ImageAnalyzer.Configuration([.text, .machineReadableCode]))
|
||||
await MainActor.run {
|
||||
self.liveTextInteraction.analysis = analysis
|
||||
self.liveTextInteraction.preferredInteractionTypes = .automatic
|
||||
if self.liveTextInteraction.isSupplementaryInterfaceHidden {
|
||||
self.liveTextInteraction.setSupplementaryInterfaceHidden(false, animated: true)
|
||||
}
|
||||
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
self.liveTextInteraction.preferredInteractionTypes = []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: setup image for container %s", ((#file as NSString).lastPathComponent), #line, #function, container.frame.debugDescription)
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import Combine
|
||||
import MastodonAsset
|
||||
import MastodonLocalization
|
||||
import FLAnimatedImage
|
||||
import VisionKit
|
||||
|
||||
protocol MediaPreviewImageViewControllerDelegate: AnyObject {
|
||||
func mediaPreviewImageViewController(_ viewController: MediaPreviewImageViewController, tapGestureRecognizerDidTrigger tapGestureRecognizer: UITapGestureRecognizer)
|
||||
@ -31,7 +32,7 @@ final class MediaPreviewImageViewController: UIViewController {
|
||||
|
||||
let tapGestureRecognizer = UITapGestureRecognizer.singleTapGestureRecognizer
|
||||
let longPressGestureRecognizer = UILongPressGestureRecognizer()
|
||||
|
||||
|
||||
deinit {
|
||||
os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||
previewImageView.imageView.af.cancelImageRequest()
|
||||
@ -42,7 +43,10 @@ extension MediaPreviewImageViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
if #available(iOS 16.0, *) {
|
||||
previewImageView.liveTextInteraction.delegate = self
|
||||
}
|
||||
previewImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(previewImageView)
|
||||
NSLayoutConstraint.activate([
|
||||
@ -53,7 +57,9 @@ extension MediaPreviewImageViewController {
|
||||
])
|
||||
|
||||
tapGestureRecognizer.addTarget(self, action: #selector(MediaPreviewImageViewController.tapGestureRecognizerHandler(_:)))
|
||||
tapGestureRecognizer.delegate = self
|
||||
longPressGestureRecognizer.addTarget(self, action: #selector(MediaPreviewImageViewController.longPressGestureRecognizerHandler(_:)))
|
||||
longPressGestureRecognizer.delegate = self
|
||||
tapGestureRecognizer.require(toFail: previewImageView.doubleTapGestureRecognizer)
|
||||
tapGestureRecognizer.require(toFail: longPressGestureRecognizer)
|
||||
previewImageView.addGestureRecognizer(tapGestureRecognizer)
|
||||
@ -105,10 +111,42 @@ extension MediaPreviewImageViewController {
|
||||
|
||||
}
|
||||
|
||||
// MARK: - ImageAnalysisInteractionDelegate
|
||||
@available(iOS 16.0, *)
|
||||
extension MediaPreviewImageViewController: ImageAnalysisInteractionDelegate {
|
||||
func contentView(for interaction: ImageAnalysisInteraction) -> UIView? {
|
||||
view
|
||||
}
|
||||
|
||||
func presentingViewController(for interaction: ImageAnalysisInteraction) -> UIViewController? {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UIGestureRecognizerDelegate
|
||||
extension MediaPreviewImageViewController: UIGestureRecognizerDelegate {
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
|
||||
if #available(iOS 16.0, *) {
|
||||
let location = touch.location(in: previewImageView.imageView)
|
||||
let hasItem = previewImageView.liveTextInteraction.hasInteractiveItem(at: location)
|
||||
return !hasItem
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UIContextMenuInteractionDelegate
|
||||
extension MediaPreviewImageViewController: UIContextMenuInteractionDelegate {
|
||||
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||
|
||||
if #available(iOS 16.0, *) {
|
||||
if previewImageView.liveTextInteraction.hasInteractiveItem(at: previewImageView.imageView.convert(location, from: previewImageView)) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let previewProvider: UIContextMenuContentPreviewProvider = { () -> UIViewController? in
|
||||
return nil
|
||||
|
13
MastodonSDK/Sources/MastodonExtension/ImageAnalyzer.swift
Normal file
13
MastodonSDK/Sources/MastodonExtension/ImageAnalyzer.swift
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// ImageAnalyzer.swift
|
||||
//
|
||||
//
|
||||
// Created by Jed Fox on 2022-11-14.
|
||||
//
|
||||
|
||||
import VisionKit
|
||||
|
||||
@available(iOS 16.0, *)
|
||||
extension ImageAnalyzer {
|
||||
public static let shared = ImageAnalyzer()
|
||||
}
|
Loading…
Reference in New Issue
Block a user