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 0000000000..e9f0dcdbc3 Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Components/TextSpot.imageset/blurSmall_Normal@3x.png differ 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) }