Various fixes

This commit is contained in:
Ilya Laktyushin
2024-12-12 20:41:33 +04:00
parent 9e908c9ea7
commit ad9f0d6847
14 changed files with 214 additions and 31 deletions

View File

@@ -382,12 +382,102 @@ private final class LoadingProgressNode: ASDisplayNode {
}
}
private final class BadgeNode: ASDisplayNode {
private var fillColor: UIColor
private var strokeColor: UIColor
private var textColor: UIColor
private let textNode: ImmediateTextNode
private let backgroundNode: ASImageNode
private let font: UIFont = Font.with(size: 15.0, design: .round, weight: .bold)
var text: String = "" {
didSet {
self.textNode.attributedText = NSAttributedString(string: self.text, font: self.font, textColor: self.textColor)
self.invalidateCalculatedLayout()
}
}
init(fillColor: UIColor, strokeColor: UIColor, textColor: UIColor) {
self.fillColor = fillColor
self.strokeColor = strokeColor
self.textColor = textColor
self.textNode = ImmediateTextNode()
self.textNode.isUserInteractionEnabled = false
self.textNode.displaysAsynchronously = false
self.backgroundNode = ASImageNode()
self.backgroundNode.isLayerBacked = true
self.backgroundNode.displayWithoutProcessing = true
self.backgroundNode.displaysAsynchronously = false
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 18.0, color: fillColor, strokeColor: nil, strokeWidth: 1.0)
super.init()
self.addSubnode(self.backgroundNode)
self.addSubnode(self.textNode)
self.isUserInteractionEnabled = false
}
func updateTheme(fillColor: UIColor, strokeColor: UIColor, textColor: UIColor) {
self.fillColor = fillColor
self.strokeColor = strokeColor
self.textColor = textColor
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 18.0, color: fillColor, strokeColor: strokeColor, strokeWidth: 1.0)
self.textNode.attributedText = NSAttributedString(string: self.text, font: self.font, textColor: self.textColor)
}
func animateBump(incremented: Bool) {
if incremented {
let firstTransition = ContainedViewLayoutTransition.animated(duration: 0.1, curve: .easeInOut)
firstTransition.updateTransformScale(layer: self.backgroundNode.layer, scale: 1.2)
firstTransition.updateTransformScale(layer: self.textNode.layer, scale: 1.2, completion: { finished in
if finished {
let secondTransition = ContainedViewLayoutTransition.animated(duration: 0.1, curve: .easeInOut)
secondTransition.updateTransformScale(layer: self.backgroundNode.layer, scale: 1.0)
secondTransition.updateTransformScale(layer: self.textNode.layer, scale: 1.0)
}
})
} else {
let firstTransition = ContainedViewLayoutTransition.animated(duration: 0.1, curve: .easeInOut)
firstTransition.updateTransformScale(layer: self.backgroundNode.layer, scale: 0.8)
firstTransition.updateTransformScale(layer: self.textNode.layer, scale: 0.8, completion: { finished in
if finished {
let secondTransition = ContainedViewLayoutTransition.animated(duration: 0.1, curve: .easeInOut)
secondTransition.updateTransformScale(layer: self.backgroundNode.layer, scale: 1.0)
secondTransition.updateTransformScale(layer: self.textNode.layer, scale: 1.0)
}
})
}
}
func animateOut() {
let timingFunction = CAMediaTimingFunctionName.easeInEaseOut.rawValue
self.backgroundNode.layer.animateScale(from: 1.0, to: 0.1, duration: 0.3, delay: 0.0, timingFunction: timingFunction, removeOnCompletion: true, completion: nil)
self.textNode.layer.animateScale(from: 1.0, to: 0.1, duration: 0.3, delay: 0.0, timingFunction: timingFunction, removeOnCompletion: true, completion: nil)
}
func update(_ constrainedSize: CGSize) -> CGSize {
let badgeSize = self.textNode.updateLayout(constrainedSize)
let backgroundSize = CGSize(width: max(18.0, badgeSize.width + 8.0), height: 18.0)
let backgroundFrame = CGRect(origin: CGPoint(), size: backgroundSize)
self.backgroundNode.frame = backgroundFrame
self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels(backgroundFrame.midX - badgeSize.width / 2.0), y: floorToScreenPixels((backgroundFrame.size.height - badgeSize.height) / 2.0) - UIScreenPixel), size: badgeSize)
return backgroundSize
}
}
private final class MainButtonNode: HighlightTrackingButtonNode {
private var state: AttachmentMainButtonState
private var size: CGSize?
private let backgroundAnimationNode: ASImageNode
fileprivate let textNode: ImmediateTextNode
private var badgeNode: BadgeNode?
private let statusNode: SemanticStatusNode
private var progressNode: ASImageNode?
@@ -616,6 +706,7 @@ private final class MainButtonNode: HighlightTrackingButtonNode {
progressNode.image = generateIndefiniteActivityIndicatorImage(color: state.textColor, diameter: diameter, lineWidth: 3.0)
}
var textFrame: CGRect = .zero
if let text = state.text {
let font: UIFont
switch state.font {
@@ -627,13 +718,7 @@ private final class MainButtonNode: HighlightTrackingButtonNode {
self.textNode.attributedText = NSAttributedString(string: text, font: font, textColor: state.textColor)
let textSize = self.textNode.updateLayout(size)
let textFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize)
if self.textNode.frame.width.isZero {
self.textNode.frame = textFrame
} else {
self.textNode.bounds = CGRect(origin: .zero, size: textSize)
transition.updatePosition(node: self.textNode, position: textFrame.center)
}
textFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize)
switch state.background {
case let .color(backgroundColor):
@@ -669,6 +754,40 @@ private final class MainButtonNode: HighlightTrackingButtonNode {
}
}
if let badge = state.badge {
let badgeNode: BadgeNode
var badgeTransition = transition
if let current = self.badgeNode {
badgeNode = current
} else {
badgeTransition = .immediate
var textColor: UIColor
switch state.background {
case let .color(backgroundColor):
textColor = backgroundColor
case .premium:
textColor = UIColor(rgb: 0x0077ff)
}
badgeNode = BadgeNode(fillColor: state.textColor, strokeColor: .clear, textColor: textColor)
self.badgeNode = badgeNode
self.addSubnode(badgeNode)
}
badgeNode.text = badge
let badgeSize = badgeNode.update(CGSize(width: 100.0, height: 100.0))
textFrame.origin.x -= badgeSize.width / 2.0
badgeTransition.updateFrame(node: badgeNode, frame: CGRect(origin: CGPoint(x: textFrame.maxX + 6.0, y: textFrame.minY + floorToScreenPixels((textFrame.height - badgeSize.height) * 0.5)), size: badgeSize))
} else if let badgeNode = self.badgeNode {
self.badgeNode = nil
badgeNode.removeFromSupernode()
}
if self.textNode.frame.width.isZero {
self.textNode.frame = textFrame
} else {
self.textNode.bounds = CGRect(origin: .zero, size: textFrame.size)
transition.updatePosition(node: self.textNode, position: textFrame.center)
}
if previousState.progress != state.progress {
if state.progress == .center {
self.transitionToProgress()