import Foundation import UIKit import AsyncDisplayKit import Display import TelegramPresentationData import ItemListAddressItem import SwiftSignalKit import AccountContext final class PeerInfoScreenAddressItem: PeerInfoScreenItem { let id: AnyHashable let label: String let text: String let imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? let action: (() -> Void)? let longTapAction: (() -> Void)? let linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? init( id: AnyHashable, label: String, text: String, imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?, action: (() -> Void)?, longTapAction: (() -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil ) { self.id = id self.label = label self.text = text self.imageSignal = imageSignal self.action = action self.longTapAction = longTapAction self.linkItemAction = linkItemAction } func node() -> PeerInfoScreenItemNode { return PeerInfoScreenAddressItemNode() } } private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode { private let selectionNode: PeerInfoScreenSelectableBackgroundNode private let bottomSeparatorNode: ASDisplayNode private let maskNode: ASImageNode private var item: PeerInfoScreenAddressItem? private var itemNode: ItemListAddressItemNode? override init() { var bringToFrontForHighlightImpl: (() -> Void)? self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() }) self.bottomSeparatorNode = ASDisplayNode() self.bottomSeparatorNode.isLayerBacked = true self.maskNode = ASImageNode() self.maskNode.isUserInteractionEnabled = false super.init() bringToFrontForHighlightImpl = { [weak self] in self?.bringToFrontForHighlight?() } self.addSubnode(self.bottomSeparatorNode) self.addSubnode(self.selectionNode) self.addSubnode(self.maskNode) } override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat { guard let item = item as? PeerInfoScreenAddressItem else { return 10.0 } self.item = item self.selectionNode.pressed = item.action let sideInset: CGFloat = 16.0 + safeInsets.left self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor let addressItem = ItemListAddressItem(theme: presentationData.theme, label: item.label, text: item.text, imageSignal: item.imageSignal, sectionId: 0, style: .blocks, displayDecorations: false, action: nil, longTapAction: item.longTapAction, linkItemAction: item.linkItemAction) let params = ListViewItemLayoutParams(width: width, leftInset: safeInsets.left, rightInset: safeInsets.right, availableHeight: 1000.0) let itemNode: ItemListAddressItemNode if let current = self.itemNode { itemNode = current addressItem.updateNode(async: { $0() }, node: { return itemNode }, params: params, previousItem: nil, nextItem: nil, animation: .None, completion: { (layout, apply) in let nodeFrame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: layout.size.height)) itemNode.contentSize = layout.contentSize itemNode.insets = layout.insets itemNode.frame = nodeFrame apply(ListViewItemApply(isOnScreen: true)) }) } else { var itemNodeValue: ListViewItemNode? addressItem.nodeConfiguredForParams(async: { $0() }, params: params, synchronousLoads: false, previousItem: nil, nextItem: nil, completion: { node, apply in itemNodeValue = node apply().1(ListViewItemApply(isOnScreen: true)) }) itemNode = itemNodeValue as! ItemListAddressItemNode itemNode.isUserInteractionEnabled = false self.itemNode = itemNode self.addSubnode(itemNode) } let height = itemNode.contentSize.height let hasCorners = hasCorners && (topItem == nil || bottomItem == nil) let hasTopCorners = hasCorners && topItem == nil let hasBottomCorners = hasCorners && bottomItem == nil self.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil self.maskNode.frame = CGRect(origin: CGPoint(x: safeInsets.left, y: 0.0), size: CGSize(width: width - safeInsets.left - safeInsets.right, height: height)) self.bottomSeparatorNode.isHidden = hasBottomCorners transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(), size: itemNode.bounds.size)) let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition) transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset))) transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: height - UIScreenPixel), size: CGSize(width: width - sideInset, height: UIScreenPixel))) transition.updateAlpha(node: self.bottomSeparatorNode, alpha: bottomItem == nil ? 0.0 : 1.0) return height } }