From ccffdb6bac4c5827f8b36c0275f1912e44761ec0 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 22 Dec 2021 23:47:25 +0400 Subject: [PATCH] Reaction improvements --- .../ContainedViewLayoutTransition.swift | 6 +- .../Sources/ReactionContextNode.swift | 134 +++++++++------- .../Sources/ReactionSelectionNode.swift | 146 +++++++++++++----- 3 files changed, 186 insertions(+), 100 deletions(-) diff --git a/submodules/Display/Source/ContainedViewLayoutTransition.swift b/submodules/Display/Source/ContainedViewLayoutTransition.swift index 74eec36301..07668fb552 100644 --- a/submodules/Display/Source/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Source/ContainedViewLayoutTransition.swift @@ -393,16 +393,16 @@ public extension ContainedViewLayoutTransition { } } - func animatePositionWithKeyframes(node: ASDisplayNode, keyframes: [AnyObject], removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { + func animatePositionWithKeyframes(node: ASDisplayNode, keyframes: [CGPoint], removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { self.animatePositionWithKeyframes(layer: node.layer, keyframes: keyframes, removeOnCompletion: removeOnCompletion, additive: additive, completion: completion) } - func animatePositionWithKeyframes(layer: CALayer, keyframes: [AnyObject], removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { + func animatePositionWithKeyframes(layer: CALayer, keyframes: [CGPoint], removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { switch self { case .immediate: completion?(true) case let .animated(duration, curve): - layer.animateKeyframes(values: keyframes, duration: duration, keyPath: "position", timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, removeOnCompletion: removeOnCompletion, completion: { value in + layer.animateKeyframes(values: keyframes.map(NSValue.init(cgPoint:)), duration: duration, keyPath: "position", timingFunction: curve.timingFunction, mediaTimingFunction: curve.mediaTimingFunction, removeOnCompletion: removeOnCompletion, completion: { value in completion?(value) }) } diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index c4c59b1476..afdf304fe0 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -41,6 +41,7 @@ private let largeCircleSize: CGFloat = 16.0 private let smallCircleSize: CGFloat = 8.0 public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { + private let context: AccountContext private let theme: PresentationTheme private let items: [ReactionContextItem] @@ -49,7 +50,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { private let contentContainer: ASDisplayNode private let contentContainerMask: UIImageView private let scrollNode: ASScrollNode - private var itemNodes: [ReactionNode] = [] + private var visibleItemNodes: [Int: ReactionNode] = [:] private var isExpanded: Bool = true private var highlightedReaction: ReactionContextItem.Reaction? @@ -64,7 +65,10 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { private weak var animationTargetView: UIView? private var animationHideNode: Bool = false + private var didAnimateIn: Bool = false + public init(context: AccountContext, theme: PresentationTheme, items: [ReactionContextItem]) { + self.context = context self.theme = theme self.items = items @@ -116,11 +120,6 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { self.scrollNode.view.delegate = self - self.itemNodes = self.items.map { item in - return ReactionNode(context: context, theme: theme, item: item) - } - self.itemNodes.forEach(self.scrollNode.addSubnode) - self.addSubnode(self.contentContainer) } @@ -180,30 +179,61 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { } private func updateScrolling(transition: ContainedViewLayoutTransition) { - let sideInset: CGFloat = 14.0 - let minScale: CGFloat = 0.6 - let scaleDistance: CGFloat = 30.0 + let sideInset: CGFloat = 11.0 + let itemSpacing: CGFloat = 9.0 + let itemSize: CGFloat = 40.0 + let verticalInset: CGFloat = 13.0 + let rowHeight: CGFloat = 30.0 + let visibleBounds = self.scrollNode.view.bounds - for itemNode in self.itemNodes { - if itemNode.isExtracted { - continue - } - let itemScale: CGFloat - let itemFrame = itemNode.frame.offsetBy(dx: -visibleBounds.minX, dy: 0.0) - if itemFrame.minX < sideInset || itemFrame.maxX > visibleBounds.width - sideInset { - let edgeDistance: CGFloat - if itemFrame.minX < sideInset { - edgeDistance = sideInset - itemFrame.minX + var validIndices = Set() + for i in 0 ..< self.items.count { + let columnIndex = i + let column = CGFloat(columnIndex) + + let itemOffsetY: CGFloat = -1.0 + + let itemFrame = CGRect(origin: CGPoint(x: sideInset + column * (itemSize + itemSpacing), y: verticalInset + floor((rowHeight - itemSize) / 2.0) + itemOffsetY), size: CGSize(width: itemSize, height: itemSize)) + /*if self.highlightedReaction == self.items[i].reaction { + itemFrame = itemFrame.insetBy(dx: -6.0, dy: -6.0) + }*/ + if visibleBounds.intersects(itemFrame) { + validIndices.insert(i) + + var animateIn = false + + let itemNode: ReactionNode + if let current = self.visibleItemNodes[i] { + itemNode = current } else { - edgeDistance = itemFrame.maxX - (visibleBounds.width - sideInset) + animateIn = self.didAnimateIn + + itemNode = ReactionNode(context: self.context, theme: self.theme, item: self.items[i]) + self.visibleItemNodes[i] = itemNode + self.scrollNode.addSubnode(itemNode) + } + + if !itemNode.isExtracted { + transition.updateFrame(node: itemNode, frame: itemFrame, beginWithCurrentState: true) + itemNode.updateLayout(size: itemFrame.size, isExpanded: false, transition: transition) + + if animateIn { + itemNode.animateIn() + } } - let edgeFactor: CGFloat = min(1.0, edgeDistance / scaleDistance) - itemScale = edgeFactor * minScale + (1.0 - edgeFactor) * 1.0 - } else { - itemScale = 1.0 } - transition.updateSublayerTransformScale(node: itemNode, scale: itemScale) + } + + var removedIndices: [Int] = [] + for (index, itemNode) in self.visibleItemNodes { + if !validIndices.contains(index) { + removedIndices.append(index) + itemNode.removeFromSupernode() + } + } + for index in removedIndices { + self.visibleItemNodes.removeValue(forKey: index) } } @@ -237,22 +267,6 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size)) self.scrollNode.view.contentSize = CGSize(width: completeContentWidth, height: backgroundFrame.size.height) - for i in 0 ..< self.items.count { - let columnIndex = i - let column = CGFloat(columnIndex) - - let itemOffsetY: CGFloat = -1.0 - - var itemFrame = CGRect(origin: CGPoint(x: sideInset + column * (itemSize + itemSpacing), y: verticalInset + floor((rowHeight - itemSize) / 2.0) + itemOffsetY), size: CGSize(width: itemSize, height: itemSize)) - if self.highlightedReaction == self.items[i].reaction { - itemFrame = itemFrame.insetBy(dx: -6.0, dy: -6.0) - } - if !self.itemNodes[i].isExtracted { - transition.updateFrame(node: self.itemNodes[i], frame: itemFrame, beginWithCurrentState: true) - self.itemNodes[i].updateLayout(size: itemFrame.size, isExpanded: false, transition: transition) - } - } - self.updateScrolling(transition: transition) transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame) @@ -291,23 +305,28 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, transition: .immediate, animateInFromAnchorRect: sourceAnchorRect, animateOutToAnchorRect: nil) } - let mainCircleDuration: Double = 0.5 + //let mainCircleDuration: Double = 0.5 let mainCircleDelay: Double = 0.1 self.backgroundNode.animateIn() - for i in 0 ..< self.itemNodes.count { - let itemNode = self.itemNodes[i] + self.didAnimateIn = true + + for i in 0 ..< self.items.count { + guard let itemNode = self.visibleItemNodes[i] else { + continue + } let itemDelay = mainCircleDelay + 0.1 + Double(i) * 0.03 - itemNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: itemDelay) - itemNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: mainCircleDuration, delay: itemDelay, initialVelocity: 0.0) + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + itemDelay, execute: { [weak itemNode] in + itemNode?.animateIn() + }) } } public func animateOut(to targetAnchorRect: CGRect?, animatingOutToReaction: Bool) { self.backgroundNode.animateOut() - for itemNode in self.itemNodes { + for (_, itemNode) in self.visibleItemNodes { if itemNode.isExtracted { continue } @@ -367,7 +386,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { } public func willAnimateOutToReaction(value: String) { - for itemNode in self.itemNodes { + for (_, itemNode) in self.visibleItemNodes { if itemNode.item.reaction.rawValue != value { continue } @@ -376,7 +395,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { } public func animateOutToReaction(value: String, targetView: UIView, hideNode: Bool, completion: @escaping () -> Void) { - for itemNode in self.itemNodes { + for (_, itemNode) in self.visibleItemNodes { if itemNode.item.reaction.rawValue != value { continue } @@ -400,7 +419,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { let selfSourceRect = itemNode.view.convert(itemNode.view.bounds, to: self.view) let selfTargetRect = self.view.convert(targetView.bounds, from: targetView) - let expandedScale: CGFloat = 3.0 + let expandedScale: CGFloat = 4.0 let expandedSize = CGSize(width: floor(selfSourceRect.width * expandedScale), height: floor(selfSourceRect.height * expandedScale)) var expandedFrame = CGRect(origin: CGPoint(x: floor(selfTargetRect.midX - expandedSize.width / 2.0), y: floor(selfTargetRect.midY - expandedSize.height / 2.0)), size: expandedSize) @@ -411,10 +430,11 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .linear) self.addSubnode(itemNode) - itemNode.frame = selfSourceRect + //itemNode.position = selfSourceRect.center itemNode.position = expandedFrame.center transition.updateBounds(node: itemNode, bounds: CGRect(origin: CGPoint(), size: expandedFrame.size)) itemNode.updateLayout(size: expandedFrame.size, isExpanded: true, transition: transition) + transition.animatePositionWithKeyframes(node: itemNode, keyframes: generateParabollicMotionKeyframes(from: selfSourceRect.center, to: expandedFrame.center, elevation: 30.0)) let additionalAnimationNode = AnimatedStickerNode() @@ -507,7 +527,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { public func reaction(at point: CGPoint) -> ReactionContextItem? { for i in 0 ..< 2 { let touchInset: CGFloat = i == 0 ? 0.0 : 8.0 - for itemNode in self.itemNodes { + for (_, itemNode) in self.visibleItemNodes { let itemPoint = self.view.convert(point, to: itemNode.view) if itemNode.bounds.insetBy(dx: -touchInset, dy: -touchInset).contains(itemPoint) { return itemNode.item @@ -518,7 +538,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { } public func performReactionSelection(reaction: ReactionContextItem.Reaction) { - for itemNode in self.itemNodes { + for (_, itemNode) in self.visibleItemNodes { if itemNode.item.reaction == reaction { self.reactionSelected?(itemNode.item) break @@ -782,7 +802,7 @@ public final class StandaloneDismissReactionAnimation: ASDisplayNode { } } -private func generateParabollicMotionKeyframes(from sourcePoint: CGPoint, to targetPosition: CGPoint, elevation: CGFloat) -> [AnyObject] { +private func generateParabollicMotionKeyframes(from sourcePoint: CGPoint, to targetPosition: CGPoint, elevation: CGFloat) -> [CGPoint] { let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0, y: sourcePoint.y - elevation) let x1 = sourcePoint.x @@ -792,13 +812,13 @@ private func generateParabollicMotionKeyframes(from sourcePoint: CGPoint, to tar let x3 = targetPosition.x let y3 = targetPosition.y - var keyframes: [AnyObject] = [] + var keyframes: [CGPoint] = [] if abs(y1 - y3) < 5.0 && abs(x1 - x3) < 5.0 { for i in 0 ..< 10 { let k = CGFloat(i) / CGFloat(10 - 1) let x = sourcePoint.x * (1.0 - k) + targetPosition.x * k let y = sourcePoint.y * (1.0 - k) + targetPosition.y * k - keyframes.append(NSValue(cgPoint: CGPoint(x: x, y: y))) + keyframes.append(CGPoint(x: x, y: y)) } } else { let a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) @@ -809,7 +829,7 @@ private func generateParabollicMotionKeyframes(from sourcePoint: CGPoint, to tar let k = CGFloat(i) / CGFloat(10 - 1) let x = sourcePoint.x * (1.0 - k) + targetPosition.x * k let y = a * x * x + b * x + c - keyframes.append(NSValue(cgPoint: CGPoint(x: x, y: y))) + keyframes.append(CGPoint(x: x, y: y)) } } diff --git a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift index f6c6f2a719..c184fb9f99 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift @@ -38,8 +38,10 @@ private let font = Font.medium(13.0) final class ReactionNode: ASDisplayNode { let context: AccountContext let item: ReactionContextItem - private let staticImageNode: TransformImageNode - private let stillAnimationNode: AnimatedStickerNode + + private var animateInAnimationNode: AnimatedStickerNode? + private let staticAnimationNode: AnimatedStickerNode + private var stillAnimationNode: AnimatedStickerNode? private var animationNode: AnimatedStickerNode? private var fetchStickerDisposable: Disposable? @@ -55,22 +57,40 @@ final class ReactionNode: ASDisplayNode { self.context = context self.item = item - self.staticImageNode = TransformImageNode() + self.staticAnimationNode = AnimatedStickerNode() + self.staticAnimationNode.isHidden = true + + self.animateInAnimationNode = AnimatedStickerNode() self.stillAnimationNode = AnimatedStickerNode() super.init() - self.addSubnode(self.staticImageNode) + if let animateInAnimationNode = self.animateInAnimationNode { + self.addSubnode(animateInAnimationNode) + } + self.addSubnode(self.staticAnimationNode) - self.addSubnode(self.stillAnimationNode) - - self.stillAnimationNode.started = { [weak self] in + self.animateInAnimationNode?.completed = { [weak self] _ in guard let strongSelf = self else { return } - strongSelf.staticImageNode.isHidden = true + if strongSelf.animationNode == nil { + strongSelf.staticAnimationNode.isHidden = false + } + + strongSelf.animateInAnimationNode?.removeFromSupernode() + strongSelf.animateInAnimationNode = nil } + /*self.stillAnimationNode.started = { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.animateInAnimationNode.isHidden = true + strongSelf.animateInAnimationNode.visibility = false + }*/ + + self.fetchStickerDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: .standalone(resource: item.appearAnimation.resource)).start() self.fetchStickerDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: .standalone(resource: item.stillAnimation.resource)).start() self.fetchStickerDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: .standalone(resource: item.listAnimation.resource)).start() self.fetchFullAnimationDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: .standalone(resource: item.applicationAnimation.resource)).start() @@ -81,6 +101,10 @@ final class ReactionNode: ASDisplayNode { self.fetchFullAnimationDisposable?.dispose() } + func animateIn() { + self.animateInAnimationNode?.visibility = true + } + func updateLayout(size: CGSize, isExpanded: Bool, transition: ContainedViewLayoutTransition) { let intrinsicSize = size @@ -101,60 +125,102 @@ final class ReactionNode: ASDisplayNode { self.animationNode = animationNode self.addSubnode(animationNode) - animationNode.started = { [weak self] in - guard let strongSelf = self else { - return - } - strongSelf.staticImageNode.isHidden = true - } - animationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.listAnimation.resource), width: Int(animationDisplaySize.width * 2.0), height: Int(animationDisplaySize.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.listAnimation.resource.id))) animationNode.frame = animationFrame animationNode.updateLayout(size: animationFrame.size) - if transition.isAnimated, !self.staticImageNode.frame.isEmpty { - transition.animateTransformScale(node: animationNode, from: self.staticImageNode.bounds.width / animationFrame.width) - transition.animatePositionAdditive(node: animationNode, offset: CGPoint(x: self.staticImageNode.frame.midX - animationFrame.midX, y: self.staticImageNode.frame.midY - animationFrame.midY)) - } - animationNode.visibility = true - self.stillAnimationNode.alpha = 0.0 if transition.isAnimated { - self.stillAnimationNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak self] _ in - self?.stillAnimationNode.visibility = false - }) + if let stillAnimationNode = self.stillAnimationNode, !stillAnimationNode.frame.isEmpty { + stillAnimationNode.alpha = 0.0 + stillAnimationNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak self] _ in + guard let strongSelf = self, let stillAnimationNode = strongSelf.stillAnimationNode else { + return + } + strongSelf.stillAnimationNode = nil + stillAnimationNode.removeFromSupernode() + }) + } + if let animateInAnimationNode = self.animateInAnimationNode { + animateInAnimationNode.alpha = 0.0 + animateInAnimationNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak self] _ in + guard let strongSelf = self, let animateInAnimationNode = strongSelf.animateInAnimationNode else { + return + } + strongSelf.animateInAnimationNode = nil + animateInAnimationNode.removeFromSupernode() + }) + } + + var referenceNode: ASDisplayNode? + if let animateInAnimationNode = self.animateInAnimationNode { + referenceNode = animateInAnimationNode + } else if !self.staticAnimationNode.isHidden { + referenceNode = self.staticAnimationNode + } + + if let referenceNode = referenceNode { + transition.animateTransformScale(node: animationNode, from: referenceNode.bounds.width / animationFrame.width) + transition.animatePositionAdditive(node: animationNode, offset: CGPoint(x: referenceNode.frame.midX - animationFrame.midX, y: referenceNode.frame.midY - animationFrame.midY)) + } + + if !self.staticAnimationNode.isHidden { + transition.animateTransformScale(node: self.staticAnimationNode, from: self.staticAnimationNode.bounds.width / animationFrame.width) + transition.animatePositionAdditive(node: self.staticAnimationNode, offset: CGPoint(x: self.staticAnimationNode.frame.midX - animationFrame.midX, y: self.staticAnimationNode.frame.midY - animationFrame.midY)) + + self.staticAnimationNode.alpha = 0.0 + self.staticAnimationNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2) + } + animationNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) } else { - self.stillAnimationNode.visibility = false + if let stillAnimationNode = self.stillAnimationNode { + self.stillAnimationNode = nil + stillAnimationNode.removeFromSupernode() + } + self.staticAnimationNode.isHidden = true } + animationNode.visibility = true } if self.validSize != size { self.validSize = size - - if !self.staticImageNode.isHidden { - self.staticImageNode.setSignal(chatMessageAnimatedSticker(postbox: self.context.account.postbox, file: item.stillAnimation, small: false, size: CGSize(width: animationDisplaySize.width * UIScreenScale, height: animationDisplaySize.height * UIScreenScale), fitzModifier: nil, fetched: false, onlyFullSize: false, thumbnail: false, synchronousLoad: false)) - let imageApply = self.staticImageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: animationDisplaySize, boundingSize: animationDisplaySize, intrinsicInsets: UIEdgeInsets())) - imageApply() - } - transition.updateFrame(node: self.staticImageNode, frame: animationFrame) } if !self.didSetupStillAnimation { if self.animationNode == nil { self.didSetupStillAnimation = true - self.stillAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation.resource), width: Int(animationDisplaySize.width * 2.5), height: Int(animationDisplaySize.height * 2.5), playbackMode: .loop, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation.resource.id))) + self.staticAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation.resource), width: Int(animationDisplaySize.width * 2.5), height: Int(animationDisplaySize.height * 2.5), playbackMode: .still(.start), mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation.resource.id))) + self.staticAnimationNode.position = animationFrame.center + self.staticAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size) + self.staticAnimationNode.updateLayout(size: animationFrame.size) + self.staticAnimationNode.visibility = true + + if let animateInAnimationNode = self.animateInAnimationNode { + animateInAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.appearAnimation.resource), width: Int(animationDisplaySize.width * 2.5), height: Int(animationDisplaySize.height * 2.5), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.appearAnimation.resource.id))) + animateInAnimationNode.position = animationFrame.center + animateInAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size) + animateInAnimationNode.updateLayout(size: animationFrame.size) + } + + /*self.stillAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation.resource), width: Int(animationDisplaySize.width * 2.5), height: Int(animationDisplaySize.height * 2.5), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation.resource.id))) self.stillAnimationNode.position = animationFrame.center self.stillAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size) - self.stillAnimationNode.updateLayout(size: animationFrame.size) - self.stillAnimationNode.visibility = true + self.stillAnimationNode.updateLayout(size: animationFrame.size)*/ } } else { - transition.updatePosition(node: self.stillAnimationNode, position: animationFrame.center, beginWithCurrentState: true) - transition.updateTransformScale(node: self.stillAnimationNode, scale: animationFrame.size.width / self.stillAnimationNode.bounds.width, beginWithCurrentState: true) + transition.updatePosition(node: self.staticAnimationNode, position: animationFrame.center, beginWithCurrentState: true) + transition.updateTransformScale(node: self.staticAnimationNode, scale: animationFrame.size.width / self.staticAnimationNode.bounds.width, beginWithCurrentState: true) + + if let animateInAnimationNode = self.animateInAnimationNode { + transition.updatePosition(node: animateInAnimationNode, position: animationFrame.center, beginWithCurrentState: true) + transition.updateTransformScale(node: animateInAnimationNode, scale: animationFrame.size.width / animateInAnimationNode.bounds.width, beginWithCurrentState: true) + } + + if let stillAnimationNode = self.stillAnimationNode { + transition.updatePosition(node: stillAnimationNode, position: animationFrame.center, beginWithCurrentState: true) + transition.updateTransformScale(node: stillAnimationNode, scale: animationFrame.size.width / stillAnimationNode.bounds.width, beginWithCurrentState: true) + } } } - - func didAppear() { - } }