mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
118 lines
4.3 KiB
Swift
118 lines
4.3 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import AsyncDisplayKit
|
|
import Display
|
|
|
|
private class RadialTimeoutNodeParameters: NSObject {
|
|
let backgroundColor: UIColor
|
|
let foregroundColor: UIColor
|
|
let value: CGFloat
|
|
|
|
init(backgroundColor: UIColor, foregroundColor: UIColor, value: CGFloat) {
|
|
self.backgroundColor = backgroundColor
|
|
self.foregroundColor = foregroundColor
|
|
self.value = value
|
|
|
|
super.init()
|
|
}
|
|
}
|
|
|
|
private final class RadialTimeoutNodeTimer: NSObject {
|
|
let action: () -> Void
|
|
init(_ action: @escaping () -> Void) {
|
|
self.action = action
|
|
|
|
super.init()
|
|
}
|
|
|
|
@objc func event() {
|
|
self.action()
|
|
}
|
|
}
|
|
|
|
public final class RadialTimeoutNode: ASDisplayNode {
|
|
private var nodeBackgroundColor: UIColor
|
|
private var nodeForegroundColor: UIColor
|
|
|
|
private var timeout: (Double, Double)?
|
|
|
|
private var animationTimer: Timer?
|
|
|
|
public init(backgroundColor: UIColor, foregroundColor: UIColor) {
|
|
self.nodeBackgroundColor = backgroundColor
|
|
self.nodeForegroundColor = foregroundColor
|
|
|
|
super.init()
|
|
|
|
self.isOpaque = false
|
|
}
|
|
|
|
public func updateTheme(backgroundColor: UIColor, foregroundColor: UIColor) {
|
|
self.nodeBackgroundColor = backgroundColor
|
|
self.nodeForegroundColor = foregroundColor
|
|
|
|
self.setNeedsDisplay()
|
|
}
|
|
|
|
deinit {
|
|
self.animationTimer?.invalidate()
|
|
}
|
|
|
|
public func setTimeout(beginTimestamp: Double, timeout: Double) {
|
|
if self.timeout?.0 != beginTimestamp || self.timeout?.1 != timeout {
|
|
self.animationTimer?.invalidate()
|
|
self.timeout = (beginTimestamp, timeout)
|
|
|
|
let animationTimer = Timer(timeInterval: 1.0 / 60.0, target: RadialTimeoutNodeTimer({ [weak self] in
|
|
self?.setNeedsDisplay()
|
|
}), selector: #selector(RadialTimeoutNodeTimer.event), userInfo: nil, repeats: true)
|
|
self.animationTimer = animationTimer
|
|
RunLoop.main.add(animationTimer, forMode: .common)
|
|
}
|
|
}
|
|
|
|
public override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
|
|
var value: CGFloat = 0.0
|
|
if let (beginTimestamp, timeout) = self.timeout {
|
|
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
|
|
value = CGFloat(max(0.0, min(1.0, (timestamp - beginTimestamp) / timeout)))
|
|
}
|
|
return RadialTimeoutNodeParameters(backgroundColor: self.nodeBackgroundColor, foregroundColor: self.nodeForegroundColor, value: value)
|
|
}
|
|
|
|
@objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
|
|
let context = UIGraphicsGetCurrentContext()!
|
|
|
|
if !isRasterizing {
|
|
context.setBlendMode(.copy)
|
|
context.setFillColor(UIColor.clear.cgColor)
|
|
context.fill(bounds)
|
|
}
|
|
|
|
if let parameters = parameters as? RadialTimeoutNodeParameters {
|
|
context.setFillColor(parameters.backgroundColor.cgColor)
|
|
context.fillEllipse(in: CGRect(origin: CGPoint(), size: CGSize(width: bounds.size.width, height: bounds.size.height)))
|
|
|
|
context.setFillColor(parameters.foregroundColor.cgColor)
|
|
//context.fill(CGRect(origin: CGPoint(), size: CGSize(width: bounds.size.width, height: bounds.size.height * parameters.value)))
|
|
|
|
let radius = (bounds.size.width - 4.0) * 0.5
|
|
|
|
let viewCenter = CGPoint(x: bounds.size.width * 0.5, y: bounds.size.height * 0.5)
|
|
let startAngle = -CGFloat.pi * 0.5
|
|
|
|
// update the end angle of the segment
|
|
let endAngle = startAngle + 2.0 * CGFloat.pi * parameters.value
|
|
|
|
// move to the center of the pie chart
|
|
context.move(to: viewCenter)
|
|
|
|
// add arc from the center for each segment (anticlockwise is specified for the arc, but as the view flips the context, it will produce a clockwise arc)
|
|
context.addArc(center: viewCenter, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: false)
|
|
|
|
// fill segment
|
|
context.fillPath()
|
|
}
|
|
}
|
|
}
|