import Foundation import AsyncDisplayKit open class ContextReferenceContentNode: ASDisplayNode { override public init() { super.init() } } public final class ContextExtractedContentContainingNode: ASDisplayNode { public let contentNode: ContextExtractedContentNode public var contentRect: CGRect = CGRect() public var isExtractedToContextPreview: Bool = false public var willUpdateIsExtractedToContextPreview: ((Bool, ContainedViewLayoutTransition) -> Void)? public var isExtractedToContextPreviewUpdated: ((Bool) -> Void)? public var updateAbsoluteRect: ((CGRect, CGSize) -> Void)? public var applyAbsoluteOffset: ((CGPoint, ContainedViewLayoutTransitionCurve, Double) -> Void)? public var applyAbsoluteOffsetSpring: ((CGFloat, Double, CGFloat) -> Void)? public var layoutUpdated: ((CGSize, ListViewItemUpdateAnimation) -> Void)? public var updateDistractionFreeMode: ((Bool) -> Void)? public var requestDismiss: (() -> Void)? public override init() { self.contentNode = ContextExtractedContentNode() super.init() self.addSubnode(self.contentNode) } public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { if self.contentNode.supernode === self { return self.contentNode.hitTest(self.view.convert(point, to: self.contentNode.view), with: event) } else { return nil } } } public final class ContextExtractedContentContainingView: UIView { public let contentView: ContextExtractedContentView public var contentRect: CGRect = CGRect() public var isExtractedToContextPreview: Bool = false public var willUpdateIsExtractedToContextPreview: ((Bool, ContainedViewLayoutTransition) -> Void)? public var isExtractedToContextPreviewUpdated: ((Bool) -> Void)? public var updateAbsoluteRect: ((CGRect, CGSize) -> Void)? public var applyAbsoluteOffset: ((CGPoint, ContainedViewLayoutTransitionCurve, Double) -> Void)? public var applyAbsoluteOffsetSpring: ((CGFloat, Double, CGFloat) -> Void)? public var layoutUpdated: ((CGSize, ListViewItemUpdateAnimation) -> Void)? public var updateDistractionFreeMode: ((Bool) -> Void)? public var requestDismiss: (() -> Void)? public override init(frame: CGRect) { self.contentView = ContextExtractedContentView() super.init(frame: frame) self.addSubview(self.contentView) } required public init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { if self.contentView.superview === self { return self.contentView.hitTest(self.convert(point, to: self.contentView), with: event) } else { return nil } } } public final class ContextExtractedContentNode: ASDisplayNode { private var viewImpl: ContextExtractedContentView { return self.view as! ContextExtractedContentView } public var customHitTest: ((CGPoint) -> UIView?)? { didSet { if self.isNodeLoaded { self.viewImpl.customHitTest = self.customHitTest } } } override public init() { super.init() self.setViewBlock { return ContextExtractedContentView(frame: CGRect()) } } } public final class ContextExtractedContentView: UIView { public var customHitTest: ((CGPoint) -> UIView?)? override public init(frame: CGRect) { super.init(frame: frame) } required public init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let result = super.hitTest(point, with: event) if result === self { return nil } else { return result } } } public final class ContextControllerContentNode: ASDisplayNode { public let sourceView: UIView public let controller: ViewController private let tapped: () -> Void public init(sourceView: UIView, controller: ViewController, tapped: @escaping () -> Void) { self.sourceView = sourceView self.controller = controller self.tapped = tapped super.init() self.addSubnode(controller.displayNode) } override public func didLoad() { super.didLoad() self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) } @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { if case .ended = recognizer.state { self.tapped() } } public func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { transition.updateFrame(node: self.controller.displayNode, frame: CGRect(origin: CGPoint(), size: size)) } } public enum ContextContentNode { case reference(view: UIView) case extracted(node: ContextExtractedContentContainingNode, keepInPlace: Bool) case controller(ContextControllerContentNode) }