mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
158 lines
6.7 KiB
Swift
158 lines
6.7 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import AsyncDisplayKit
|
|
import Display
|
|
import TelegramPresentationData
|
|
|
|
public class WebAppCancelButtonNode: ASDisplayNode {
|
|
public enum State {
|
|
case cancel
|
|
case back
|
|
}
|
|
|
|
public let buttonNode: HighlightTrackingButtonNode
|
|
private let arrowNode: ASImageNode
|
|
private let labelNode: ImmediateTextNode
|
|
|
|
public var state: State = .cancel
|
|
|
|
private var color: UIColor?
|
|
|
|
private var _theme: PresentationTheme
|
|
public var theme: PresentationTheme {
|
|
get {
|
|
return self._theme
|
|
}
|
|
set {
|
|
self._theme = newValue
|
|
self.setState(self.state, animated: false, animateScale: false, force: true)
|
|
}
|
|
}
|
|
private let strings: PresentationStrings
|
|
|
|
private weak var colorSnapshotView: UIView?
|
|
|
|
public func updateColor(_ color: UIColor?, transition: ContainedViewLayoutTransition) {
|
|
let previousColor = self.color
|
|
self.color = color
|
|
|
|
if case let .animated(duration, curve) = transition, previousColor != color, !self.animatingStateChange {
|
|
if let snapshotView = self.view.snapshotContentTree() {
|
|
snapshotView.frame = self.bounds
|
|
self.view.addSubview(snapshotView)
|
|
self.colorSnapshotView = snapshotView
|
|
|
|
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, timingFunction: curve.timingFunction, removeOnCompletion: false, completion: { _ in
|
|
snapshotView.removeFromSuperview()
|
|
})
|
|
self.arrowNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, timingFunction: curve.timingFunction)
|
|
self.labelNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, timingFunction: curve.timingFunction)
|
|
}
|
|
}
|
|
self.setState(self.state, animated: false, animateScale: false, force: true)
|
|
}
|
|
|
|
public init(theme: PresentationTheme, strings: PresentationStrings) {
|
|
self._theme = theme
|
|
self.strings = strings
|
|
|
|
self.buttonNode = HighlightTrackingButtonNode()
|
|
|
|
self.arrowNode = ASImageNode()
|
|
self.arrowNode.displaysAsynchronously = false
|
|
|
|
self.labelNode = ImmediateTextNode()
|
|
self.labelNode.displaysAsynchronously = false
|
|
|
|
super.init()
|
|
|
|
self.addSubnode(self.buttonNode)
|
|
self.buttonNode.addSubnode(self.arrowNode)
|
|
self.buttonNode.addSubnode(self.labelNode)
|
|
|
|
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
|
guard let strongSelf = self else {
|
|
return
|
|
}
|
|
if highlighted {
|
|
strongSelf.arrowNode.layer.removeAnimation(forKey: "opacity")
|
|
strongSelf.arrowNode.alpha = 0.4
|
|
strongSelf.labelNode.layer.removeAnimation(forKey: "opacity")
|
|
strongSelf.labelNode.alpha = 0.4
|
|
} else {
|
|
strongSelf.arrowNode.alpha = 1.0
|
|
strongSelf.arrowNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
|
strongSelf.labelNode.alpha = 1.0
|
|
strongSelf.labelNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
|
}
|
|
}
|
|
|
|
self.setState(.cancel, animated: false, force: true)
|
|
}
|
|
|
|
public func setTheme(_ theme: PresentationTheme, animated: Bool) {
|
|
self._theme = theme
|
|
var animated = animated
|
|
if self.animatingStateChange {
|
|
animated = false
|
|
}
|
|
self.setState(self.state, animated: animated, animateScale: false, force: true)
|
|
}
|
|
|
|
private var animatingStateChange = false
|
|
public func setState(_ state: State, animated: Bool, animateScale: Bool = true, force: Bool = false) {
|
|
guard self.state != state || force else {
|
|
return
|
|
}
|
|
self.state = state
|
|
|
|
if let colorSnapshotView = self.colorSnapshotView {
|
|
self.colorSnapshotView = nil
|
|
colorSnapshotView.removeFromSuperview()
|
|
}
|
|
|
|
if animated, let snapshotView = self.buttonNode.view.snapshotContentTree() {
|
|
self.animatingStateChange = true
|
|
snapshotView.layer.sublayerTransform = self.buttonNode.subnodeTransform
|
|
self.view.addSubview(snapshotView)
|
|
|
|
let duration: Double = animateScale ? 0.25 : 0.3
|
|
if animateScale {
|
|
snapshotView.layer.animateScale(from: 1.0, to: 0.001, duration: 0.25, removeOnCompletion: false)
|
|
}
|
|
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
|
snapshotView?.removeFromSuperview()
|
|
self.animatingStateChange = false
|
|
})
|
|
|
|
if animateScale {
|
|
self.buttonNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.25)
|
|
}
|
|
self.buttonNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
|
}
|
|
|
|
let color = self.color ?? self.theme.rootController.navigationBar.accentTextColor
|
|
|
|
self.arrowNode.isHidden = state == .cancel
|
|
self.labelNode.attributedText = NSAttributedString(string: state == .cancel ? self.strings.Common_Close : self.strings.Common_Back, font: Font.regular(17.0), textColor: color)
|
|
|
|
let labelSize = self.labelNode.updateLayout(CGSize(width: 120.0, height: 56.0))
|
|
|
|
self.buttonNode.frame = CGRect(origin: .zero, size: CGSize(width: labelSize.width, height: self.buttonNode.frame.height))
|
|
self.arrowNode.image = NavigationBarTheme.generateBackArrowImage(color: color)
|
|
if let image = self.arrowNode.image {
|
|
self.arrowNode.frame = CGRect(origin: self.arrowNode.frame.origin, size: image.size)
|
|
}
|
|
self.labelNode.frame = CGRect(origin: self.labelNode.frame.origin, size: labelSize)
|
|
self.buttonNode.subnodeTransform = CATransform3DMakeTranslation(state == .back ? 11.0 : 0.0, 0.0, 0.0)
|
|
}
|
|
|
|
override public func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
|
self.buttonNode.frame = CGRect(origin: .zero, size: CGSize(width: self.buttonNode.frame.width, height: constrainedSize.height))
|
|
self.arrowNode.frame = CGRect(origin: CGPoint(x: -19.0, y: floorToScreenPixels((constrainedSize.height - self.arrowNode.frame.size.height) / 2.0)), size: self.arrowNode.frame.size)
|
|
self.labelNode.frame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((constrainedSize.height - self.labelNode.frame.size.height) / 2.0)), size: self.labelNode.frame.size)
|
|
|
|
return CGSize(width: 70.0, height: 56.0)
|
|
}
|
|
}
|