From a217e4c1aaa3ec4585e684dba0477f928c590827 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 2 Dec 2021 18:29:19 +0400 Subject: [PATCH] Improve spoiler reveal --- .../Sources/InvisibleInkDustNode.swift | 48 +++++++++++++++++- .../TextSpot.imageset/Contents.json | 21 ++++++++ .../TextSpot.imageset/blurSmall_Normal@3x.png | Bin 0 -> 6505 bytes .../ChatMessageTextBubbleContentNode.swift | 13 +---- 4 files changed, 68 insertions(+), 14 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Components/TextSpot.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Components/TextSpot.imageset/blurSmall_Normal@3x.png diff --git a/submodules/InvisibleInkDustNode/Sources/InvisibleInkDustNode.swift b/submodules/InvisibleInkDustNode/Sources/InvisibleInkDustNode.swift index b42347bd9c..84e8c537d1 100644 --- a/submodules/InvisibleInkDustNode/Sources/InvisibleInkDustNode.swift +++ b/submodules/InvisibleInkDustNode/Sources/InvisibleInkDustNode.swift @@ -17,11 +17,28 @@ private func createEmitterBehavior(type: String) -> NSObject { public class InvisibleInkDustNode: ASDisplayNode { private var currentParams: (size: CGSize, color: UIColor, rects: [CGRect])? + private weak var textNode: TextNode? + + private let maskNode: ASDisplayNode + private let spotNode: ASImageNode + private var emitter: CAEmitterCell? private var emitterLayer: CAEmitterLayer? public var isRevealedUpdated: (Bool) -> Void = { _ in } + public init(textNode: TextNode) { + self.textNode = textNode + + self.maskNode = ASDisplayNode() + self.spotNode = ASImageNode() + self.spotNode.image = UIImage(bundleImageName: "Components/TextSpot") + + super.init() + + self.maskNode.addSubnode(self.spotNode) + } + public override func didLoad() { super.didLoad() @@ -77,23 +94,48 @@ public class InvisibleInkDustNode: ASDisplayNode { private var revealed = false @objc private func tap(_ gestureRecognizer: UITapGestureRecognizer) { - guard !self.revealed else { + guard let (size, _, _) = self.currentParams, !self.revealed else { return } + self.revealed = true let position = gestureRecognizer.location(in: self.view) self.emitterLayer?.setValue(true, forKeyPath: "emitterBehaviors.fingerAttractor.enabled") self.emitterLayer?.setValue(position, forKeyPath: "emitterBehaviors.fingerAttractor.position") + self.textNode?.view.mask = self.maskNode.view + self.textNode?.alpha = 1.0 + + let radius = max(size.width, size.height) + self.spotNode.frame = CGRect(x: position.x - radius / 2.0, y: position.y - radius / 2.0, width: radius, height: radius) + + self.spotNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) + self.spotNode.layer.animateScale(from: 0.0, to: 3.5, duration: 0.61, removeOnCompletion: false, completion: { [weak self] _ in + self?.textNode?.view.mask = nil + }) + Queue.mainQueue().after(0.2) { + let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .linear) + transition.updateAlpha(node: self, alpha: 0.0) + self.isRevealedUpdated(true) } + Queue.mainQueue().after(0.7) { + self.emitterLayer?.setValue(false, forKeyPath: "emitterBehaviors.fingerAttractor.enabled") + self.spotNode.layer.removeAllAnimations() + } + Queue.mainQueue().after(4.0) { self.revealed = false - self.emitterLayer?.setValue(false, forKeyPath: "emitterBehaviors.fingerAttractor.enabled") self.isRevealedUpdated(false) + + let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .linear) + transition.updateAlpha(node: self, alpha: 1.0) + if let textNode = self.textNode { + transition.updateAlpha(node: textNode, alpha: 0.0) + } } } @@ -120,6 +162,8 @@ public class InvisibleInkDustNode: ASDisplayNode { public func update(size: CGSize, color: UIColor, rects: [CGRect]) { self.currentParams = (size, color, rects) + + self.maskNode.frame = CGRect(origin: CGPoint(x: 3.0, y: 3.0), size: size) if self.isNodeLoaded { self.updateEmitter() diff --git a/submodules/TelegramUI/Images.xcassets/Components/TextSpot.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Components/TextSpot.imageset/Contents.json new file mode 100644 index 0000000000..dce2efef0a --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Components/TextSpot.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "blurSmall_Normal@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Components/TextSpot.imageset/blurSmall_Normal@3x.png b/submodules/TelegramUI/Images.xcassets/Components/TextSpot.imageset/blurSmall_Normal@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f0dcdbc3f6f4d2505f8cf51e948b85f70fe13f GIT binary patch literal 6505 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 P00000NkvXXu0mjfv{_IY literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index 5b8f4661d8..d5bdadc345 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -387,18 +387,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { if let current = strongSelf.dustNode { dustNode = current } else { - dustNode = InvisibleInkDustNode() - dustNode.isRevealedUpdated = { [weak self] revealed in - if let strongSelf = self { - let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .linear) - if let dustNode = strongSelf.dustNode { - transition.updateAlpha(node: dustNode, alpha: revealed ? 0.0 : 1.0) - } - if let spoilerTextNode = strongSelf.spoilerTextNode { - transition.updateAlpha(node: spoilerTextNode, alpha: revealed ? 1.0 : 0.0) - } - } - } + dustNode = InvisibleInkDustNode(textNode: spoilerTextNode) strongSelf.dustNode = dustNode strongSelf.insertSubnode(dustNode, aboveSubnode: spoilerTextNode) }