mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Update encryption key animations
This commit is contained in:
parent
51a657c41c
commit
81ae40bcde
@ -7,6 +7,96 @@ import BalancedTextComponent
|
|||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
import CallsEmoji
|
import CallsEmoji
|
||||||
|
|
||||||
|
private final class EmojiContainerView: UIView {
|
||||||
|
private let maskImageView: UIImageView?
|
||||||
|
let contentView: UIView
|
||||||
|
|
||||||
|
var isMaskEnabled: Bool = false {
|
||||||
|
didSet {
|
||||||
|
if self.isMaskEnabled != oldValue {
|
||||||
|
if self.isMaskEnabled {
|
||||||
|
self.mask = self.maskImageView
|
||||||
|
} else {
|
||||||
|
self.mask = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(hasMask: Bool) {
|
||||||
|
if hasMask {
|
||||||
|
self.maskImageView = UIImageView()
|
||||||
|
} else {
|
||||||
|
self.maskImageView = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.contentView = UIView()
|
||||||
|
self.contentView.layer.anchorPoint = CGPoint(x: 0.0, y: 0.0)
|
||||||
|
self.contentView.center = CGPoint(x: 0.0, y: 0.0)
|
||||||
|
|
||||||
|
super.init(frame: CGRect())
|
||||||
|
|
||||||
|
if let maskImageView = self.maskImageView {
|
||||||
|
self.mask = maskImageView
|
||||||
|
}
|
||||||
|
self.addSubview(self.contentView)
|
||||||
|
self.clipsToBounds = hasMask
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(size: CGSize, borderWidth: CGFloat) {
|
||||||
|
let minimalHeight = borderWidth * 2.0 + 1.0
|
||||||
|
let minimalSize = CGSize(width: 4.0, height: minimalHeight)
|
||||||
|
|
||||||
|
if let maskImageView = self.maskImageView, maskImageView.image?.size != minimalSize {
|
||||||
|
let generatedImage = generateImage(minimalSize, rotatedContext: { imageSize, context in
|
||||||
|
context.clear(CGRect(origin: CGPoint(), size: imageSize))
|
||||||
|
|
||||||
|
let height: CGFloat = borderWidth
|
||||||
|
let baseGradientAlpha: CGFloat = 1.0
|
||||||
|
let numSteps = 8
|
||||||
|
let firstStep = 0
|
||||||
|
let firstLocation = 0.0
|
||||||
|
let colors = (0 ..< numSteps).map { i -> UIColor in
|
||||||
|
if i < firstStep {
|
||||||
|
return UIColor(white: 1.0, alpha: 1.0)
|
||||||
|
} else {
|
||||||
|
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
|
||||||
|
let value: CGFloat = bezierPoint(0.42, 0.0, 0.58, 1.0, step)
|
||||||
|
return UIColor(white: 1.0, alpha: baseGradientAlpha * value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var locations = (0 ..< numSteps).map { i -> CGFloat in
|
||||||
|
if i < firstStep {
|
||||||
|
return 0.0
|
||||||
|
} else {
|
||||||
|
let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1)
|
||||||
|
return (firstLocation + (1.0 - firstLocation) * step)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let gradient = CGGradient(colorsSpace: DeviceGraphicsContextSettings.shared.colorSpace, colors: colors.map { $0.cgColor } as CFArray, locations: &locations)!
|
||||||
|
|
||||||
|
context.setFillColor(UIColor.white.cgColor)
|
||||||
|
context.fill(CGRect(origin: CGPoint(x: 0.0, y: height), size: CGSize(width: imageSize.width, height: 1.0)))
|
||||||
|
|
||||||
|
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: height), options: CGGradientDrawingOptions())
|
||||||
|
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: imageSize.height), end: CGPoint(x: 0.0, y: imageSize.height - height), options: CGGradientDrawingOptions())
|
||||||
|
})
|
||||||
|
|
||||||
|
let capInsets = UIEdgeInsets(top: borderWidth, left: 0, bottom: borderWidth, right: 0)
|
||||||
|
maskImageView.image = generatedImage?.resizableImage(withCapInsets: capInsets, resizingMode: .stretch)
|
||||||
|
}
|
||||||
|
if let maskImageView = self.maskImageView {
|
||||||
|
maskImageView.frame = CGRect(origin: CGPoint(), size: size)
|
||||||
|
}
|
||||||
|
self.contentView.bounds = CGRect(origin: CGPoint(), size: size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final class EmojiItemComponent: Component {
|
private final class EmojiItemComponent: Component {
|
||||||
let emoji: String?
|
let emoji: String?
|
||||||
|
|
||||||
@ -22,8 +112,9 @@ private final class EmojiItemComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class View: UIView {
|
final class View: UIView {
|
||||||
|
private let containerView: EmojiContainerView
|
||||||
private let measureEmojiView = ComponentView<Empty>()
|
private let measureEmojiView = ComponentView<Empty>()
|
||||||
private var pendingContainerView: UIView?
|
private var pendingContainerView: EmojiContainerView?
|
||||||
private var pendingEmojiViews: [ComponentView<Empty>] = []
|
private var pendingEmojiViews: [ComponentView<Empty>] = []
|
||||||
private var emojiView: ComponentView<Empty>?
|
private var emojiView: ComponentView<Empty>?
|
||||||
|
|
||||||
@ -33,7 +124,11 @@ private final class EmojiItemComponent: Component {
|
|||||||
private var pendingEmojiValues: [String]?
|
private var pendingEmojiValues: [String]?
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
|
self.containerView = EmojiContainerView(hasMask: true)
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
self.addSubview(self.containerView)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
@ -44,6 +139,8 @@ private final class EmojiItemComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func update(component: EmojiItemComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
func update(component: EmojiItemComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||||
|
let pendingContainerInset: CGFloat = 6.0
|
||||||
|
|
||||||
self.component = component
|
self.component = component
|
||||||
self.state = state
|
self.state = state
|
||||||
|
|
||||||
@ -55,10 +152,35 @@ private final class EmojiItemComponent: Component {
|
|||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: 200.0, height: 200.0)
|
containerSize: CGSize(width: 200.0, height: 200.0)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let containerFrame = CGRect(origin: CGPoint(x: -pendingContainerInset, y: -pendingContainerInset), size: CGSize(width: size.width + pendingContainerInset * 2.0, height: size.height + pendingContainerInset * 2.0))
|
||||||
|
self.containerView.frame = containerFrame
|
||||||
|
self.containerView.update(size: containerFrame.size, borderWidth: 12.0)
|
||||||
|
|
||||||
|
/*let maxBlur: CGFloat = 4.0
|
||||||
|
if component.emoji == nil, (self.containerView.contentView.layer.filters == nil || self.containerView.contentView.layer.filters?.count == 0) {
|
||||||
|
if let blurFilter = CALayer.blur() {
|
||||||
|
blurFilter.setValue(maxBlur as NSNumber, forKey: "inputRadius")
|
||||||
|
self.containerView.contentView.layer.filters = [blurFilter]
|
||||||
|
self.containerView.contentView.layer.animate(from: 0.0 as NSNumber, to: maxBlur as NSNumber, keyPath: "filters.gaussianBlur.inputRadius", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: 0.2, removeOnCompletion: true)
|
||||||
|
}
|
||||||
|
} else if self.containerView.contentView.layer.filters != nil && self.containerView.contentView.layer.filters?.count != 0 {
|
||||||
|
if let blurFilter = CALayer.blur() {
|
||||||
|
blurFilter.setValue(0.0 as NSNumber, forKey: "inputRadius")
|
||||||
|
self.containerView.contentView.layer.filters = [blurFilter]
|
||||||
|
self.containerView.contentView.layer.animate(from: maxBlur as NSNumber, to: 0.0 as NSNumber, keyPath: "filters.gaussianBlur.inputRadius", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: 0.2, removeOnCompletion: false, completion: { [weak self] flag in
|
||||||
|
if flag, let self {
|
||||||
|
self.containerView.contentView.layer.filters = nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
let borderEmoji = 2
|
let borderEmoji = 2
|
||||||
let numEmoji = borderEmoji * 2 + 3
|
let numEmoji = borderEmoji * 2 + 3
|
||||||
|
|
||||||
|
var previousEmojiView: ComponentView<Empty>?
|
||||||
|
|
||||||
if let emoji = component.emoji {
|
if let emoji = component.emoji {
|
||||||
let emojiView: ComponentView<Empty>
|
let emojiView: ComponentView<Empty>
|
||||||
var emojiViewTransition = transition
|
var emojiViewTransition = transition
|
||||||
@ -77,19 +199,41 @@ private final class EmojiItemComponent: Component {
|
|||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: 200.0, height: 200.0)
|
containerSize: CGSize(width: 200.0, height: 200.0)
|
||||||
)
|
)
|
||||||
let emojiFrame = CGRect(origin: CGPoint(x: floor((size.width - emojiSize.width) * 0.5), y: floor((size.height - emojiSize.height) * 0.5)), size: emojiSize)
|
let emojiFrame = CGRect(origin: CGPoint(x: pendingContainerInset + floor((size.width - emojiSize.width) * 0.5), y: pendingContainerInset + floor((size.height - emojiSize.height) * 0.5)), size: emojiSize)
|
||||||
if let emojiComponentView = emojiView.view {
|
if let emojiComponentView = emojiView.view {
|
||||||
if emojiComponentView.superview == nil {
|
if emojiComponentView.superview == nil {
|
||||||
self.addSubview(emojiComponentView)
|
self.containerView.contentView.addSubview(emojiComponentView)
|
||||||
}
|
}
|
||||||
emojiViewTransition.setFrame(view: emojiComponentView, frame: emojiFrame)
|
emojiViewTransition.setFrame(view: emojiComponentView, frame: emojiFrame)
|
||||||
|
|
||||||
|
if let pendingContainerView = self.pendingContainerView {
|
||||||
|
self.pendingContainerView = nil
|
||||||
|
self.pendingEmojiViews.removeAll()
|
||||||
|
|
||||||
|
let currentPendingContainerOffset = pendingContainerView.contentView.layer.presentation()?.position.y ?? pendingContainerView.contentView.layer.position.y
|
||||||
|
|
||||||
|
pendingContainerView.contentView.layer.removeAnimation(forKey: "offsetCycle")
|
||||||
|
pendingContainerView.contentView.layer.position.y = currentPendingContainerOffset
|
||||||
|
|
||||||
|
let animateTransition: ComponentTransition = .spring(duration: 0.4)
|
||||||
|
let targetOffset: CGFloat = CGFloat(borderEmoji - 1) * size.height
|
||||||
|
animateTransition.setPosition(layer: pendingContainerView.contentView.layer, position: CGPoint(x: 0.0, y: targetOffset), completion: { [weak self, weak pendingContainerView] _ in
|
||||||
|
pendingContainerView?.removeFromSuperview()
|
||||||
|
|
||||||
|
self?.containerView.isMaskEnabled = false
|
||||||
|
})
|
||||||
|
|
||||||
|
animateTransition.animatePosition(view: emojiComponentView, from: CGPoint(x: 0.0, y: currentPendingContainerOffset - targetOffset), to: CGPoint(), additive: true)
|
||||||
|
} else {
|
||||||
|
self.containerView.isMaskEnabled = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pendingEmojiValues = nil
|
self.pendingEmojiValues = nil
|
||||||
} else {
|
} else {
|
||||||
if let emojiView = self.emojiView {
|
if let emojiView = self.emojiView {
|
||||||
self.emojiView = nil
|
self.emojiView = nil
|
||||||
emojiView.view?.removeFromSuperview()
|
previousEmojiView = emojiView
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.pendingEmojiValues?.count != numEmoji {
|
if self.pendingEmojiValues?.count != numEmoji {
|
||||||
@ -105,11 +249,13 @@ private final class EmojiItemComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let pendingEmojiValues, pendingEmojiValues.count == numEmoji {
|
if let pendingEmojiValues, pendingEmojiValues.count == numEmoji {
|
||||||
let pendingContainerView: UIView
|
self.containerView.isMaskEnabled = true
|
||||||
|
|
||||||
|
let pendingContainerView: EmojiContainerView
|
||||||
if let current = self.pendingContainerView {
|
if let current = self.pendingContainerView {
|
||||||
pendingContainerView = current
|
pendingContainerView = current
|
||||||
} else {
|
} else {
|
||||||
pendingContainerView = UIView()
|
pendingContainerView = EmojiContainerView(hasMask: false)
|
||||||
self.pendingContainerView = pendingContainerView
|
self.pendingContainerView = pendingContainerView
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,27 +277,70 @@ private final class EmojiItemComponent: Component {
|
|||||||
)
|
)
|
||||||
if let pendingEmojiComponentView = pendingEmojiView.view {
|
if let pendingEmojiComponentView = pendingEmojiView.view {
|
||||||
if pendingEmojiComponentView.superview == nil {
|
if pendingEmojiComponentView.superview == nil {
|
||||||
pendingContainerView.addSubview(pendingEmojiComponentView)
|
pendingContainerView.contentView.addSubview(pendingEmojiComponentView)
|
||||||
}
|
}
|
||||||
pendingEmojiComponentView.frame = CGRect(origin: CGPoint(x: 0.0, y: CGFloat(i) * size.height), size: pendingEmojiViewSize)
|
pendingEmojiComponentView.frame = CGRect(origin: CGPoint(x: pendingContainerInset, y: pendingContainerInset + CGFloat(i) * size.height), size: pendingEmojiViewSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingContainerView.frame = CGRect(origin: CGPoint(), size: size)
|
pendingContainerView.frame = CGRect(origin: CGPoint(), size: containerFrame.size)
|
||||||
|
pendingContainerView.update(size: containerFrame.size, borderWidth: 12.0)
|
||||||
|
|
||||||
if pendingContainerView.superview == nil {
|
if pendingContainerView.superview == nil {
|
||||||
self.addSubview(pendingContainerView)
|
self.containerView.contentView.addSubview(pendingContainerView)
|
||||||
|
|
||||||
let animation = CABasicAnimation(keyPath: "sublayerTransform.translation.y")
|
let startTime = CACurrentMediaTime()
|
||||||
//animation.duration = 4.2
|
|
||||||
|
var loopAnimationOffset: Double = 0.0
|
||||||
|
if let previousEmojiComponentView = previousEmojiView?.view {
|
||||||
|
previousEmojiView = nil
|
||||||
|
|
||||||
|
pendingContainerView.contentView.addSubview(previousEmojiComponentView)
|
||||||
|
previousEmojiComponentView.center = previousEmojiComponentView.center.offsetBy(dx: 0.0, dy: CGFloat(numEmoji) * size.height)
|
||||||
|
|
||||||
|
let animation = CABasicAnimation(keyPath: "position.y")
|
||||||
|
loopAnimationOffset = 0.25
|
||||||
|
animation.duration = loopAnimationOffset
|
||||||
|
animation.fromValue = -CGFloat(numEmoji) * size.height
|
||||||
|
animation.toValue = 0.0
|
||||||
|
animation.timingFunction = CAMediaTimingFunction(name: .easeIn)
|
||||||
|
animation.autoreverses = false
|
||||||
|
animation.repeatCount = 1.0
|
||||||
|
animation.fillMode = .backwards
|
||||||
|
animation.isRemovedOnCompletion = true
|
||||||
|
animation.beginTime = pendingContainerView.contentView.layer.convertTime(startTime, from: nil)
|
||||||
|
animation.isAdditive = true
|
||||||
|
|
||||||
|
animation.completion = { [weak previousEmojiComponentView] _ in
|
||||||
|
previousEmojiComponentView?.removeFromSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingContainerView.contentView.layer.add(animation, forKey: "offsetCyclePre")
|
||||||
|
}
|
||||||
|
|
||||||
|
let animation = CABasicAnimation(keyPath: "position.y")
|
||||||
animation.duration = 0.2
|
animation.duration = 0.2
|
||||||
animation.fromValue = -CGFloat(numEmoji - borderEmoji) * size.height
|
animation.fromValue = -CGFloat(numEmoji - borderEmoji) * size.height
|
||||||
animation.toValue = CGFloat(borderEmoji - 3) * size.height
|
animation.toValue = CGFloat(borderEmoji - 3) * size.height
|
||||||
animation.timingFunction = CAMediaTimingFunction(name: .linear)
|
animation.timingFunction = CAMediaTimingFunction(name: .linear)
|
||||||
animation.autoreverses = false
|
animation.autoreverses = false
|
||||||
animation.repeatCount = .infinity
|
animation.repeatCount = .infinity
|
||||||
|
animation.fillMode = .forwards
|
||||||
|
|
||||||
|
animation.beginTime = pendingContainerView.contentView.layer.convertTime(startTime + loopAnimationOffset, from: nil)
|
||||||
|
|
||||||
pendingContainerView.layer.add(animation, forKey: "offsetCycle")
|
pendingContainerView.contentView.layer.add(animation, forKey: "offsetCycle")
|
||||||
|
} else if pendingContainerView.contentView.layer.animation(forKey: "offsetCycle") == nil {
|
||||||
|
let animation = CABasicAnimation(keyPath: "position.y")
|
||||||
|
animation.duration = 0.2
|
||||||
|
animation.fromValue = -CGFloat(numEmoji - borderEmoji) * size.height
|
||||||
|
animation.toValue = CGFloat(borderEmoji - 3) * size.height
|
||||||
|
animation.timingFunction = CAMediaTimingFunction(name: .linear)
|
||||||
|
animation.autoreverses = false
|
||||||
|
animation.repeatCount = .infinity
|
||||||
|
animation.fillMode = .forwards
|
||||||
|
|
||||||
|
pendingContainerView.contentView.layer.add(animation, forKey: "offsetCycle")
|
||||||
}
|
}
|
||||||
} else if let pendingContainerView = self.pendingContainerView {
|
} else if let pendingContainerView = self.pendingContainerView {
|
||||||
self.pendingContainerView = nil
|
self.pendingContainerView = nil
|
||||||
@ -162,9 +351,10 @@ private final class EmojiItemComponent: Component {
|
|||||||
}
|
}
|
||||||
self.pendingEmojiViews.removeAll()
|
self.pendingEmojiViews.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
//self.layer.borderColor = UIColor.red.cgColor
|
if let previousEmojiView {
|
||||||
//self.layer.borderWidth = 4.0
|
previousEmojiView.view?.removeFromSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
@ -227,9 +417,15 @@ final class VideoChatEncryptionKeyComponent: Component {
|
|||||||
private let expandedButtonText = ComponentView<Empty>()
|
private let expandedButtonText = ComponentView<Empty>()
|
||||||
|
|
||||||
private var component: VideoChatEncryptionKeyComponent?
|
private var component: VideoChatEncryptionKeyComponent?
|
||||||
|
private weak var state: EmptyComponentState?
|
||||||
private var isUpdating: Bool = false
|
private var isUpdating: Bool = false
|
||||||
|
|
||||||
private var tapRecognizer: TapLongTapOrDoubleTapGestureRecognizer?
|
private var tapRecognizer: TapLongTapOrDoubleTapGestureRecognizer?
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
private var mockStateTimer: Foundation.Timer?
|
||||||
|
private var mockCurrentKey: [String]?
|
||||||
|
#endif
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
self.containerView = UIView()
|
self.containerView = UIView()
|
||||||
@ -246,6 +442,10 @@ final class VideoChatEncryptionKeyComponent: Component {
|
|||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.mockStateTimer?.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
@objc private func tapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
@objc private func tapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
||||||
guard let component = self.component else {
|
guard let component = self.component else {
|
||||||
@ -269,8 +469,32 @@ final class VideoChatEncryptionKeyComponent: Component {
|
|||||||
defer {
|
defer {
|
||||||
self.isUpdating = false
|
self.isUpdating = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG && false
|
||||||
|
if self.component == nil {
|
||||||
|
self.mockStateTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 4.0, repeats: true, block: { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.mockCurrentKey == nil {
|
||||||
|
self.mockCurrentKey = (0 ..< 4).map { _ in randomCallsEmoji() ?? "👍" }
|
||||||
|
} else {
|
||||||
|
self.mockCurrentKey = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.isUpdating {
|
||||||
|
self.state?.updated(transition: .spring(duration: 0.4), isLocal: true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let emoji = self.mockCurrentKey ?? []
|
||||||
|
#else
|
||||||
|
let emoji = component.emoji
|
||||||
|
#endif
|
||||||
|
|
||||||
self.component = component
|
self.component = component
|
||||||
|
self.state = state
|
||||||
|
|
||||||
let alphaTransition: ComponentTransition
|
let alphaTransition: ComponentTransition
|
||||||
if transition.animation.isImmediate {
|
if transition.animation.isImmediate {
|
||||||
@ -303,7 +527,7 @@ final class VideoChatEncryptionKeyComponent: Component {
|
|||||||
return emojiItem.update(
|
return emojiItem.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(EmojiItemComponent(
|
component: AnyComponent(EmojiItemComponent(
|
||||||
emoji: i < component.emoji.count ? component.emoji[i] : nil
|
emoji: i < emoji.count ? emoji[i] : nil
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: 200.0, height: 200.0)
|
containerSize: CGSize(width: 200.0, height: 200.0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user