import Foundation import UIKit import Display import ComponentFlow import PagerComponent import TelegramPresentationData import TelegramCore import Postbox import AnimationCache import MultiAnimationRenderer import AccountContext import AsyncDisplayKit import ComponentDisplayAdapters public protocol EntitySearchContainerNode: ASDisplayNode { var onCancel: (() -> Void)? { get set } func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, inputHeight: CGFloat, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition) } final class EntitySearchContentEnvironment: Equatable { let context: AccountContext let theme: PresentationTheme let deviceMetrics: DeviceMetrics let inputHeight: CGFloat init( context: AccountContext, theme: PresentationTheme, deviceMetrics: DeviceMetrics, inputHeight: CGFloat ) { self.context = context self.theme = theme self.deviceMetrics = deviceMetrics self.inputHeight = inputHeight } static func ==(lhs: EntitySearchContentEnvironment, rhs: EntitySearchContentEnvironment) -> Bool { if lhs.context !== rhs.context { return false } if lhs.theme !== rhs.theme { return false } if lhs.deviceMetrics != rhs.deviceMetrics { return false } if lhs.inputHeight != rhs.inputHeight { return false } return true } } final class EntitySearchContentComponent: Component { typealias EnvironmentType = EntitySearchContentEnvironment let makeContainerNode: () -> EntitySearchContainerNode? let dismissSearch: () -> Void init( makeContainerNode: @escaping () -> EntitySearchContainerNode?, dismissSearch: @escaping () -> Void ) { self.makeContainerNode = makeContainerNode self.dismissSearch = dismissSearch } static func ==(lhs: EntitySearchContentComponent, rhs: EntitySearchContentComponent) -> Bool { return true } final class View: UIView { private var containerNode: EntitySearchContainerNode? override init(frame: CGRect) { super.init(frame: frame) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func update(component: EntitySearchContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { let containerNode: EntitySearchContainerNode? if let current = self.containerNode { containerNode = current } else { containerNode = component.makeContainerNode() if let containerNode = containerNode { self.containerNode = containerNode self.addSubnode(containerNode) } } if let containerNode = containerNode { let environmentValue = environment[EntitySearchContentEnvironment.self].value transition.setFrame(view: containerNode.view, frame: CGRect(origin: CGPoint(), size: availableSize)) containerNode.updateLayout( size: availableSize, leftInset: 0.0, rightInset: 0.0, bottomInset: 0.0, inputHeight: environmentValue.inputHeight, deviceMetrics: environmentValue.deviceMetrics, transition: transition.containedViewLayoutTransition ) containerNode.onCancel = { component.dismissSearch() } } return availableSize } } func makeView() -> View { return View(frame: CGRect()) } func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) } }