2025-03-07 17:52:50 +01:00

141 lines
5.7 KiB
Swift

import Foundation
import UIKit
import Display
import ComponentFlow
import AccountContext
import TelegramCore
private let premiumBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white)
private let featuredBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/PanelBadgeAdd"), color: .white)
private let lockedBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/PanelBadgeLock"), color: .white)
private let itemBadgeTextFont: UIFont = {
return Font.regular(10.0)
}()
final class PremiumBadgeView: UIView {
private let context: AccountContext
private var badge: EmojiKeyboardItemLayer.Badge?
let contentLayer: SimpleLayer
private let overlayColorLayer: SimpleLayer
private let iconLayer: SimpleLayer
private var customFileLayer: InlineFileIconLayer?
init(context: AccountContext) {
self.context = context
self.contentLayer = SimpleLayer()
self.contentLayer.contentsGravity = .resize
self.contentLayer.masksToBounds = true
self.overlayColorLayer = SimpleLayer()
self.overlayColorLayer.masksToBounds = true
self.iconLayer = SimpleLayer()
super.init(frame: CGRect())
self.layer.addSublayer(self.contentLayer)
self.layer.addSublayer(self.overlayColorLayer)
self.layer.addSublayer(self.iconLayer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(transition: ComponentTransition, badge: EmojiKeyboardItemLayer.Badge, backgroundColor: UIColor, size: CGSize) {
if self.badge != badge {
self.badge = badge
switch badge {
case .premium:
self.iconLayer.contents = premiumBadgeIcon?.cgImage
case .featured:
self.iconLayer.contents = featuredBadgeIcon?.cgImage
case .locked:
self.iconLayer.contents = lockedBadgeIcon?.cgImage
case let .text(text):
let string = NSAttributedString(string: text, font: itemBadgeTextFont)
let size = CGSize(width: 12.0, height: 12.0)
let stringBounds = string.boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil)
let image = generateImage(size, rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
UIGraphicsPushContext(context)
string.draw(at: CGPoint(x: floor((size.width - stringBounds.width) * 0.5), y: floor((size.height - stringBounds.height) * 0.5)))
UIGraphicsPopContext()
})
self.iconLayer.contents = image?.cgImage
case .customFile:
self.iconLayer.contents = nil
}
if case let .customFile(customFile) = badge {
let customFileLayer: InlineFileIconLayer
if let current = self.customFileLayer {
customFileLayer = current
} else {
customFileLayer = InlineFileIconLayer(
context: self.context,
userLocation: .other,
attemptSynchronousLoad: false,
file: customFile._parse(),
cache: self.context.animationCache,
renderer: self.context.animationRenderer,
unique: false,
placeholderColor: .clear,
pointSize: CGSize(width: 18.0, height: 18.0),
dynamicColor: nil
)
self.customFileLayer = customFileLayer
self.layer.addSublayer(customFileLayer)
}
let _ = customFileLayer
} else {
if let customFileLayer = self.customFileLayer {
self.customFileLayer = nil
customFileLayer.removeFromSuperlayer()
}
}
}
let iconInset: CGFloat
switch badge {
case .premium:
iconInset = 2.0
case .featured:
iconInset = 0.0
case .locked:
iconInset = 0.0
case .text, .customFile:
iconInset = 0.0
}
switch badge {
case .text, .customFile:
self.contentLayer.isHidden = true
self.overlayColorLayer.isHidden = true
default:
self.contentLayer.isHidden = false
self.overlayColorLayer.isHidden = false
}
self.overlayColorLayer.backgroundColor = backgroundColor.cgColor
transition.setFrame(layer: self.contentLayer, frame: CGRect(origin: CGPoint(), size: size))
transition.setCornerRadius(layer: self.contentLayer, cornerRadius: min(size.width / 2.0, size.height / 2.0))
transition.setFrame(layer: self.overlayColorLayer, frame: CGRect(origin: CGPoint(), size: size))
transition.setCornerRadius(layer: self.overlayColorLayer, cornerRadius: min(size.width / 2.0, size.height / 2.0))
transition.setFrame(layer: self.iconLayer, frame: CGRect(origin: CGPoint(), size: size).insetBy(dx: iconInset, dy: iconInset))
if let customFileLayer = self.customFileLayer {
let iconSize = CGSize(width: 18.0, height: 18.0)
transition.setFrame(layer: customFileLayer, frame: CGRect(origin: CGPoint(), size: iconSize))
}
}
}