diff --git a/Examples/UIComponentExample/Examples/AsyncImage/AsyncImageViewController.swift b/Examples/UIComponentExample/Examples/AsyncImage/AsyncImageViewController.swift index 83c84b3c..89975612 100644 --- a/Examples/UIComponentExample/Examples/AsyncImage/AsyncImageViewController.swift +++ b/Examples/UIComponentExample/Examples/AsyncImage/AsyncImageViewController.swift @@ -15,7 +15,7 @@ struct ImageData { } class AsyncImageViewController: ComponentViewController { - let images = [ + var images = [ ImageData(url: URL(string: "https://unsplash.com/photos/Yn0l7uwBrpw/download?force=true&w=640")!, size: CGSize(width: 640, height: 360)), ImageData(url: URL(string: "https://unsplash.com/photos/J4-xolC4CCU/download?force=true&w=640")!, @@ -28,30 +28,41 @@ class AsyncImageViewController: ComponentViewController { size: CGSize(width: 640, height: 426)), ImageData(url: URL(string: "https://unsplash.com/photos/MOfETox0bkE/download?force=true&w=640")!, size: CGSize(width: 640, height: 426)), - ] + ] { + didSet { + reloadComponent() + } + } override var component: Component { Waterfall(columns: 2, spacing: 1) { - for image in images { + for (index, image) in images.enumerated() { AsyncImage(image.url) .size(width: .fill, height: .aspectPercentage(image.size.height / image.size.width)) .tappableView { let detailVC = AsyncImageDetailViewController() detailVC.image = image $0.parentViewController?.navigationController?.pushViewController(detailVC, animated: true) + }.previewProvider { + let detailVC = AsyncImageDetailViewController() + detailVC.preferredContentSize = image.size + detailVC.image = image + return detailVC + }.contextMenuProvider { [weak self] in + UIMenu(children: [ + UIAction(title: "Delete", image: UIImage(systemName: "trash"), attributes: [.destructive], handler: { action in + self?.images.remove(at: index) + }) + ]) } } } } - init() { - super.init(nibName: nil, bundle: nil) + override func viewDidLoad() { + super.viewDidLoad() title = "Async Image" } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } } diff --git a/Sources/UIComponent/Components/TappableView.swift b/Sources/UIComponent/Components/TappableView.swift index 198bdbab..37cc7737 100644 --- a/Sources/UIComponent/Components/TappableView.swift +++ b/Sources/UIComponent/Components/TappableView.swift @@ -49,9 +49,19 @@ open class TappableView: ComponentView { } } - public var contextMenuProvider: ((TappableView) -> UIMenu?)? { + public var previewProvider: (() -> UIViewController?)? { didSet { - if contextMenuProvider != nil { + if previewProvider != nil || contextMenuProvider != nil { + addInteraction(contextMenuInteraction) + } else { + removeInteraction(contextMenuInteraction) + } + } + } + + public var contextMenuProvider: (() -> UIMenu?)? { + didSet { + if previewProvider != nil || contextMenuProvider != nil { addInteraction(contextMenuInteraction) } else { removeInteraction(contextMenuInteraction) @@ -106,9 +116,10 @@ open class TappableView: ComponentView { extension TappableView: UIContextMenuInteractionDelegate { public func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? { - return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { [weak self] _ in - guard let self = self else { return nil } - return self.contextMenuProvider?(self) + return UIContextMenuConfiguration(identifier: nil) { [weak self] in + return self?.previewProvider?() + } actionProvider: { [weak self] _ in + return self?.contextMenuProvider?() } } }