mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
114 lines
4.3 KiB
Swift
114 lines
4.3 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Display
|
|
import ComponentFlow
|
|
|
|
public final class ProgressIndicatorComponent: Component {
|
|
public let diameter: CGFloat
|
|
public let value: Double
|
|
public let backgroundColor: UIColor
|
|
public let foregroundColor: UIColor
|
|
|
|
public init(
|
|
diameter: CGFloat,
|
|
backgroundColor: UIColor,
|
|
foregroundColor: UIColor,
|
|
value: Double
|
|
) {
|
|
self.diameter = diameter
|
|
self.backgroundColor = backgroundColor
|
|
self.foregroundColor = foregroundColor
|
|
self.value = value
|
|
}
|
|
|
|
public static func ==(lhs: ProgressIndicatorComponent, rhs: ProgressIndicatorComponent) -> Bool {
|
|
if lhs.diameter != rhs.diameter {
|
|
return false
|
|
}
|
|
if lhs.backgroundColor != rhs.backgroundColor {
|
|
return false
|
|
}
|
|
if lhs.foregroundColor != rhs.foregroundColor {
|
|
return false
|
|
}
|
|
if lhs.value != rhs.value {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
public final class View: UIView {
|
|
private var currentComponent: ProgressIndicatorComponent?
|
|
|
|
private let foregroundShapeLayer: SimpleShapeLayer
|
|
|
|
public init() {
|
|
self.foregroundShapeLayer = SimpleShapeLayer()
|
|
self.foregroundShapeLayer.isOpaque = false
|
|
self.foregroundShapeLayer.backgroundColor = nil
|
|
self.foregroundShapeLayer.fillColor = nil
|
|
self.foregroundShapeLayer.lineCap = .round
|
|
|
|
super.init(frame: CGRect())
|
|
|
|
let shapeLayer = self.layer as! CAShapeLayer
|
|
shapeLayer.isOpaque = false
|
|
shapeLayer.backgroundColor = nil
|
|
shapeLayer.fillColor = nil
|
|
|
|
self.layer.addSublayer(self.foregroundShapeLayer)
|
|
}
|
|
|
|
required public init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override public static var layerClass: AnyClass {
|
|
return CAShapeLayer.self
|
|
}
|
|
|
|
func update(component: ProgressIndicatorComponent, availableSize: CGSize, transition: ComponentTransition) -> CGSize {
|
|
let lineWidth: CGFloat = 1.33
|
|
let size = CGSize(width: component.diameter, height: component.diameter)
|
|
|
|
let shapeLayer = self.layer as! CAShapeLayer
|
|
|
|
if self.currentComponent?.backgroundColor != component.backgroundColor {
|
|
shapeLayer.strokeColor = component.backgroundColor.cgColor
|
|
shapeLayer.lineWidth = lineWidth
|
|
}
|
|
|
|
if self.currentComponent?.foregroundColor != component.foregroundColor {
|
|
self.foregroundShapeLayer.strokeColor = component.foregroundColor.cgColor
|
|
self.foregroundShapeLayer.lineWidth = lineWidth
|
|
}
|
|
|
|
if self.currentComponent?.diameter != component.diameter {
|
|
let path = UIBezierPath(arcCenter: CGPoint(x: component.diameter / 2.0, y: component.diameter / 2.0), radius: component.diameter / 2.0, startAngle: -CGFloat.pi / 2.0, endAngle: 2.0 * CGFloat.pi - CGFloat.pi / 2.0, clockwise: true).cgPath
|
|
shapeLayer.path = path
|
|
self.foregroundShapeLayer.path = path
|
|
|
|
self.foregroundShapeLayer.frame = CGRect(origin: CGPoint(), size: size)
|
|
}
|
|
|
|
if self.currentComponent != nil {
|
|
let previousValue: CGFloat = self.foregroundShapeLayer.presentation()?.strokeEnd ?? self.foregroundShapeLayer.strokeEnd
|
|
self.foregroundShapeLayer.animate(from: CGFloat(previousValue) as NSNumber, to: CGFloat(component.value) as NSNumber, keyPath: "strokeEnd", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: 0.12)
|
|
}
|
|
self.foregroundShapeLayer.strokeEnd = CGFloat(component.value)
|
|
|
|
self.currentComponent = component
|
|
|
|
return size
|
|
}
|
|
}
|
|
|
|
public func makeView() -> View {
|
|
return View()
|
|
}
|
|
|
|
public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
|
return view.update(component: self, availableSize: availableSize, transition: transition)
|
|
}
|
|
}
|