mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
113 lines
4.1 KiB
Swift
113 lines
4.1 KiB
Swift
import UIKit
|
|
import AsyncDisplayKit
|
|
|
|
private let groupSpacing: CGFloat = 8.0
|
|
|
|
final class ActionSheetItemGroupsContainerNode: ASDisplayNode {
|
|
var theme: ActionSheetControllerTheme {
|
|
didSet {
|
|
self.setGroups(self.groups)
|
|
if let size = self.validSize {
|
|
let _ = self.updateLayout(constrainedSize: size, transition: .immediate)
|
|
}
|
|
}
|
|
}
|
|
|
|
private var groups: [ActionSheetItemGroup] = []
|
|
var groupNodes: [ActionSheetItemGroupNode] = []
|
|
|
|
var requestLayout: (() -> Void)?
|
|
|
|
private var validSize: CGSize?
|
|
|
|
init(theme: ActionSheetControllerTheme) {
|
|
self.theme = theme
|
|
|
|
super.init()
|
|
}
|
|
|
|
func setGroups(_ groups: [ActionSheetItemGroup]) {
|
|
self.groups = groups
|
|
|
|
for groupNode in self.groupNodes {
|
|
groupNode.removeFromSupernode()
|
|
}
|
|
self.groupNodes.removeAll()
|
|
|
|
for group in groups {
|
|
let groupNode = ActionSheetItemGroupNode(theme: self.theme)
|
|
let itemNodes = group.items.map({ $0.node(theme: self.theme) })
|
|
|
|
for node in itemNodes {
|
|
node.requestLayout = { [weak self] in
|
|
self?.requestLayout?()
|
|
}
|
|
}
|
|
groupNode.updateItemNodes(itemNodes, leadingVisibleNodeCount: group.leadingVisibleNodeCount ?? 1000.0)
|
|
self.groupNodes.append(groupNode)
|
|
self.addSubnode(groupNode)
|
|
}
|
|
}
|
|
|
|
func updateLayout(constrainedSize: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
|
self.validSize = constrainedSize
|
|
|
|
var groupsHeight: CGFloat = 0.0
|
|
|
|
var calculatedSizes: [CGSize] = []
|
|
for groupNode in self.groupNodes.reversed() {
|
|
if CGFloat(0.0).isLess(than: groupsHeight) {
|
|
groupsHeight += groupSpacing
|
|
}
|
|
|
|
let size = groupNode.updateLayout(constrainedSize: CGSize(width: constrainedSize.width, height: max(0.0, constrainedSize.height - groupsHeight)), transition: transition)
|
|
calculatedSizes.insert(size, at: 0)
|
|
|
|
groupsHeight += size.height
|
|
}
|
|
|
|
var itemGroupsHeight: CGFloat = 0.0
|
|
for i in 0 ..< self.groupNodes.count {
|
|
let groupNode = self.groupNodes[i]
|
|
|
|
let size = calculatedSizes[i]
|
|
if i != 0 {
|
|
itemGroupsHeight += groupSpacing
|
|
transition.updateFrame(view: self.groupNodes[i - 1].trailingDimView, frame: CGRect(x: 0.0, y: groupNodes[i - 1].bounds.size.height, width: size.width, height: groupSpacing))
|
|
}
|
|
transition.updateFrame(node: groupNode, frame: CGRect(origin: CGPoint(x: 0.0, y: itemGroupsHeight), size: size))
|
|
transition.updateFrame(view: groupNode.trailingDimView, frame: CGRect())
|
|
|
|
itemGroupsHeight += size.height
|
|
}
|
|
return CGSize(width: constrainedSize.width, height: min(groupsHeight, constrainedSize.height))
|
|
}
|
|
|
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
for groupNode in self.groupNodes {
|
|
if groupNode.frame.contains(point) {
|
|
return groupNode.hitTest(self.convert(point, to: groupNode), with: event)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func animateDimViewsAlpha(from: CGFloat, to: CGFloat, duration: Double) {
|
|
for node in self.groupNodes {
|
|
node.animateDimViewsAlpha(from: from, to: to, duration: duration)
|
|
}
|
|
}
|
|
|
|
public func updateItem(groupIndex: Int, itemIndex: Int, _ f: (ActionSheetItem) -> ActionSheetItem) {
|
|
var item = self.groups[groupIndex].items[itemIndex]
|
|
let itemNode = self.groupNodes[groupIndex].itemNode(at: itemIndex)
|
|
item = f(item)
|
|
item.updateNode(itemNode)
|
|
|
|
var groupItems = self.groups[groupIndex].items
|
|
groupItems[itemIndex] = item
|
|
|
|
self.groups[groupIndex] = ActionSheetItemGroup(items: groupItems)
|
|
}
|
|
}
|