mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-07-28 22:20:52 +00:00
104 lines
3.3 KiB
Swift
104 lines
3.3 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Display
|
|
import ComponentFlow
|
|
|
|
final class AvatarLayer: SimpleLayer {
|
|
struct Params: Equatable {
|
|
var size: CGSize
|
|
var cornerRadius: CGFloat
|
|
var isExpanded: Bool
|
|
|
|
init(size: CGSize, cornerRadius: CGFloat, isExpanded: Bool) {
|
|
self.size = size
|
|
self.cornerRadius = cornerRadius
|
|
self.isExpanded = isExpanded
|
|
}
|
|
}
|
|
|
|
private(set) var params: Params?
|
|
private var rasterizedImage: UIImage?
|
|
private var isAnimating: Bool = false
|
|
|
|
var image: UIImage? {
|
|
didSet {
|
|
if self.image !== oldValue {
|
|
self.updateImage()
|
|
}
|
|
}
|
|
}
|
|
|
|
override init() {
|
|
super.init()
|
|
|
|
self.contentsGravity = .resizeAspectFill
|
|
self.masksToBounds = true
|
|
}
|
|
|
|
override init(layer: Any) {
|
|
super.init(layer: layer)
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
private func updateImage() {
|
|
guard let params else {
|
|
return
|
|
}
|
|
|
|
if self.isAnimating || params.isExpanded {
|
|
self.contents = self.image?.cgImage
|
|
} else {
|
|
self.contents = self.image.flatMap({ image -> UIImage? in
|
|
let imageSize = CGSize(width: min(params.size.width, params.size.height), height: min(params.size.width, params.size.height))
|
|
|
|
return generateImage(imageSize, contextGenerator: { size, context in
|
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
|
if params.cornerRadius == size.width * 0.5 {
|
|
context.addEllipse(in: CGRect(origin: CGPoint(), size: size))
|
|
} else {
|
|
context.addPath(UIBezierPath(roundedRect: CGRect(origin: CGPoint(), size: size), cornerRadius: params.cornerRadius).cgPath)
|
|
}
|
|
context.clip()
|
|
|
|
if let cgImage = image.cgImage {
|
|
context.draw(cgImage, in: CGRect(origin: CGPoint(), size: size))
|
|
}
|
|
})
|
|
})?.cgImage
|
|
}
|
|
}
|
|
|
|
func update(size: CGSize, isExpanded: Bool, cornerRadius: CGFloat, transition: Transition) {
|
|
let params = Params(size: size, cornerRadius: cornerRadius, isExpanded: isExpanded)
|
|
if self.params == params {
|
|
return
|
|
}
|
|
let previousCornerRadius = self.params?.cornerRadius
|
|
self.params = params
|
|
|
|
if previousCornerRadius != params.cornerRadius {
|
|
self.masksToBounds = true
|
|
self.isAnimating = true
|
|
self.updateImage()
|
|
|
|
if let previousCornerRadius, self.animation(forKey: "cornerRadius") == nil {
|
|
self.cornerRadius = previousCornerRadius
|
|
}
|
|
transition.setCornerRadius(layer: self, cornerRadius: cornerRadius, completion: { [weak self] completed in
|
|
guard let self, completed else {
|
|
return
|
|
}
|
|
|
|
self.isAnimating = false
|
|
self.masksToBounds = false
|
|
self.cornerRadius = 0.0
|
|
|
|
self.updateImage()
|
|
})
|
|
}
|
|
}
|
|
}
|