diff --git a/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift b/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift index 576df8e2e2..d2a6de85b4 100644 --- a/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift +++ b/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift @@ -179,13 +179,13 @@ public final class ReactionButtonAsyncNode: ContextControllerSourceNode { if previousComponent != component { componentAlpha = animationFraction - componentVerticalOffset = (1.0 - animationFraction) * 8.0 + componentVerticalOffset = -(1.0 - animationFraction) * 8.0 if previousComponent.string < component.string { componentVerticalOffset = -componentVerticalOffset } let previousComponentAlpha = 1.0 - componentAlpha - var previousComponentVerticalOffset = -animationFraction * 8.0 + var previousComponentVerticalOffset = animationFraction * 8.0 if previousComponent.string < component.string { previousComponentVerticalOffset = -previousComponentVerticalOffset } diff --git a/submodules/ReactionSelectionNode/BUILD b/submodules/ReactionSelectionNode/BUILD index 393180a383..34077a9831 100644 --- a/submodules/ReactionSelectionNode/BUILD +++ b/submodules/ReactionSelectionNode/BUILD @@ -14,6 +14,7 @@ swift_library( "//submodules/TelegramCore:TelegramCore", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", + "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AnimatedStickerNode:AnimatedStickerNode", "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", "//submodules/TelegramPresentationData:TelegramPresentationData", diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index 1d0f40d5bf..a92477c809 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -7,6 +7,7 @@ import TelegramPresentationData import AccountContext import TelegramAnimatedStickerNode import ReactionButtonListComponent +import SwiftSignalKit public final class ReactionContextItem { public struct Reaction: Equatable { @@ -60,7 +61,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { private let previewingItemContainer: ASDisplayNode private var visibleItemNodes: [Int: ReactionNode] = [:] - private weak var currentLongPressItemNode: ReactionNode? + private var longPressRecognizer: UILongPressGestureRecognizer? + private var longPressTimer: SwiftSignalKit.Timer? private var highlightedReaction: ReactionContextItem.Reaction? private var didTriggerExpandedReaction: Bool = false @@ -144,9 +146,10 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) - let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:))) - longPressGesture.minimumPressDuration = 0.2 - self.view.addGestureRecognizer(longPressGesture) + let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:))) + longPressRecognizer.minimumPressDuration = 0.2 + self.longPressRecognizer = longPressRecognizer + self.view.addGestureRecognizer(longPressRecognizer) } public func updateLayout(size: CGSize, insets: UIEdgeInsets, anchorRect: CGRect, transition: ContainedViewLayoutTransition) { @@ -485,6 +488,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { itemNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.9, removeOnCompletion: false) itemNode.layer.animatePosition(from: itemNode.layer.position, to: targetPosition, duration: duration, removeOnCompletion: false) + targetSnapshotView.alpha = 1.0 targetSnapshotView.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration * 0.8) targetSnapshotView.layer.animatePosition(from: sourceFrame.center, to: targetPosition, duration: duration, removeOnCompletion: false) targetSnapshotView.layer.animateScale(from: itemNode.bounds.width / targetSnapshotView.bounds.width, to: 1.0, duration: duration, removeOnCompletion: false, completion: { [weak targetSnapshotView] _ in @@ -653,7 +657,6 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { theme: strongSelf.context.sharedContext.currentPresentationData.with({ $0 }).theme, reaction: itemNode.item, targetView: targetView, - hideNode: true, completion: { [weak standaloneReactionAnimation] in standaloneReactionAnimation?.removeFromSupernode() } @@ -704,8 +707,18 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { if let (size, insets, anchorRect) = self.validLayout { self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, transition: .animated(duration: 2.5, curve: .linear), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) } + + self.longPressTimer?.invalidate() + self.longPressTimer = SwiftSignalKit.Timer(timeout: 2.5, repeat: false, completion: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.longPressRecognizer?.state = .cancelled + }, queue: .mainQueue()) + self.longPressTimer?.start() } case .ended, .cancelled: + self.longPressTimer?.invalidate() self.continuousHaptic = nil self.didTriggerExpandedReaction = true self.highlightGestureFinished(performAction: true) @@ -839,7 +852,6 @@ public final class StandaloneReactionAnimation: ASDisplayNode { private var isCancelled: Bool = false private weak var targetView: UIView? - private var hideNode: Bool = false override public init() { super.init() @@ -847,18 +859,17 @@ public final class StandaloneReactionAnimation: ASDisplayNode { self.isUserInteractionEnabled = false } - public func animateReactionSelection(context: AccountContext, theme: PresentationTheme, reaction: ReactionContextItem, targetView: UIView, hideNode: Bool, completion: @escaping () -> Void) { - self.animateReactionSelection(context: context, theme: theme, reaction: reaction, targetView: targetView, currentItemNode: nil, hideNode: hideNode, completion: completion) + public func animateReactionSelection(context: AccountContext, theme: PresentationTheme, reaction: ReactionContextItem, targetView: UIView, completion: @escaping () -> Void) { + self.animateReactionSelection(context: context, theme: theme, reaction: reaction, targetView: targetView, currentItemNode: nil, completion: completion) } - func animateReactionSelection(context: AccountContext, theme: PresentationTheme, reaction: ReactionContextItem, targetView: UIView, currentItemNode: ReactionNode?, hideNode: Bool, completion: @escaping () -> Void) { + func animateReactionSelection(context: AccountContext, theme: PresentationTheme, reaction: ReactionContextItem, targetView: UIView, currentItemNode: ReactionNode?, completion: @escaping () -> Void) { guard let sourceSnapshotView = targetView.snapshotContentTree() else { completion() return } self.targetView = targetView - self.hideNode = hideNode let itemNode: ReactionNode if let currentItemNode = currentItemNode { @@ -884,9 +895,7 @@ public final class StandaloneReactionAnimation: ASDisplayNode { targetView.imageView.isHidden = true } else { - if hideNode { - targetView.isHidden = true - } + targetView.isHidden = true } } @@ -951,10 +960,8 @@ public final class StandaloneReactionAnimation: ASDisplayNode { if let targetView = targetView as? ReactionIconView { targetView.imageView.isHidden = false } else { - if strongSelf.hideNode { - targetView.alpha = 1.0 - targetView.isHidden = false - } + targetView.alpha = 1.0 + targetView.isHidden = false } } @@ -981,63 +988,6 @@ public final class StandaloneReactionAnimation: ASDisplayNode { }) } - /*private func animateFromItemNodeToReaction(itemNode: ReactionNode, targetView: UIView, hideNode: Bool, completion: @escaping () -> Void) { - if "".isEmpty { - if hideNode { - targetView.alpha = 1.0 - targetView.isHidden = false - } - completion() - return - } - - guard let targetSnapshotView = targetView.snapshotContentTree(unhide: true) else { - completion() - return - } - - let sourceFrame = itemNode.view.convert(itemNode.bounds, to: self.view) - let targetFrame = self.view.convert(targetView.convert(targetView.bounds, to: nil), from: nil) - - targetSnapshotView.frame = targetFrame - self.view.insertSubview(targetSnapshotView, belowSubview: itemNode.view) - - var completedTarget = false - var targetScaleCompleted = false - let intermediateCompletion: () -> Void = { - if completedTarget && targetScaleCompleted { - completion() - } - } - - let targetPosition = targetFrame.center - let duration: Double = 0.16 - - itemNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration * 0.9, removeOnCompletion: false) - itemNode.layer.animatePosition(from: itemNode.layer.position, to: targetPosition, duration: duration, removeOnCompletion: false) - targetSnapshotView.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration * 0.8) - targetSnapshotView.layer.animatePosition(from: sourceFrame.center, to: targetPosition, duration: duration, removeOnCompletion: false) - targetSnapshotView.layer.animateScale(from: itemNode.bounds.width / targetSnapshotView.bounds.width, to: 1.0, duration: duration, removeOnCompletion: false, completion: { [weak targetSnapshotView] _ in - completedTarget = true - intermediateCompletion() - - targetSnapshotView?.isHidden = true - - if hideNode { - targetView.alpha = 1.0 - targetView.isHidden = false - targetSnapshotView?.isHidden = true - targetScaleCompleted = true - intermediateCompletion() - } else { - targetScaleCompleted = true - intermediateCompletion() - } - }) - - itemNode.layer.animateScale(from: 1.0, to: (targetSnapshotView.bounds.width * 1.0) / itemNode.bounds.width, duration: duration, removeOnCompletion: false) - }*/ - public func addRelativeContentOffset(_ offset: CGPoint, transition: ContainedViewLayoutTransition) { self.bounds = self.bounds.offsetBy(dx: 0.0, dy: offset.y) transition.animateOffsetAdditive(node: self, offset: -offset.y) @@ -1046,7 +996,7 @@ public final class StandaloneReactionAnimation: ASDisplayNode { public func cancel() { self.isCancelled = true - if let targetView = self.targetView, self.hideNode { + if let targetView = self.targetView { if let targetView = targetView as? ReactionIconView { targetView.imageView.isHidden = false } else { diff --git a/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift b/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift index 2c4a70dcd4..34bd0a559e 100644 --- a/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift @@ -171,7 +171,6 @@ class ReactionChatPreviewItemNode: ListViewItemNode { largeApplicationAnimation: reaction.effectAnimation ), targetView: targetView, - hideNode: true, completion: { [weak standaloneReactionAnimation] in standaloneReactionAnimation?.removeFromSupernode() } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 247a262e15..2b4357fe33 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1293,7 +1293,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G largeApplicationAnimation: reaction.effectAnimation ), targetView: targetView, - hideNode: true, completion: { [weak standaloneReactionAnimation] in standaloneReactionAnimation?.removeFromSupernode() } diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index b0b8aef217..576b1d1328 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -2595,7 +2595,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { largeApplicationAnimation: reaction.effectAnimation ), targetView: targetView, - hideNode: true, completion: { [weak standaloneReactionAnimation] in standaloneReactionAnimation?.removeFromSupernode() } diff --git a/submodules/TelegramUI/Sources/ChatMessageDateAndStatusNode.swift b/submodules/TelegramUI/Sources/ChatMessageDateAndStatusNode.swift index fa1e3c0bd7..7c2f39dab8 100644 --- a/submodules/TelegramUI/Sources/ChatMessageDateAndStatusNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageDateAndStatusNode.swift @@ -70,7 +70,7 @@ private final class StatusReactionNode: ASDisplayNode { if self.value != value { self.value = value - let boundingImageSize = CGSize(width: 17.0, height: 17.0) + let boundingImageSize = CGSize(width: 14.0, height: 14.0) let defaultImageSize = CGSize(width: boundingImageSize.width + floor(boundingImageSize.width * 0.5 * 2.0), height: boundingImageSize.height + floor(boundingImageSize.height * 0.5 * 2.0)) let imageSize: CGSize if let file = file { @@ -809,29 +809,30 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { item.node.layer.animateScale(from: 0.01, to: 1.0, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring) item.node.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } - - let itemValue = item.value - let itemNode = item.node - item.node.isGestureEnabled = true - let canViewReactionList = arguments.canViewReactionList - item.node.activateAfterCompletion = !canViewReactionList - item.node.activated = { [weak itemNode] gesture, _ in - guard let strongSelf = self, canViewReactionList else { - return - } - guard let itemNode = itemNode else { - return - } - - if let openReactionPreview = strongSelf.openReactionPreview { - openReactionPreview(gesture, itemNode.containerNode, itemValue) - } else { - gesture.cancel() - } - } } else { animation.animator.updateFrame(layer: item.node.layer, frame: CGRect(origin: reactionButtonPosition, size: item.size), completion: nil) } + + let itemValue = item.value + let itemNode = item.node + item.node.isGestureEnabled = true + let canViewReactionList = arguments.canViewReactionList + item.node.activateAfterCompletion = !canViewReactionList + item.node.activated = { [weak itemNode] gesture, _ in + guard let strongSelf = self, canViewReactionList else { + return + } + guard let itemNode = itemNode else { + return + } + + if let openReactionPreview = strongSelf.openReactionPreview { + openReactionPreview(gesture, itemNode.containerNode, itemValue) + } else { + gesture.cancel() + } + } + reactionButtonPosition.x += item.size.width + 6.0 } @@ -1052,7 +1053,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { node.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } } - let nodeFrame = CGRect(origin: CGPoint(x: reactionOffset, y: backgroundInsets.top + offset + verticalInset - 2.0), size: CGSize(width: reactionSize, height: reactionSize)) + let nodeFrame = CGRect(origin: CGPoint(x: reactionOffset, y: backgroundInsets.top + offset + verticalInset), size: CGSize(width: reactionSize, height: reactionSize)) if animateNode { animation.animator.updateFrame(layer: node.layer, frame: nodeFrame, completion: nil) } else { diff --git a/submodules/TelegramUI/Sources/ChatMessageReactionsFooterContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageReactionsFooterContentNode.swift index 7caa0cffc9..ef0076299e 100644 --- a/submodules/TelegramUI/Sources/ChatMessageReactionsFooterContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageReactionsFooterContentNode.swift @@ -311,27 +311,27 @@ final class MessageReactionButtonsNode: ASDisplayNode { item.node.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } item.node.frame = itemFrame - - let itemValue = item.value - let itemNode = item.node - item.node.isGestureEnabled = true - let canViewReactionList = canViewMessageReactionList(message: message) - item.node.activateAfterCompletion = !canViewReactionList - item.node.activated = { [weak itemNode] gesture, _ in - guard let strongSelf = self, let itemNode = itemNode else { - gesture.cancel() - return - } - if !canViewReactionList { - return - } - strongSelf.openReactionPreview?(gesture, itemNode.containerNode, itemValue) - } - item.node.additionalActivationProgressLayer = itemMaskView.layer } else { animation.animator.updateFrame(layer: item.node.layer, frame: itemFrame, completion: nil) } + let itemValue = item.value + let itemNode = item.node + item.node.isGestureEnabled = true + let canViewReactionList = canViewMessageReactionList(message: message) + item.node.activateAfterCompletion = !canViewReactionList + item.node.activated = { [weak itemNode] gesture, _ in + guard let strongSelf = self, let itemNode = itemNode else { + gesture.cancel() + return + } + if !canViewReactionList { + return + } + strongSelf.openReactionPreview?(gesture, itemNode.containerNode, itemValue) + } + item.node.additionalActivationProgressLayer = itemMaskView.layer + if itemMaskView.superview == nil { strongSelf.backgroundMaskView?.addSubview(itemMaskView) if animation.isAnimated { diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index 3e926654b0..3ff9a85793 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -689,7 +689,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { layoutSize.height += dateAndStatusSize.height } if let reactionButtonsSizeAndApply = reactionButtonsSizeAndApply { - layoutSize.height += 4.0 + reactionButtonsSizeAndApply.0.height + 4.0 + layoutSize.height += reactionButtonsSizeAndApply.0.height + 2.0 } if let actionButtonsSizeAndApply = actionButtonsSizeAndApply { layoutSize.height += actionButtonsSizeAndApply.0.height @@ -986,7 +986,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { if let reactionButtonsSizeAndApply = reactionButtonsSizeAndApply { let reactionButtonsNode = reactionButtonsSizeAndApply.1(animation) - var reactionButtonsFrame = CGRect(origin: CGPoint(x: imageFrame.minX, y: imageFrame.maxY - innerImageInset + 4.0), size: reactionButtonsSizeAndApply.0) + var reactionButtonsFrame = CGRect(origin: CGPoint(x: imageFrame.minX, y: dateAndStatusFrame.maxY + 6.0), size: reactionButtonsSizeAndApply.0) if !incoming { reactionButtonsFrame.origin.x = imageFrame.maxX - innerImageInset - reactionButtonsSizeAndApply.0.width }