2022-04-23 05:28:29 +04:00

134 lines
5.0 KiB
Swift

import Foundation
import UIKit
import AsyncDisplayKit
import Display
import TelegramPresentationData
import ManagedAnimationNode
import ContextUI
public final class MoreButtonNode: ASDisplayNode {
public class MoreIconNode: ManagedAnimationNode {
public enum State: Equatable {
case more
case search
}
private let duration: Double = 0.21
public var iconState: State = .search
init() {
super.init(size: CGSize(width: 30.0, height: 30.0))
self.trackTo(item: ManagedAnimationItem(source: .local("anim_moretosearch"), frames: .range(startFrame: 90, endFrame: 90), duration: 0.0))
}
func play() {
if case .more = self.iconState {
self.trackTo(item: ManagedAnimationItem(source: .local("anim_moredots"), frames: .range(startFrame: 0, endFrame: 46), duration: 0.76))
}
}
public func enqueueState(_ state: State, animated: Bool) {
guard self.iconState != state else {
return
}
let previousState = self.iconState
self.iconState = state
let source = ManagedAnimationSource.local("anim_moretosearch")
let totalLength: Int = 90
if animated {
switch previousState {
case .more:
switch state {
case .more:
break
case .search:
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: 0, endFrame: totalLength), duration: self.duration))
}
case .search:
switch state {
case .more:
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: totalLength, endFrame: 0), duration: self.duration))
case .search:
break
}
}
} else {
switch state {
case .more:
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: 0, endFrame: 0), duration: 0.0))
case .search:
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: totalLength, endFrame: totalLength), duration: 0.0))
}
}
}
}
public var action: ((ASDisplayNode, ContextGesture?) -> Void)?
private let containerNode: ContextControllerSourceNode
public let contextSourceNode: ContextReferenceContentNode
private let buttonNode: HighlightableButtonNode
public let iconNode: MoreIconNode
public var theme: PresentationTheme {
didSet {
self.iconNode.customColor = self.theme.rootController.navigationBar.buttonColor
}
}
public init(theme: PresentationTheme) {
self.theme = theme
self.contextSourceNode = ContextReferenceContentNode()
self.containerNode = ContextControllerSourceNode()
self.containerNode.animateScale = false
self.buttonNode = HighlightableButtonNode()
self.iconNode = MoreIconNode()
self.iconNode.customColor = self.theme.rootController.navigationBar.buttonColor
super.init()
self.addSubnode(self.buttonNode)
self.buttonNode.addSubnode(self.containerNode)
self.containerNode.addSubnode(self.contextSourceNode)
self.contextSourceNode.addSubnode(self.iconNode)
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
self.containerNode.activated = { [weak self] gesture, _ in
guard let strongSelf = self else {
return
}
if case .more = strongSelf.iconNode.iconState {
strongSelf.action?(strongSelf.contextSourceNode, gesture)
}
}
}
@objc public func buttonPressed() {
self.action?(self.contextSourceNode, nil)
if case .more = self.iconNode.iconState {
self.iconNode.play()
}
}
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
let animationSize = CGSize(width: 30.0, height: 30.0)
let inset: CGFloat = 0.0
self.iconNode.frame = CGRect(origin: CGPoint(x: inset + 6.0, y: floor((constrainedSize.height - animationSize.height) / 2.0) + 1.0), size: animationSize)
let size = CGSize(width: animationSize.width + inset * 2.0, height: constrainedSize.height)
let bounds = CGRect(origin: CGPoint(), size: size)
self.buttonNode.frame = bounds
self.containerNode.frame = bounds
self.contextSourceNode.frame = bounds
return size
}
}