mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
206 lines
9.0 KiB
Swift
206 lines
9.0 KiB
Swift
import AsyncDisplayKit
|
|
import Display
|
|
import TelegramPresentationData
|
|
|
|
final class PeerInfoScreenDisclosureItem: PeerInfoScreenItem {
|
|
enum Label {
|
|
case none
|
|
case text(String)
|
|
case badge(String, UIColor)
|
|
|
|
var text: String {
|
|
switch self {
|
|
case .none:
|
|
return ""
|
|
case let .text(text), let .badge(text, _):
|
|
return text
|
|
}
|
|
}
|
|
|
|
var badgeColor: UIColor? {
|
|
switch self {
|
|
case .none, .text:
|
|
return nil
|
|
case let .badge(_, color):
|
|
return color
|
|
}
|
|
}
|
|
}
|
|
|
|
let id: AnyHashable
|
|
let label: Label
|
|
let text: String
|
|
let icon: UIImage?
|
|
let action: (() -> Void)?
|
|
|
|
init(id: AnyHashable, label: Label = .none, text: String, icon: UIImage? = nil, action: (() -> Void)?) {
|
|
self.id = id
|
|
self.label = label
|
|
self.text = text
|
|
self.icon = icon
|
|
self.action = action
|
|
}
|
|
|
|
func node() -> PeerInfoScreenItemNode {
|
|
return PeerInfoScreenDisclosureItemNode()
|
|
}
|
|
}
|
|
|
|
private final class PeerInfoScreenDisclosureItemNode: PeerInfoScreenItemNode {
|
|
private let selectionNode: PeerInfoScreenSelectableBackgroundNode
|
|
private let iconNode: ASImageNode
|
|
private let labelBadgeNode: ASImageNode
|
|
private let labelNode: ImmediateTextNode
|
|
private let textNode: ImmediateTextNode
|
|
private let arrowNode: ASImageNode
|
|
private let bottomSeparatorNode: ASDisplayNode
|
|
private let activateArea: AccessibilityAreaNode
|
|
|
|
private var item: PeerInfoScreenDisclosureItem?
|
|
|
|
override init() {
|
|
var bringToFrontForHighlightImpl: (() -> Void)?
|
|
self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() })
|
|
|
|
self.iconNode = ASImageNode()
|
|
self.iconNode.isLayerBacked = true
|
|
self.iconNode.displaysAsynchronously = false
|
|
|
|
self.labelBadgeNode = ASImageNode()
|
|
self.labelBadgeNode.displayWithoutProcessing = true
|
|
self.labelBadgeNode.displaysAsynchronously = false
|
|
self.labelBadgeNode.isLayerBacked = true
|
|
|
|
self.labelNode = ImmediateTextNode()
|
|
self.labelNode.displaysAsynchronously = false
|
|
self.labelNode.isUserInteractionEnabled = false
|
|
|
|
self.textNode = ImmediateTextNode()
|
|
self.textNode.displaysAsynchronously = false
|
|
self.textNode.isUserInteractionEnabled = false
|
|
|
|
self.arrowNode = ASImageNode()
|
|
self.arrowNode.isLayerBacked = true
|
|
self.arrowNode.displaysAsynchronously = false
|
|
self.arrowNode.displayWithoutProcessing = true
|
|
self.arrowNode.isUserInteractionEnabled = false
|
|
|
|
self.bottomSeparatorNode = ASDisplayNode()
|
|
self.bottomSeparatorNode.isLayerBacked = true
|
|
|
|
self.activateArea = AccessibilityAreaNode()
|
|
|
|
super.init()
|
|
|
|
bringToFrontForHighlightImpl = { [weak self] in
|
|
self?.bringToFrontForHighlight?()
|
|
}
|
|
|
|
self.addSubnode(self.bottomSeparatorNode)
|
|
self.addSubnode(self.selectionNode)
|
|
self.addSubnode(self.labelNode)
|
|
self.addSubnode(self.textNode)
|
|
self.addSubnode(self.arrowNode)
|
|
self.addSubnode(self.activateArea)
|
|
}
|
|
|
|
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
|
|
guard let item = item as? PeerInfoScreenDisclosureItem else {
|
|
return 10.0
|
|
}
|
|
|
|
let previousItem = self.item
|
|
self.item = item
|
|
|
|
self.selectionNode.pressed = item.action
|
|
|
|
let sideInset: CGFloat = 16.0 + safeInsets.left
|
|
let leftInset = (item.icon == nil ? sideInset : sideInset + 29.0 + 16.0)
|
|
let rightInset = sideInset + 18.0
|
|
let separatorInset = item.icon == nil ? sideInset : leftInset - 1.0
|
|
let titleFont = Font.regular(presentationData.listsFontSize.itemListBaseFontSize)
|
|
|
|
self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
|
|
|
let textColorValue: UIColor = presentationData.theme.list.itemPrimaryTextColor
|
|
let labelColorValue: UIColor
|
|
let labelFont: UIFont
|
|
if case .badge = item.label {
|
|
labelColorValue = presentationData.theme.list.itemCheckColors.foregroundColor
|
|
labelFont = Font.regular(15.0)
|
|
} else {
|
|
labelColorValue = presentationData.theme.list.itemSecondaryTextColor
|
|
labelFont = titleFont
|
|
}
|
|
self.labelNode.attributedText = NSAttributedString(string: item.label.text, font: labelFont, textColor: labelColorValue)
|
|
|
|
self.textNode.maximumNumberOfLines = 1
|
|
self.textNode.attributedText = NSAttributedString(string: item.text, font: titleFont, textColor: textColorValue)
|
|
|
|
let textSize = self.textNode.updateLayout(CGSize(width: width - (leftInset + rightInset), height: .greatestFiniteMagnitude))
|
|
let labelSize = self.labelNode.updateLayout(CGSize(width: width - textSize.width - (leftInset + rightInset), height: .greatestFiniteMagnitude))
|
|
|
|
let textFrame = CGRect(origin: CGPoint(x: leftInset, y: 12.0), size: textSize)
|
|
|
|
let height = textSize.height + 24.0
|
|
|
|
if let icon = item.icon {
|
|
if self.iconNode.supernode == nil {
|
|
self.addSubnode(self.iconNode)
|
|
}
|
|
self.iconNode.image = icon
|
|
let iconFrame = CGRect(origin: CGPoint(x: sideInset, y: floorToScreenPixels((height - icon.size.height) / 2.0)), size: icon.size)
|
|
transition.updateFrame(node: self.iconNode, frame: iconFrame)
|
|
} else if self.iconNode.supernode != nil {
|
|
self.iconNode.image = nil
|
|
self.iconNode.removeFromSupernode()
|
|
}
|
|
|
|
if let arrowImage = PresentationResourcesItemList.disclosureArrowImage(presentationData.theme) {
|
|
self.arrowNode.image = arrowImage
|
|
let arrowFrame = CGRect(origin: CGPoint(x: width - 7.0 - arrowImage.size.width - safeInsets.right, y: floorToScreenPixels((height - arrowImage.size.height) / 2.0)), size: arrowImage.size)
|
|
transition.updateFrame(node: self.arrowNode, frame: arrowFrame)
|
|
}
|
|
|
|
let badgeDiameter: CGFloat = 20.0
|
|
if case let .badge(text, badgeColor) = item.label, !text.isEmpty {
|
|
if previousItem?.label.badgeColor != badgeColor {
|
|
self.labelBadgeNode.image = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: badgeColor)
|
|
}
|
|
if self.labelBadgeNode.supernode == nil {
|
|
self.insertSubnode(self.labelBadgeNode, belowSubnode: self.labelNode)
|
|
}
|
|
} else {
|
|
self.labelBadgeNode.removeFromSupernode()
|
|
}
|
|
|
|
let badgeWidth = max(badgeDiameter, labelSize.width + 10.0)
|
|
let labelFrame: CGRect
|
|
if case .badge = item.label {
|
|
labelFrame = CGRect(origin: CGPoint(x: width - rightInset - badgeWidth + (badgeWidth - labelSize.width) / 2.0, y: floor((height - labelSize.height) / 2.0)), size: labelSize)
|
|
} else {
|
|
labelFrame = CGRect(origin: CGPoint(x: width - rightInset - labelSize.width, y: 12.0), size: labelSize)
|
|
}
|
|
|
|
let labelBadgeNodeFrame = CGRect(origin: CGPoint(x: width - rightInset - badgeWidth, y: labelFrame.minY - 1.0), size: CGSize(width: badgeWidth, height: badgeDiameter))
|
|
|
|
self.activateArea.accessibilityLabel = item.text
|
|
self.activateArea.accessibilityValue = item.label.text
|
|
|
|
transition.updateFrame(node: self.labelBadgeNode, frame: labelBadgeNodeFrame)
|
|
transition.updateFrame(node: self.labelNode, frame: labelFrame)
|
|
transition.updateFrame(node: self.textNode, frame: textFrame)
|
|
|
|
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: separatorInset, y: height - UIScreenPixel), size: CGSize(width: width - separatorInset, height: UIScreenPixel)))
|
|
transition.updateAlpha(node: self.bottomSeparatorNode, alpha: bottomItem == nil ? 0.0 : 1.0)
|
|
|
|
self.activateArea.frame = CGRect(origin: CGPoint(x: safeInsets.left, y: 0.0), size: CGSize(width: width - safeInsets.left - safeInsets.right, height: height))
|
|
|
|
return height
|
|
}
|
|
}
|