Swiftgram/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenAddressItem.swift
2021-11-09 22:22:31 +04:00

136 lines
6.0 KiB
Swift

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
}
}