Swiftgram/submodules/TelegramUI/Sources/ShimmeringLinkNode.swift
2023-01-18 01:13:56 +04:00

100 lines
3.7 KiB
Swift

import Foundation
import UIKit
import AsyncDisplayKit
import Display
import ShimmerEffect
final class ShimmeringLinkNode: ASDisplayNode {
private let shimmerEffectNode: ShimmerEffectForegroundNode
private let borderShimmerEffectNode: ShimmerEffectForegroundNode
private let maskNode: ASImageNode
private let borderMaskNode: ASImageNode
private(set) var rects: [CGRect] = []
var color: UIColor {
didSet {
self.backgroundColor = color
}
}
var innerRadius: CGFloat = 4.0
var outerRadius: CGFloat = 4.0
var inset: CGFloat = 2.0
init(color: UIColor) {
self.color = color
self.shimmerEffectNode = ShimmerEffectForegroundNode()
self.borderShimmerEffectNode = ShimmerEffectForegroundNode()
self.maskNode = ASImageNode()
self.maskNode.displaysAsynchronously = false
self.maskNode.displayWithoutProcessing = true
self.borderMaskNode = ASImageNode()
self.borderMaskNode.displaysAsynchronously = false
self.borderMaskNode.displayWithoutProcessing = true
super.init()
self.isLayerBacked = true
self.shimmerEffectNode.backgroundColor = color.withAlphaComponent(color.alpha * 0.6)
self.addSubnode(self.shimmerEffectNode)
//self.addSubnode(self.borderShimmerEffectNode)
}
override func didLoad() {
super.didLoad()
self.shimmerEffectNode.layer.mask = self.maskNode.layer
self.borderShimmerEffectNode.layer.mask = self.borderMaskNode.layer
}
func updateRects(_ rects: [CGRect], color: UIColor? = nil) {
var updated = false
if self.rects != rects {
updated = true
self.rects = rects
}
if let color, !color.isEqual(self.color) {
updated = true
self.color = color
}
if updated {
self.updateMasks()
}
}
private func updateMasks() {
let (offset, image) = generateRectsImage(color: .white, rects: self.rects, inset: self.inset, outerRadius: self.outerRadius, innerRadius: self.innerRadius, useModernPathCalculation: true)
let (borderOffset, borderImage) = generateRectsImage(color: .white, rects: self.rects.map { $0.insetBy(dx: 0.0, dy: 0.0) }, inset: self.inset, outerRadius: self.outerRadius, innerRadius: self.innerRadius, stroke: true, useModernPathCalculation: true)
if let image = image {
self.maskNode.frame = CGRect(origin: offset, size: image.size)
self.maskNode.image = image
}
if let borderImage = borderImage {
self.borderMaskNode.frame = CGRect(origin: borderOffset, size: borderImage.size)
self.borderMaskNode.image = borderImage
}
}
func updateLayout(_ size: CGSize) {
self.shimmerEffectNode.frame = CGRect(origin: .zero, size: size)
self.borderShimmerEffectNode.frame = CGRect(origin: .zero, size: size)
self.shimmerEffectNode.updateAbsoluteRect(CGRect(origin: .zero, size: size), within: size)
self.borderShimmerEffectNode.updateAbsoluteRect(CGRect(origin: .zero, size: size), within: size)
self.shimmerEffectNode.update(backgroundColor: .clear, foregroundColor: self.color.withAlphaComponent(min(1.0, self.color.alpha * 1.2)), horizontal: true, effectSize: nil, globalTimeOffset: false, duration: nil)
self.borderShimmerEffectNode.update(backgroundColor: .clear, foregroundColor: self.color.withAlphaComponent(min(1.0, self.color.alpha * 1.5)), horizontal: true, effectSize: nil, globalTimeOffset: false, duration: nil)
}
}