import Foundation import UIKit import AsyncDisplayKit import Display enum InstantPageSettingsItemNodeStatus { case none case sameSection case otherSection } class InstantPageSettingsItemNode: ASDisplayNode { private let topSeparatorNode: ASDisplayNode private let bottomSeparatorNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode? private let highlightButtonNode: HighlightTrackingButtonNode? init(theme: InstantPageSettingsItemTheme, selectable: Bool) { self.topSeparatorNode = ASDisplayNode() self.topSeparatorNode.isLayerBacked = true self.topSeparatorNode.isHidden = true self.bottomSeparatorNode = ASDisplayNode() self.bottomSeparatorNode.isLayerBacked = true self.bottomSeparatorNode.isHidden = true if selectable { let highlightedBackgroundNode = ASDisplayNode() highlightedBackgroundNode.isLayerBacked = true highlightedBackgroundNode.alpha = 0.0 self.highlightedBackgroundNode = highlightedBackgroundNode self.highlightButtonNode = HighlightTrackingButtonNode() } else { self.highlightedBackgroundNode = nil self.highlightButtonNode = nil } super.init() self.backgroundColor = theme.itemBackgroundColor self.addSubnode(self.topSeparatorNode) self.addSubnode(self.bottomSeparatorNode) if let highlightedBackgroundNode = self.highlightedBackgroundNode { self.addSubnode(highlightedBackgroundNode) } if let highlightButtonNode = self.highlightButtonNode { self.addSubnode(highlightButtonNode) highlightButtonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) highlightButtonNode.highligthedChanged = { [weak self] highlighted in if let strongSelf = self, let highlightedBackgroundNode = strongSelf.highlightedBackgroundNode { if highlighted { strongSelf.supernode?.view.bringSubviewToFront(strongSelf.view) highlightedBackgroundNode.layer.removeAnimation(forKey: "opacity") highlightedBackgroundNode.alpha = 1.0 } else { highlightedBackgroundNode.alpha = 0.0 highlightedBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2) } } } } self.updateTheme(theme) } func updateTheme(_ theme: InstantPageSettingsItemTheme) { self.backgroundColor = theme.itemBackgroundColor self.highlightedBackgroundNode?.backgroundColor = theme.itemHighlightedBackgroundColor self.topSeparatorNode.backgroundColor = theme.separatorColor self.bottomSeparatorNode.backgroundColor = theme.separatorColor } func updateInternalLayout(width: CGFloat, insets: UIEdgeInsets, previousItem: (InstantPageSettingsItemNodeStatus, InstantPageSettingsItemNode?), nextItem: (InstantPageSettingsItemNodeStatus, InstantPageSettingsItemNode?)) -> (height: CGFloat, separatorInset: CGFloat?) { return (44.0 + insets.top + insets.bottom, nil) } final func updateLayout(width: CGFloat, previousItem: (InstantPageSettingsItemNodeStatus, InstantPageSettingsItemNode?), nextItem: (InstantPageSettingsItemNodeStatus, InstantPageSettingsItemNode?)) -> CGFloat { let separatorHeight = UIScreenPixel let separatorInset: CGFloat = 0.0 var highlightExtension: CGFloat = 0.0 switch previousItem.0 { case .none: self.topSeparatorNode.isHidden = true case .sameSection: self.topSeparatorNode.isHidden = false case .otherSection: self.topSeparatorNode.isHidden = false } switch nextItem.0 { case .none: self.bottomSeparatorNode.isHidden = true case .sameSection: self.bottomSeparatorNode.isHidden = true highlightExtension = separatorHeight case .otherSection: self.bottomSeparatorNode.isHidden = false } let (internalHeight, internalSeparatorInset) = self.updateInternalLayout(width: width, insets: UIEdgeInsets(top: self.topSeparatorNode.isHidden ? 0.0 : separatorHeight, left: 0.0, bottom: self.bottomSeparatorNode.isHidden ? 0.0 : separatorHeight, right: 0.0), previousItem: previousItem, nextItem: nextItem) let finalSeparatorInset = internalSeparatorInset ?? separatorInset self.topSeparatorNode.frame = CGRect(origin: CGPoint(x: finalSeparatorInset, y: 0.0), size: CGSize(width: width - finalSeparatorInset, height: separatorHeight)) self.bottomSeparatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: internalHeight - separatorHeight), size: CGSize(width: width, height: separatorHeight)) if let highlightButtonNode = self.highlightButtonNode { highlightButtonNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -highlightExtension), size: CGSize(width: width, height: internalHeight + highlightExtension)) } if let highlightedBackgroundNode = self.highlightedBackgroundNode { highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: internalHeight + highlightExtension)) } return internalHeight } @objc func buttonPressed() { self.pressed() } func pressed() { } }