mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Refactor InstantPageUI and related modules
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import TelegramCore
|
||||
import Postbox
|
||||
import TelegramPresentationData
|
||||
import AvatarNode
|
||||
|
||||
private let avatarFont = UIFont(name: ".SFCompactRounded-Semibold", size: 24.0)!
|
||||
private let avatarBackgroundImage = UIImage(bundleImageName: "Chat/Message/LocationPin")?.precomposed()
|
||||
|
||||
private func addPulseAnimations(layer: CALayer) {
|
||||
let scaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
|
||||
scaleAnimation.values = [0.0 as NSNumber, 0.72 as NSNumber, 1.0 as NSNumber, 1.0 as NSNumber]
|
||||
scaleAnimation.keyTimes = [0.0 as NSNumber, 0.49 as NSNumber, 0.88 as NSNumber, 1.0 as NSNumber]
|
||||
scaleAnimation.duration = 3.0
|
||||
scaleAnimation.repeatCount = Float.infinity
|
||||
scaleAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
|
||||
scaleAnimation.beginTime = 1.0
|
||||
layer.add(scaleAnimation, forKey: "pulse-scale")
|
||||
|
||||
let opacityAnimation = CAKeyframeAnimation(keyPath: "opacity")
|
||||
opacityAnimation.values = [1.0 as NSNumber, 0.2 as NSNumber, 0.0 as NSNumber, 0.0 as NSNumber]
|
||||
opacityAnimation.keyTimes = [0.0 as NSNumber, 0.4 as NSNumber, 0.62 as NSNumber, 1.0 as NSNumber]
|
||||
opacityAnimation.duration = 3.0
|
||||
opacityAnimation.repeatCount = Float.infinity
|
||||
opacityAnimation.beginTime = 1.0
|
||||
layer.add(opacityAnimation, forKey: "pulse-opacity")
|
||||
}
|
||||
|
||||
private func removePulseAnimations(layer: CALayer) {
|
||||
layer.removeAnimation(forKey: "pulse-scale")
|
||||
layer.removeAnimation(forKey: "pulse-opacity")
|
||||
}
|
||||
|
||||
public final class ChatMessageLiveLocationPositionNode: ASDisplayNode {
|
||||
private let backgroundNode: ASImageNode
|
||||
private let avatarNode: AvatarNode
|
||||
private let pulseNode: ASImageNode
|
||||
|
||||
private var pulseImage: UIImage?
|
||||
|
||||
override public init() {
|
||||
let isLayerBacked = !smartInvertColorsEnabled()
|
||||
|
||||
self.backgroundNode = ASImageNode()
|
||||
self.backgroundNode.isLayerBacked = true
|
||||
self.backgroundNode.displaysAsynchronously = false
|
||||
self.backgroundNode.displayWithoutProcessing = true
|
||||
|
||||
self.avatarNode = AvatarNode(font: avatarFont)
|
||||
self.avatarNode.isLayerBacked = isLayerBacked
|
||||
|
||||
self.pulseNode = ASImageNode()
|
||||
self.pulseNode.isLayerBacked = true
|
||||
self.pulseNode.displaysAsynchronously = false
|
||||
self.pulseNode.displayWithoutProcessing = true
|
||||
self.pulseNode.isHidden = true
|
||||
|
||||
super.init()
|
||||
|
||||
self.isLayerBacked = isLayerBacked
|
||||
|
||||
self.addSubnode(self.pulseNode)
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.avatarNode)
|
||||
}
|
||||
|
||||
public func asyncLayout() -> (_ account: Account, _ theme: PresentationTheme, _ peer: Peer?, _ liveActive: Bool?) -> (CGSize, () -> Void) {
|
||||
let currentPulseImage = self.pulseImage
|
||||
|
||||
return { [weak self] account, theme, peer, liveActive in
|
||||
let backgroundImage: UIImage?
|
||||
var hasPulse = false
|
||||
if let peer = peer {
|
||||
backgroundImage = avatarBackgroundImage
|
||||
|
||||
if let liveActive = liveActive {
|
||||
hasPulse = liveActive
|
||||
}
|
||||
} else {
|
||||
backgroundImage = PresentationResourcesChat.chatBubbleMapPinImage(theme)
|
||||
}
|
||||
|
||||
let pulseImage: UIImage?
|
||||
if hasPulse {
|
||||
pulseImage = currentPulseImage ?? generateFilledCircleImage(diameter: 120.0, color: UIColor(rgb: 0x007aff, alpha: 0.27))
|
||||
} else {
|
||||
pulseImage = nil
|
||||
}
|
||||
|
||||
return (CGSize(width: 62.0, height: 74.0), {
|
||||
if let strongSelf = self {
|
||||
if strongSelf.backgroundNode.image !== backgroundImage {
|
||||
strongSelf.backgroundNode.image = backgroundImage
|
||||
}
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 62.0, height: 74.0))
|
||||
strongSelf.avatarNode.frame = CGRect(origin: CGPoint(x: 10.0, y: 9.0), size: CGSize(width: 42.0, height: 42.0))
|
||||
if let peer = peer {
|
||||
strongSelf.avatarNode.setPeer(account: account, theme: theme, peer: peer)
|
||||
strongSelf.avatarNode.isHidden = false
|
||||
|
||||
if let liveActive = liveActive {
|
||||
strongSelf.avatarNode.alpha = liveActive ? 1.0 : 0.6
|
||||
} else {
|
||||
strongSelf.avatarNode.alpha = 1.0
|
||||
}
|
||||
} else {
|
||||
strongSelf.avatarNode.isHidden = true
|
||||
}
|
||||
|
||||
strongSelf.pulseImage = pulseImage
|
||||
strongSelf.pulseNode.image = pulseImage
|
||||
strongSelf.pulseNode.frame = CGRect(origin: CGPoint(x: floor((62.0 - 60.0) / 2.0), y: 34.0), size: CGSize(width: 60.0, height: 60.0))
|
||||
if hasPulse {
|
||||
if strongSelf.pulseNode.isHidden {
|
||||
strongSelf.pulseNode.isHidden = false
|
||||
if strongSelf.isInHierarchy {
|
||||
addPulseAnimations(layer: strongSelf.pulseNode.layer)
|
||||
}
|
||||
}
|
||||
} else if !strongSelf.pulseNode.isHidden {
|
||||
strongSelf.pulseNode.isHidden = true
|
||||
removePulseAnimations(layer: strongSelf.pulseNode.layer)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override public func willEnterHierarchy() {
|
||||
super.willEnterHierarchy()
|
||||
if !self.pulseNode.isHidden {
|
||||
addPulseAnimations(layer: self.pulseNode.layer)
|
||||
}
|
||||
}
|
||||
|
||||
override public func didExitHierarchy() {
|
||||
super.didExitHierarchy()
|
||||
if !self.pulseNode.isHidden {
|
||||
removePulseAnimations(layer: self.pulseNode.layer)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user