Ilya Laktyushin f7e6755a39 Update API
2024-09-19 03:24:24 +04:00

108 lines
4.6 KiB
Swift

import Foundation
import UIKit
import Display
import AppBundle
import HierarchyTrackingLayer
import ComponentFlow
import TextLoadingEffect
public final class ItemShimmeringLoadingComponent: Component {
private let color: UIColor
private let cornerRadius: CGFloat
public init(
color: UIColor,
cornerRadius: CGFloat = 10.0
) {
self.color = color
self.cornerRadius = cornerRadius
}
public static func ==(lhs: ItemShimmeringLoadingComponent, rhs: ItemShimmeringLoadingComponent) -> Bool {
if !lhs.color.isEqual(rhs.color) {
return false
}
if lhs.cornerRadius != rhs.cornerRadius {
return false
}
return true
}
public final class View: UIView {
private let loadingView = TextLoadingEffectView()
private let borderView = UIImageView()
private let borderMaskView = UIView()
private let borderMaskGradientView = UIImageView()
private let borderMaskFillView = UIImageView()
private var component: ItemShimmeringLoadingComponent?
override public init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(self.loadingView)
self.addSubview(self.borderView)
self.borderMaskView.backgroundColor = .clear
self.borderMaskFillView.backgroundColor = .white
self.borderMaskView.addSubview(self.borderMaskFillView)
self.borderMaskFillView.addSubview(self.borderMaskGradientView)
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func playAppearanceAnimation() {
self.borderView.mask = self.borderMaskView
let gradientWidth = self.borderView.bounds.width * 0.4
self.borderMaskGradientView.image = generateGradientImage(size: CGSize(width: gradientWidth, height: 24.0), colors: [UIColor.white, UIColor.white.withAlphaComponent(0.0)], locations: [0.0, 1.0], direction: .horizontal)
self.borderMaskGradientView.frame = CGRect(origin: CGPoint(x: self.borderView.bounds.width, y: 0.0), size: CGSize(width: gradientWidth, height: self.borderView.bounds.height))
self.borderMaskFillView.frame = CGRect(origin: .zero, size: self.borderView.bounds.size)
self.borderMaskFillView.layer.animatePosition(from: CGPoint(x: -self.borderView.bounds.width, y: 0.0), to: .zero, duration: 1.0, removeOnCompletion: false, additive: true, completion: { _ in
self.borderView.mask = nil
})
}
func update(component: ItemShimmeringLoadingComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
let isFirstTime = self.component == nil
let previousCornerRadius = self.component?.cornerRadius
self.component = component
if previousCornerRadius != component.cornerRadius {
self.borderView.image = generateFilledRoundedRectImage(size: CGSize(width: 24.0, height: 24.0), cornerRadius: component.cornerRadius, color: nil, strokeColor: .white, strokeWidth: 1.0 + UIScreenPixel, backgroundColor: nil)?.stretchableImage(withLeftCapWidth: Int(component.cornerRadius), topCapHeight: Int(component.cornerRadius)).withRenderingMode(.alwaysTemplate)
}
self.borderView.tintColor = component.color
self.loadingView.update(color: component.color, rect: CGRect(origin: .zero, size: availableSize))
self.loadingView.frame = CGRect(origin: .zero, size: availableSize)
self.loadingView.layer.cornerRadius = component.cornerRadius
self.loadingView.clipsToBounds = true
transition.setFrame(view: self.borderView, frame: CGRect(origin: .zero, size: availableSize))
self.borderMaskView.frame = self.borderView.bounds
if isFirstTime {
self.playAppearanceAnimation()
}
return availableSize
}
}
public func makeView() -> View {
return View(frame: CGRect())
}
public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}