Use static spoiler when energy saving

This commit is contained in:
Ilya Laktyushin 2023-03-03 16:48:20 +04:00
parent 6fa3948d22
commit 9fddaf9f96
13 changed files with 229 additions and 144 deletions

View File

@ -1038,7 +1038,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
if let current = self.dustNode { if let current = self.dustNode {
dustNode = current dustNode = current
} else { } else {
dustNode = InvisibleInkDustNode(textNode: nil) dustNode = InvisibleInkDustNode(textNode: nil, enableAnimations: self.context.sharedContext.energyUsageSettings.fullTranslucency)
dustNode.alpha = self.spoilersRevealed ? 0.0 : 1.0 dustNode.alpha = self.spoilersRevealed ? 0.0 : 1.0
dustNode.isUserInteractionEnabled = false dustNode.isUserInteractionEnabled = false
textInputNode.textView.addSubview(dustNode.view) textInputNode.textView.addSubview(dustNode.view)
@ -1298,7 +1298,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
private func updateOneLineSpoiler() { private func updateOneLineSpoiler() {
if let textLayout = self.oneLineNode.textNode.cachedLayout, !textLayout.spoilers.isEmpty { if let textLayout = self.oneLineNode.textNode.cachedLayout, !textLayout.spoilers.isEmpty {
if self.oneLineDustNode == nil { if self.oneLineDustNode == nil {
let oneLineDustNode = InvisibleInkDustNode(textNode: nil) let oneLineDustNode = InvisibleInkDustNode(textNode: nil, enableAnimations: self.context.sharedContext.energyUsageSettings.fullTranslucency)
self.oneLineDustNode = oneLineDustNode self.oneLineDustNode = oneLineDustNode
self.oneLineNode.textNode.supernode?.insertSubnode(oneLineDustNode, aboveSubnode: self.oneLineNode.textNode) self.oneLineNode.textNode.supernode?.insertSubnode(oneLineDustNode, aboveSubnode: self.oneLineNode.textNode)

View File

@ -549,7 +549,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
if let textLayout = self.currentOptionNode.cachedLayout, !textLayout.spoilers.isEmpty { if let textLayout = self.currentOptionNode.cachedLayout, !textLayout.spoilers.isEmpty {
if self.dustNode == nil { if self.dustNode == nil {
let dustNode = InvisibleInkDustNode(textNode: nil) let dustNode = InvisibleInkDustNode(textNode: nil, enableAnimations: true)
self.dustNode = dustNode self.dustNode = dustNode
self.currentOptionNode.supernode?.insertSubnode(dustNode, aboveSubnode: self.currentOptionNode) self.currentOptionNode.supernode?.insertSubnode(dustNode, aboveSubnode: self.currentOptionNode)

View File

@ -3124,7 +3124,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
if let current = strongSelf.dustNode { if let current = strongSelf.dustNode {
dustNode = current dustNode = current
} else { } else {
dustNode = InvisibleInkDustNode(textNode: nil) dustNode = InvisibleInkDustNode(textNode: nil, enableAnimations: item.context.sharedContext.energyUsageSettings.fullTranslucency)
dustNode.isUserInteractionEnabled = false dustNode.isUserInteractionEnabled = false
strongSelf.dustNode = dustNode strongSelf.dustNode = dustNode

View File

@ -813,7 +813,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
self.spoilerTextNode = spoilerTextNode self.spoilerTextNode = spoilerTextNode
self.textNode.supernode?.insertSubnode(spoilerTextNode, aboveSubnode: self.textNode) self.textNode.supernode?.insertSubnode(spoilerTextNode, aboveSubnode: self.textNode)
let dustNode = InvisibleInkDustNode(textNode: spoilerTextNode) let dustNode = InvisibleInkDustNode(textNode: spoilerTextNode, enableAnimations: self.context.sharedContext.energyUsageSettings.fullTranslucency)
self.dustNode = dustNode self.dustNode = dustNode
spoilerTextNode.supernode?.insertSubnode(dustNode, aboveSubnode: spoilerTextNode) spoilerTextNode.supernode?.insertSubnode(dustNode, aboveSubnode: spoilerTextNode)

View File

@ -6,6 +6,25 @@ import AsyncDisplayKit
import Display import Display
import AppBundle import AppBundle
import LegacyComponents import LegacyComponents
import GameplayKit
private struct ArbitraryRandomNumberGenerator : RandomNumberGenerator {
init(seed: Int) { srand48(seed) }
func next() -> UInt64 { return UInt64(drand48() * Double(UInt64.max)) }
}
// mutating func next() -> UInt64 {
// // GKRandom produces values in [INT32_MIN, INT32_MAX] range; hence we need two numbers to produce 64-bit value.
// let next1 = UInt64(bitPattern: Int64(gkrandom.nextInt()))
// let next2 = UInt64(bitPattern: Int64(gkrandom.nextInt()))
// return next1 ^ (next2 << 32)
// }
//
// init(seed: UInt64) {
// self.gkrandom = GKMersenneTwisterRandomSource(seed: seed)
// }
//
// private let gkrandom: GKRandom
//}
func createEmitterBehavior(type: String) -> NSObject { func createEmitterBehavior(type: String) -> NSObject {
let selector = ["behaviorWith", "Type:"].joined(separator: "") let selector = ["behaviorWith", "Type:"].joined(separator: "")
@ -45,6 +64,7 @@ func generateMaskImage(size originalSize: CGSize, position: CGPoint, inverse: Bo
public class InvisibleInkDustNode: ASDisplayNode { public class InvisibleInkDustNode: ASDisplayNode {
private var currentParams: (size: CGSize, color: UIColor, textColor: UIColor, rects: [CGRect], wordRects: [CGRect])? private var currentParams: (size: CGSize, color: UIColor, textColor: UIColor, rects: [CGRect], wordRects: [CGRect])?
private var animColor: CGColor? private var animColor: CGColor?
private let enableAnimations: Bool
private weak var textNode: TextNode? private weak var textNode: TextNode?
private let textMaskNode: ASDisplayNode private let textMaskNode: ASDisplayNode
@ -56,12 +76,16 @@ public class InvisibleInkDustNode: ASDisplayNode {
private let emitterMaskNode: ASDisplayNode private let emitterMaskNode: ASDisplayNode
private let emitterSpotNode: ASImageNode private let emitterSpotNode: ASImageNode
private let emitterMaskFillNode: ASDisplayNode private let emitterMaskFillNode: ASDisplayNode
private var staticNode: ASImageNode?
private var staticParams: (size: CGSize, color: UIColor, rects: [CGRect])?
public var isRevealed = false public var isRevealed = false
private var isExploding = false private var isExploding = false
public init(textNode: TextNode?) { public init(textNode: TextNode?, enableAnimations: Bool) {
self.textNode = textNode self.textNode = textNode
self.enableAnimations = enableAnimations
self.emitterNode = ASDisplayNode() self.emitterNode = ASDisplayNode()
self.emitterNode.isUserInteractionEnabled = false self.emitterNode.isUserInteractionEnabled = false
@ -94,47 +118,53 @@ public class InvisibleInkDustNode: ASDisplayNode {
public override func didLoad() { public override func didLoad() {
super.didLoad() super.didLoad()
let emitter = CAEmitterCell() if self.enableAnimations {
emitter.contents = UIImage(bundleImageName: "Components/TextSpeckle")?.cgImage let emitter = CAEmitterCell()
emitter.contentsScale = 1.8 emitter.contents = UIImage(bundleImageName: "Components/TextSpeckle")?.cgImage
emitter.emissionRange = .pi * 2.0 emitter.contentsScale = 1.8
emitter.lifetime = 1.0 emitter.emissionRange = .pi * 2.0
emitter.scale = 0.5 emitter.lifetime = 1.0
emitter.velocityRange = 20.0 emitter.scale = 0.5
emitter.name = "dustCell" emitter.velocityRange = 20.0
emitter.alphaRange = 1.0 emitter.name = "dustCell"
emitter.setValue("point", forKey: "particleType") emitter.alphaRange = 1.0
emitter.setValue(3.0, forKey: "mass") emitter.setValue("point", forKey: "particleType")
emitter.setValue(2.0, forKey: "massRange") emitter.setValue(3.0, forKey: "mass")
self.emitter = emitter emitter.setValue(2.0, forKey: "massRange")
self.emitter = emitter
let fingerAttractor = createEmitterBehavior(type: "simpleAttractor")
fingerAttractor.setValue("fingerAttractor", forKey: "name") let fingerAttractor = createEmitterBehavior(type: "simpleAttractor")
fingerAttractor.setValue("fingerAttractor", forKey: "name")
let alphaBehavior = createEmitterBehavior(type: "valueOverLife")
alphaBehavior.setValue("color.alpha", forKey: "keyPath") let alphaBehavior = createEmitterBehavior(type: "valueOverLife")
alphaBehavior.setValue([0.0, 0.0, 1.0, 0.0, -1.0], forKey: "values") alphaBehavior.setValue("color.alpha", forKey: "keyPath")
alphaBehavior.setValue(true, forKey: "additive") alphaBehavior.setValue([0.0, 0.0, 1.0, 0.0, -1.0], forKey: "values")
alphaBehavior.setValue(true, forKey: "additive")
let behaviors = [fingerAttractor, alphaBehavior]
let behaviors = [fingerAttractor, alphaBehavior]
let emitterLayer = CAEmitterLayer()
emitterLayer.masksToBounds = true let emitterLayer = CAEmitterLayer()
emitterLayer.allowsGroupOpacity = true emitterLayer.masksToBounds = true
emitterLayer.lifetime = 1 emitterLayer.allowsGroupOpacity = true
emitterLayer.emitterCells = [emitter] emitterLayer.lifetime = 1
emitterLayer.emitterPosition = CGPoint(x: 0, y: 0) emitterLayer.emitterCells = [emitter]
emitterLayer.seed = arc4random() emitterLayer.emitterPosition = CGPoint(x: 0, y: 0)
emitterLayer.emitterSize = CGSize(width: 1, height: 1) emitterLayer.seed = arc4random()
emitterLayer.emitterShape = CAEmitterLayerEmitterShape(rawValue: "rectangles") emitterLayer.emitterSize = CGSize(width: 1, height: 1)
emitterLayer.setValue(behaviors, forKey: "emitterBehaviors") emitterLayer.emitterShape = CAEmitterLayerEmitterShape(rawValue: "rectangles")
emitterLayer.setValue(behaviors, forKey: "emitterBehaviors")
emitterLayer.setValue(4.0, forKeyPath: "emitterBehaviors.fingerAttractor.stiffness")
emitterLayer.setValue(false, forKeyPath: "emitterBehaviors.fingerAttractor.enabled") emitterLayer.setValue(4.0, forKeyPath: "emitterBehaviors.fingerAttractor.stiffness")
emitterLayer.setValue(false, forKeyPath: "emitterBehaviors.fingerAttractor.enabled")
self.emitterLayer = emitterLayer
self.emitterLayer = emitterLayer
self.emitterNode.layer.addSublayer(emitterLayer)
self.emitterNode.layer.addSublayer(emitterLayer)
} else {
let staticNode = ASImageNode()
self.staticNode = staticNode
self.addSubnode(staticNode)
}
self.updateEmitter() self.updateEmitter()
@ -170,102 +200,164 @@ public class InvisibleInkDustNode: ASDisplayNode {
} }
self.isRevealed = true self.isRevealed = true
self.isExploding = true
let position = gestureRecognizer.location(in: self.view) if self.enableAnimations {
self.emitterLayer?.setValue(true, forKeyPath: "emitterBehaviors.fingerAttractor.enabled") self.isExploding = true
self.emitterLayer?.setValue(position, forKeyPath: "emitterBehaviors.fingerAttractor.position")
let maskSize = self.emitterNode.frame.size
Queue.concurrentDefaultQueue().async {
let textMaskImage = generateMaskImage(size: maskSize, position: position, inverse: false)
let emitterMaskImage = generateMaskImage(size: maskSize, position: position, inverse: true)
Queue.mainQueue().async { let position = gestureRecognizer.location(in: self.view)
self.textSpotNode.image = textMaskImage self.emitterLayer?.setValue(true, forKeyPath: "emitterBehaviors.fingerAttractor.enabled")
self.emitterSpotNode.image = emitterMaskImage self.emitterLayer?.setValue(position, forKeyPath: "emitterBehaviors.fingerAttractor.position")
let maskSize = self.emitterNode.frame.size
Queue.concurrentDefaultQueue().async {
let textMaskImage = generateMaskImage(size: maskSize, position: position, inverse: false)
let emitterMaskImage = generateMaskImage(size: maskSize, position: position, inverse: true)
Queue.mainQueue().async {
self.textSpotNode.image = textMaskImage
self.emitterSpotNode.image = emitterMaskImage
}
} }
}
Queue.mainQueue().after(0.1 * UIView.animationDurationFactor()) {
Queue.mainQueue().after(0.1 * UIView.animationDurationFactor()) { textNode.alpha = 1.0
textNode.view.mask = self.textMaskNode.view
self.textSpotNode.frame = CGRect(x: 0.0, y: 0.0, width: self.emitterMaskNode.frame.width * 3.0, height: self.emitterMaskNode.frame.height * 3.0)
let xFactor = (position.x / self.emitterNode.frame.width - 0.5) * 2.0
let yFactor = (position.y / self.emitterNode.frame.height - 0.5) * 2.0
let maxFactor = max(abs(xFactor), abs(yFactor))
var scaleAddition = maxFactor * 4.0
var durationAddition = -maxFactor * 0.2
if self.emitterNode.frame.height > 0.0, self.emitterNode.frame.width / self.emitterNode.frame.height < 0.7 {
scaleAddition *= 5.0
durationAddition *= 2.0
}
self.textSpotNode.layer.anchorPoint = CGPoint(x: position.x / self.emitterMaskNode.frame.width, y: position.y / self.emitterMaskNode.frame.height)
self.textSpotNode.position = position
self.textSpotNode.layer.animateScale(from: 0.3333, to: 10.5 + scaleAddition, duration: 0.55 + durationAddition, removeOnCompletion: false, completion: { _ in
textNode.view.mask = nil
})
self.textSpotNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
self.emitterNode.view.mask = self.emitterMaskNode.view
self.emitterSpotNode.frame = CGRect(x: 0.0, y: 0.0, width: self.emitterMaskNode.frame.width * 3.0, height: self.emitterMaskNode.frame.height * 3.0)
self.emitterSpotNode.layer.anchorPoint = CGPoint(x: position.x / self.emitterMaskNode.frame.width, y: position.y / self.emitterMaskNode.frame.height)
self.emitterSpotNode.position = position
self.emitterSpotNode.layer.animateScale(from: 0.3333, to: 10.5 + scaleAddition, duration: 0.55 + durationAddition, removeOnCompletion: false, completion: { [weak self] _ in
self?.alpha = 0.0
self?.emitterNode.view.mask = nil
self?.emitter?.color = textColor.cgColor
})
self.emitterMaskFillNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
}
Queue.mainQueue().after(0.8 * UIView.animationDurationFactor()) {
self.isExploding = false
self.emitterLayer?.setValue(false, forKeyPath: "emitterBehaviors.fingerAttractor.enabled")
self.textSpotNode.layer.removeAllAnimations()
self.emitterSpotNode.layer.removeAllAnimations()
self.emitterMaskFillNode.layer.removeAllAnimations()
}
} else {
textNode.alpha = 1.0 textNode.alpha = 1.0
textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
textNode.view.mask = self.textMaskNode.view self.staticNode?.alpha = 0.0
self.textSpotNode.frame = CGRect(x: 0.0, y: 0.0, width: self.emitterMaskNode.frame.width * 3.0, height: self.emitterMaskNode.frame.height * 3.0) self.staticNode?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25)
let xFactor = (position.x / self.emitterNode.frame.width - 0.5) * 2.0
let yFactor = (position.y / self.emitterNode.frame.height - 0.5) * 2.0
let maxFactor = max(abs(xFactor), abs(yFactor))
var scaleAddition = maxFactor * 4.0
var durationAddition = -maxFactor * 0.2
if self.emitterNode.frame.height > 0.0, self.emitterNode.frame.width / self.emitterNode.frame.height < 0.7 {
scaleAddition *= 5.0
durationAddition *= 2.0
}
self.textSpotNode.layer.anchorPoint = CGPoint(x: position.x / self.emitterMaskNode.frame.width, y: position.y / self.emitterMaskNode.frame.height)
self.textSpotNode.position = position
self.textSpotNode.layer.animateScale(from: 0.3333, to: 10.5 + scaleAddition, duration: 0.55 + durationAddition, removeOnCompletion: false, completion: { _ in
textNode.view.mask = nil
})
self.textSpotNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
self.emitterNode.view.mask = self.emitterMaskNode.view
self.emitterSpotNode.frame = CGRect(x: 0.0, y: 0.0, width: self.emitterMaskNode.frame.width * 3.0, height: self.emitterMaskNode.frame.height * 3.0)
self.emitterSpotNode.layer.anchorPoint = CGPoint(x: position.x / self.emitterMaskNode.frame.width, y: position.y / self.emitterMaskNode.frame.height)
self.emitterSpotNode.position = position
self.emitterSpotNode.layer.animateScale(from: 0.3333, to: 10.5 + scaleAddition, duration: 0.55 + durationAddition, removeOnCompletion: false, completion: { [weak self] _ in
self?.alpha = 0.0
self?.emitterNode.view.mask = nil
self?.emitter?.color = textColor.cgColor
})
self.emitterMaskFillNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
}
Queue.mainQueue().after(0.8 * UIView.animationDurationFactor()) {
self.isExploding = false
self.emitterLayer?.setValue(false, forKeyPath: "emitterBehaviors.fingerAttractor.enabled")
self.textSpotNode.layer.removeAllAnimations()
self.emitterSpotNode.layer.removeAllAnimations()
self.emitterMaskFillNode.layer.removeAllAnimations()
} }
} }
private func updateEmitter() { private func updateEmitter() {
guard let (size, color, _, _, wordRects) = self.currentParams else { guard let (size, color, _, lineRects, wordRects) = self.currentParams else {
return return
} }
self.emitter?.color = self.animColor ?? color.cgColor if self.enableAnimations {
self.emitterLayer?.setValue(wordRects, forKey: "emitterRects") self.emitter?.color = self.animColor ?? color.cgColor
self.emitterLayer?.frame = CGRect(origin: CGPoint(), size: size) self.emitterLayer?.setValue(wordRects, forKey: "emitterRects")
self.emitterLayer?.frame = CGRect(origin: CGPoint(), size: size)
let radius = max(size.width, size.height)
self.emitterLayer?.setValue(max(size.width, size.height), forKeyPath: "emitterBehaviors.fingerAttractor.radius") let radius = max(size.width, size.height)
self.emitterLayer?.setValue(radius * -0.5, forKeyPath: "emitterBehaviors.fingerAttractor.falloff") self.emitterLayer?.setValue(max(size.width, size.height), forKeyPath: "emitterBehaviors.fingerAttractor.radius")
self.emitterLayer?.setValue(radius * -0.5, forKeyPath: "emitterBehaviors.fingerAttractor.falloff")
var square: Float = 0.0
for rect in wordRects { var square: Float = 0.0
square += Float(rect.width * rect.height) for rect in wordRects {
} square += Float(rect.width * rect.height)
}
Queue.mainQueue().async {
self.emitter?.birthRate = min(100000, square * 0.35) Queue.mainQueue().async {
self.emitter?.birthRate = min(100000, square * 0.35)
}
} else {
if let staticParams = self.staticParams, staticParams.size == size && staticParams.color == color && staticParams.rects == lineRects && self.staticNode?.image != nil {
return
}
self.staticParams = (size, color, lineRects)
let start = CACurrentMediaTime()
var combinedRect: CGRect?
var combinedRects: [CGRect] = []
for rect in lineRects {
if let currentRect = combinedRect {
if abs(currentRect.minY - rect.minY) < 1.0 && abs(currentRect.maxY - rect.maxY) < 1.0 {
combinedRect = currentRect.union(rect)
} else {
combinedRects.append(currentRect.insetBy(dx: 0.0, dy: -1.0 + UIScreenPixel))
combinedRect = rect
}
} else {
combinedRect = rect
}
}
if let combinedRect {
combinedRects.append(combinedRect.insetBy(dx: 0.0, dy: -1.0))
}
print("combining \(CACurrentMediaTime() - start)")
var generator = ArbitraryRandomNumberGenerator(seed: 1)
let image = generateImage(size, rotatedContext: { size, context in
let bounds = CGRect(origin: .zero, size: size)
context.clear(bounds)
context.setFillColor(color.cgColor)
for rect in combinedRects {
if rect.width > 10.0 {
let rate = Int(rect.width * rect.height * 0.25)
for _ in 0 ..< rate {
let location = CGPoint(x: .random(in: rect.minX ..< rect.maxX, using: &generator), y: .random(in: rect.minY ..< rect.maxY, using: &generator))
context.fillEllipse(in: CGRect(origin: location, size: CGSize(width: 1.0, height: 1.0)))
}
}
}
})
self.staticNode?.frame = CGRect(origin: CGPoint(), size: size)
self.staticNode?.image = image
print("total draw \(CACurrentMediaTime() - start)")
} }
} }
public func update(size: CGSize, color: UIColor, textColor: UIColor, rects: [CGRect], wordRects: [CGRect]) { public func update(size: CGSize, color: UIColor, textColor: UIColor, rects: [CGRect], wordRects: [CGRect]) {
self.currentParams = (size, color, textColor, rects, wordRects) self.currentParams = (size, color, textColor, rects, wordRects)
self.emitterNode.frame = CGRect(origin: CGPoint(), size: size) let bounds = CGRect(origin: CGPoint(), size: size)
self.emitterMaskNode.frame = self.emitterNode.bounds self.emitterNode.frame = bounds
self.emitterMaskFillNode.frame = self.emitterNode.bounds self.emitterMaskNode.frame = bounds
self.emitterMaskFillNode.frame = bounds
self.textMaskNode.frame = CGRect(origin: CGPoint(x: 3.0, y: 3.0), size: size) self.textMaskNode.frame = CGRect(origin: CGPoint(x: 3.0, y: 3.0), size: size)
self.staticNode?.frame = bounds
if self.isNodeLoaded { if self.isNodeLoaded {
self.updateEmitter() self.updateEmitter()
} }

View File

@ -249,12 +249,6 @@ public func cacheAnimatedStickerFrames(data: Data, size: CGSize, fitzModifier: E
subscriber.putNext(.tempFile(tempFile)) subscriber.putNext(.tempFile(tempFile))
subscriber.putCompletion() subscriber.putCompletion()
/*print("animation render time \(CACurrentMediaTime() - startTime)")
print("of which drawing time \(drawingTime)")
print("of which appending time \(appendingTime)")
print("of which delta time \(deltaTime)")
print("of which compression time \(compressionTime)")*/
} }
} }
})) }))
@ -399,12 +393,6 @@ public func cacheVideoStickerFrames(path: String, size: CGSize, cacheKey: String
subscriber.putNext(.tempFile(tempFile)) subscriber.putNext(.tempFile(tempFile))
subscriber.putCompletion() subscriber.putCompletion()
/*print("animation render time \(CACurrentMediaTime() - startTime)")
print("of which drawing time \(drawingTime)")
print("of which appending time \(appendingTime)")
print("of which delta time \(deltaTime)")
print("of which compression time \(compressionTime)")*/
})) }))
return ActionDisposable { return ActionDisposable {

View File

@ -316,7 +316,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
if let current = strongSelf.dustNode { if let current = strongSelf.dustNode {
dustNode = current dustNode = current
} else { } else {
dustNode = InvisibleInkDustNode(textNode: nil) dustNode = InvisibleInkDustNode(textNode: nil, enableAnimations: item.context.sharedContext.energyUsageSettings.fullTranslucency)
dustNode.isUserInteractionEnabled = false dustNode.isUserInteractionEnabled = false
strongSelf.dustNode = dustNode strongSelf.dustNode = dustNode
strongSelf.insertSubnode(dustNode, aboveSubnode: strongSelf.labelNode.textNode) strongSelf.insertSubnode(dustNode, aboveSubnode: strongSelf.labelNode.textNode)

View File

@ -436,12 +436,13 @@ final class ChatMessageNotificationItemNode: NotificationItemNode {
transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(x: width - 10.0 - imageSize.width, y: (panelHeight - imageSize.height) / 2.0), size: imageSize)) transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(x: width - 10.0 - imageSize.width, y: (panelHeight - imageSize.height) / 2.0), size: imageSize))
if !textLayout.spoilers.isEmpty, let presentationData = self.item?.context.sharedContext.currentPresentationData.with({ $0 }) { if !textLayout.spoilers.isEmpty, let item = self.item {
let presentationData = item.context.sharedContext.currentPresentationData.with({ $0 })
let dustNode: InvisibleInkDustNode let dustNode: InvisibleInkDustNode
if let current = self.dustNode { if let current = self.dustNode {
dustNode = current dustNode = current
} else { } else {
dustNode = InvisibleInkDustNode(textNode: nil) dustNode = InvisibleInkDustNode(textNode: nil, enableAnimations: item.context.sharedContext.energyUsageSettings.fullTranslucency)
dustNode.isUserInteractionEnabled = false dustNode.isUserInteractionEnabled = false
self.dustNode = dustNode self.dustNode = dustNode
self.insertSubnode(dustNode, aboveSubnode: self.textNode.textNode) self.insertSubnode(dustNode, aboveSubnode: self.textNode.textNode)

View File

@ -344,7 +344,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
if let current = node.dustNode { if let current = node.dustNode {
dustNode = current dustNode = current
} else { } else {
dustNode = InvisibleInkDustNode(textNode: nil) dustNode = InvisibleInkDustNode(textNode: nil, enableAnimations: arguments.context.sharedContext.energyUsageSettings.fullTranslucency)
dustNode.isUserInteractionEnabled = false dustNode.isUserInteractionEnabled = false
node.dustNode = dustNode node.dustNode = dustNode
node.contentNode.insertSubnode(dustNode, aboveSubnode: textNode.textNode) node.contentNode.insertSubnode(dustNode, aboveSubnode: textNode.textNode)

View File

@ -485,7 +485,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
if let current = strongSelf.dustNode { if let current = strongSelf.dustNode {
dustNode = current dustNode = current
} else { } else {
dustNode = InvisibleInkDustNode(textNode: spoilerTextNode.textNode) dustNode = InvisibleInkDustNode(textNode: spoilerTextNode.textNode, enableAnimations: item.context.sharedContext.energyUsageSettings.fullTranslucency)
strongSelf.dustNode = dustNode strongSelf.dustNode = dustNode
strongSelf.insertSubnode(dustNode, aboveSubnode: spoilerTextNode.textNode) strongSelf.insertSubnode(dustNode, aboveSubnode: spoilerTextNode.textNode)
} }

View File

@ -764,7 +764,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
if let current = strongSelf.dustNode { if let current = strongSelf.dustNode {
dustNode = current dustNode = current
} else { } else {
dustNode = InvisibleInkDustNode(textNode: spoilerTextNode.textNode) dustNode = InvisibleInkDustNode(textNode: spoilerTextNode.textNode, enableAnimations: strongSelf.context.sharedContext.energyUsageSettings.fullTranslucency)
strongSelf.dustNode = dustNode strongSelf.dustNode = dustNode
strongSelf.contentTextContainer.insertSubnode(dustNode, aboveSubnode: spoilerTextNode.textNode) strongSelf.contentTextContainer.insertSubnode(dustNode, aboveSubnode: spoilerTextNode.textNode)
} }

View File

@ -2289,7 +2289,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
if let start = textInputNode.textView.position(from: beginning, offset: startIndex), let end = textInputNode.textView.position(from: start, offset: endIndex - startIndex), let textRange = textInputNode.textView.textRange(from: start, to: end) { if let start = textInputNode.textView.position(from: beginning, offset: startIndex), let end = textInputNode.textView.position(from: start, offset: endIndex - startIndex), let textRange = textInputNode.textView.textRange(from: start, to: end) {
let textRects = textInputNode.textView.selectionRects(for: textRange) let textRects = textInputNode.textView.selectionRects(for: textRange)
for textRect in textRects { for textRect in textRects {
rects.append(textRect.rect.insetBy(dx: 1.0, dy: 1.0).offsetBy(dx: 0.0, dy: 1.0)) if textRect.rect.width > 1.0 && textRect.rect.size.height > 1.0 {
rects.append(textRect.rect.insetBy(dx: 1.0, dy: 1.0).offsetBy(dx: 0.0, dy: 1.0))
}
} }
} }
} }
@ -2335,7 +2337,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
if let current = self.dustNode { if let current = self.dustNode {
dustNode = current dustNode = current
} else { } else {
dustNode = InvisibleInkDustNode(textNode: nil) dustNode = InvisibleInkDustNode(textNode: nil, enableAnimations: self.context?.sharedContext.energyUsageSettings.fullTranslucency ?? true)
dustNode.alpha = self.spoilersRevealed ? 0.0 : 1.0 dustNode.alpha = self.spoilersRevealed ? 0.0 : 1.0
dustNode.isUserInteractionEnabled = false dustNode.isUserInteractionEnabled = false
textInputNode.textView.addSubview(dustNode.view) textInputNode.textView.addSubview(dustNode.view)

View File

@ -34,6 +34,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
private let actionArea: AccessibilityAreaNode private let actionArea: AccessibilityAreaNode
private let context: AccountContext
var theme: PresentationTheme var theme: PresentationTheme
var strings: PresentationStrings var strings: PresentationStrings
@ -42,6 +43,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
init(context: AccountContext, messageId: MessageId, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) { init(context: AccountContext, messageId: MessageId, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) {
self.messageId = messageId self.messageId = messageId
self.context = context
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
@ -344,7 +346,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
if let textLayout = self.textNode.cachedLayout, !textLayout.spoilers.isEmpty { if let textLayout = self.textNode.cachedLayout, !textLayout.spoilers.isEmpty {
if self.dustNode == nil { if self.dustNode == nil {
let dustNode = InvisibleInkDustNode(textNode: nil) let dustNode = InvisibleInkDustNode(textNode: nil, enableAnimations: self.context.sharedContext.energyUsageSettings.fullTranslucency)
self.dustNode = dustNode self.dustNode = dustNode
self.textNode.supernode?.insertSubnode(dustNode, aboveSubnode: self.textNode) self.textNode.supernode?.insertSubnode(dustNode, aboveSubnode: self.textNode)
} }