mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Refactoring [skip ci]
This commit is contained in:
@@ -383,6 +383,9 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/Chat/ChatSwipeToReplyRecognizer",
|
"//submodules/TelegramUI/Components/Chat/ChatSwipeToReplyRecognizer",
|
||||||
"//submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode",
|
"//submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode",
|
||||||
"//submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoBubbleContentNode",
|
"//submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoBubbleContentNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageTransitionNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ManagedDiceAnimationNode",
|
||||||
] + select({
|
] + select({
|
||||||
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
|
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
|
||||||
"//build-system:ios_sim_arm64": [],
|
"//build-system:ios_sim_arm64": [],
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
|
swift_library(
|
||||||
|
name = "ChatMessageAnimatedStickerItemNode",
|
||||||
|
module_name = "ChatMessageAnimatedStickerItemNode",
|
||||||
|
srcs = glob([
|
||||||
|
"Sources/**/*.swift",
|
||||||
|
]),
|
||||||
|
copts = [
|
||||||
|
"-warnings-as-errors",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//submodules/AsyncDisplayKit",
|
||||||
|
"//submodules/Display",
|
||||||
|
"//submodules/SSignalKit/SwiftSignalKit",
|
||||||
|
"//submodules/Postbox",
|
||||||
|
"//submodules/TelegramCore",
|
||||||
|
"//submodules/TelegramPresentationData",
|
||||||
|
"//submodules/TextFormat",
|
||||||
|
"//submodules/AccountContext",
|
||||||
|
"//submodules/MediaResources",
|
||||||
|
"//submodules/StickerResources",
|
||||||
|
"//submodules/ContextUI",
|
||||||
|
"//submodules/AnimatedStickerNode",
|
||||||
|
"//submodules/TelegramAnimatedStickerNode",
|
||||||
|
"//submodules/Emoji",
|
||||||
|
"//submodules/Markdown",
|
||||||
|
"//submodules/ManagedAnimationNode",
|
||||||
|
"//submodules/SlotMachineAnimationNode",
|
||||||
|
"//submodules/MediaPlayer:UniversalMediaPlayer",
|
||||||
|
"//submodules/ShimmerEffect",
|
||||||
|
"//submodules/WallpaperBackgroundNode",
|
||||||
|
"//submodules/LocalMediaResources",
|
||||||
|
"//submodules/AppBundle",
|
||||||
|
"//submodules/ChatPresentationInterfaceState",
|
||||||
|
"//submodules/TelegramUI/Components/TextNodeWithEntities",
|
||||||
|
"//submodules/TelegramUI/Components/ChatControllerInteraction",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageForwardInfoNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageItem",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageItemView",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageSwipeToReplyNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageSelectionNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageDeliveryFailedNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageShareButton",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageThreadInfoNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageActionButtonsNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatSwipeToReplyRecognizer",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageReactionsFooterContentNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ManagedDiceAnimationNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/MessageHaptics",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageTransitionNode",
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
|
)
|
||||||
@@ -43,12 +43,15 @@ import ChatMessageThreadInfoNode
|
|||||||
import ChatMessageActionButtonsNode
|
import ChatMessageActionButtonsNode
|
||||||
import ChatSwipeToReplyRecognizer
|
import ChatSwipeToReplyRecognizer
|
||||||
import ChatMessageReactionsFooterContentNode
|
import ChatMessageReactionsFooterContentNode
|
||||||
|
import ManagedDiceAnimationNode
|
||||||
|
import MessageHaptics
|
||||||
|
import ChatMessageTransitionNode
|
||||||
|
|
||||||
private let nameFont = Font.medium(14.0)
|
private let nameFont = Font.medium(14.0)
|
||||||
private let inlineBotPrefixFont = Font.regular(14.0)
|
private let inlineBotPrefixFont = Font.regular(14.0)
|
||||||
private let inlineBotNameFont = nameFont
|
private let inlineBotNameFont = nameFont
|
||||||
|
|
||||||
protocol GenericAnimatedStickerNode: ASDisplayNode {
|
public protocol GenericAnimatedStickerNode: ASDisplayNode {
|
||||||
func setOverlayColor(_ color: UIColor?, replace: Bool, animated: Bool)
|
func setOverlayColor(_ color: UIColor?, replace: Bool, animated: Bool)
|
||||||
|
|
||||||
var currentFrameIndex: Int { get }
|
var currentFrameIndex: Int { get }
|
||||||
@@ -56,29 +59,32 @@ protocol GenericAnimatedStickerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension DefaultAnimatedStickerNodeImpl: GenericAnimatedStickerNode {
|
extension DefaultAnimatedStickerNodeImpl: GenericAnimatedStickerNode {
|
||||||
func setFrameIndex(_ frameIndex: Int) {
|
public func setFrameIndex(_ frameIndex: Int) {
|
||||||
self.stop()
|
self.stop()
|
||||||
self.play(fromIndex: frameIndex)
|
self.play(fromIndex: frameIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SlotMachineAnimationNode: GenericAnimatedStickerNode {
|
extension SlotMachineAnimationNode: GenericAnimatedStickerNode {
|
||||||
var currentFrameIndex: Int {
|
public var currentFrameIndex: Int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func setFrameIndex(_ frameIndex: Int) {
|
public func setFrameIndex(_ frameIndex: Int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
extension ManagedDiceAnimationNode: GenericAnimatedStickerNode {
|
||||||
let contextSourceNode: ContextExtractedContentContainingNode
|
}
|
||||||
|
|
||||||
|
public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||||
|
public let contextSourceNode: ContextExtractedContentContainingNode
|
||||||
private let containerNode: ContextControllerSourceNode
|
private let containerNode: ContextControllerSourceNode
|
||||||
let imageNode: TransformImageNode
|
public let imageNode: TransformImageNode
|
||||||
private var enableSynchronousImageApply: Bool = false
|
private var enableSynchronousImageApply: Bool = false
|
||||||
private var backgroundNode: WallpaperBubbleBackgroundNode?
|
private var backgroundNode: WallpaperBubbleBackgroundNode?
|
||||||
private(set) var placeholderNode: StickerShimmerEffectNode
|
public private(set) var placeholderNode: StickerShimmerEffectNode
|
||||||
private(set) var animationNode: GenericAnimatedStickerNode?
|
public private(set) var animationNode: GenericAnimatedStickerNode?
|
||||||
private var animationSize: CGSize?
|
private var animationSize: CGSize?
|
||||||
private var didSetUpAnimationNode = false
|
private var didSetUpAnimationNode = false
|
||||||
private var isPlaying = false
|
private var isPlaying = false
|
||||||
@@ -86,7 +92,6 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
private let textNode: TextNodeWithEntities
|
private let textNode: TextNodeWithEntities
|
||||||
|
|
||||||
private var additionalAnimationNodes: [ChatMessageTransitionNode.DecorationItemNode] = []
|
private var additionalAnimationNodes: [ChatMessageTransitionNode.DecorationItemNode] = []
|
||||||
private var overlayMeshAnimationNode: ChatMessageTransitionNode.DecorationItemNode?
|
|
||||||
private var enqueuedAdditionalAnimations: [(Int, Double)] = []
|
private var enqueuedAdditionalAnimations: [(Int, Double)] = []
|
||||||
private var additionalAnimationsCommitTimer: SwiftSignalKit.Timer?
|
private var additionalAnimationsCommitTimer: SwiftSignalKit.Timer?
|
||||||
|
|
||||||
@@ -97,10 +102,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
private var deliveryFailedNode: ChatMessageDeliveryFailedNode?
|
private var deliveryFailedNode: ChatMessageDeliveryFailedNode?
|
||||||
private var shareButtonNode: ChatMessageShareButton?
|
private var shareButtonNode: ChatMessageShareButton?
|
||||||
|
|
||||||
var telegramFile: TelegramMediaFile?
|
public var telegramFile: TelegramMediaFile?
|
||||||
var emojiFile: TelegramMediaFile?
|
public var emojiFile: TelegramMediaFile?
|
||||||
var telegramDice: TelegramMediaDice?
|
public var telegramDice: TelegramMediaDice?
|
||||||
var emojiString: String?
|
public var emojiString: String?
|
||||||
private let disposable = MetaDisposable()
|
private let disposable = MetaDisposable()
|
||||||
private let disposables = DisposableSet()
|
private let disposables = DisposableSet()
|
||||||
|
|
||||||
@@ -136,7 +141,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
private var wasPending: Bool = false
|
private var wasPending: Bool = false
|
||||||
private var didChangeFromPendingToSent: Bool = false
|
private var didChangeFromPendingToSent: Bool = false
|
||||||
|
|
||||||
required init() {
|
required public init() {
|
||||||
self.contextSourceNode = ContextExtractedContentContainingNode()
|
self.contextSourceNode = ContextExtractedContentContainingNode()
|
||||||
self.containerNode = ContextControllerSourceNode()
|
self.containerNode = ContextControllerSourceNode()
|
||||||
self.imageNode = TransformImageNode()
|
self.imageNode = TransformImageNode()
|
||||||
@@ -233,7 +238,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
self.additionalAnimationsCommitTimer?.invalidate()
|
self.additionalAnimationsCommitTimer?.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
required public init?(coder aDecoder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +253,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func didLoad() {
|
override public func didLoad() {
|
||||||
super.didLoad()
|
super.didLoad()
|
||||||
|
|
||||||
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
||||||
@@ -325,7 +330,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
self.view.addGestureRecognizer(replyRecognizer)
|
self.view.addGestureRecognizer(replyRecognizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override var visibility: ListViewItemNodeVisibility {
|
override public var visibility: ListViewItemNodeVisibility {
|
||||||
didSet {
|
didSet {
|
||||||
let wasVisible = oldValue != .none
|
let wasVisible = oldValue != .none
|
||||||
let isVisible = self.visibility != .none
|
let isVisible = self.visibility != .none
|
||||||
@@ -425,7 +430,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func setupItem(_ item: ChatMessageItem, synchronousLoad: Bool) {
|
override public func setupItem(_ item: ChatMessageItem, synchronousLoad: Bool) {
|
||||||
super.setupItem(item, synchronousLoad: synchronousLoad)
|
super.setupItem(item, synchronousLoad: synchronousLoad)
|
||||||
|
|
||||||
if item.message.id.namespace == Namespaces.Message.Local || item.message.id.namespace == Namespaces.Message.ScheduledLocal {
|
if item.message.id.namespace == Namespaces.Message.Local || item.message.id.namespace == Namespaces.Message.ScheduledLocal {
|
||||||
@@ -587,13 +592,6 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
let isPlaying = self.visibilityStatus == true && !self.forceStopAnimations
|
let isPlaying = self.visibilityStatus == true && !self.forceStopAnimations
|
||||||
if !isPlaying {
|
if !isPlaying {
|
||||||
self.removeAdditionalAnimations()
|
self.removeAdditionalAnimations()
|
||||||
|
|
||||||
if let overlayMeshAnimationNode = self.overlayMeshAnimationNode {
|
|
||||||
self.overlayMeshAnimationNode = nil
|
|
||||||
if let transitionNode = item.controllerInteraction.getMessageTransitionNode() as? ChatMessageTransitionNode {
|
|
||||||
transitionNode.remove(decorationNode: overlayMeshAnimationNode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let animationNode = self.animationNode as? AnimatedStickerNode {
|
if let animationNode = self.animationNode as? AnimatedStickerNode {
|
||||||
if self.isPlaying != isPlaying || (isPlaying && !self.didSetUpAnimationNode) {
|
if self.isPlaying != isPlaying || (isPlaying && !self.didSetUpAnimationNode) {
|
||||||
@@ -663,13 +661,13 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func updateStickerSettings(forceStopAnimations: Bool) {
|
override public func updateStickerSettings(forceStopAnimations: Bool) {
|
||||||
self.forceStopAnimations = forceStopAnimations
|
self.forceStopAnimations = forceStopAnimations
|
||||||
self.updateVisibility()
|
self.updateVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var absoluteRect: (CGRect, CGSize)?
|
private var absoluteRect: (CGRect, CGSize)?
|
||||||
override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
override public func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||||
self.absoluteRect = (rect, containerSize)
|
self.absoluteRect = (rect, containerSize)
|
||||||
if !self.contextSourceNode.isExtractedToContextPreview {
|
if !self.contextSourceNode.isExtractedToContextPreview {
|
||||||
var rect = rect
|
var rect = rect
|
||||||
@@ -723,7 +721,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func applyAbsoluteOffset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) {
|
override public func applyAbsoluteOffset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) {
|
||||||
if let backgroundNode = self.backgroundNode {
|
if let backgroundNode = self.backgroundNode {
|
||||||
backgroundNode.offset(value: value, animationCurve: animationCurve, duration: duration)
|
backgroundNode.offset(value: value, animationCurve: animationCurve, duration: duration)
|
||||||
}
|
}
|
||||||
@@ -733,7 +731,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func updateAccessibilityData(_ accessibilityData: ChatMessageAccessibilityData) {
|
override public func updateAccessibilityData(_ accessibilityData: ChatMessageAccessibilityData) {
|
||||||
super.updateAccessibilityData(accessibilityData)
|
super.updateAccessibilityData(accessibilityData)
|
||||||
|
|
||||||
self.messageAccessibilityArea.accessibilityLabel = accessibilityData.label
|
self.messageAccessibilityArea.accessibilityLabel = accessibilityData.label
|
||||||
@@ -764,7 +762,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, ListViewItemApply, Bool) -> Void) {
|
override public func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, ListViewItemApply, Bool) -> Void) {
|
||||||
var displaySize = CGSize(width: 180.0, height: 180.0)
|
var displaySize = CGSize(width: 180.0, height: 180.0)
|
||||||
let telegramFile = self.telegramFile
|
let telegramFile = self.telegramFile
|
||||||
let emojiFile = self.emojiFile
|
let emojiFile = self.emojiFile
|
||||||
@@ -1761,7 +1759,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
item.controllerInteraction.commitEmojiInteraction(item.message.id, item.message.text.strippedEmoji, EmojiInteraction(animations: animations), file)
|
item.controllerInteraction.commitEmojiInteraction(item.message.id, item.message.text.strippedEmoji, EmojiInteraction(animations: animations), file)
|
||||||
}
|
}
|
||||||
|
|
||||||
func playEmojiInteraction(_ interaction: EmojiInteraction) {
|
public func playEmojiInteraction(_ interaction: EmojiInteraction) {
|
||||||
guard interaction.animations.count <= 7 else {
|
guard interaction.animations.count <= 7 else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1807,7 +1805,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func playAdditionalEmojiAnimation(index: Int) {
|
public func playAdditionalEmojiAnimation(index: Int) {
|
||||||
guard let item = self.item else {
|
guard let item = self.item else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1846,7 +1844,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
self.playEffectAnimation(resource: effect.resource, isStickerEffect: true)
|
self.playEffectAnimation(resource: effect.resource, isStickerEffect: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func playEffectAnimation(resource: MediaResource, isStickerEffect: Bool = false) {
|
public func playEffectAnimation(resource: MediaResource, isStickerEffect: Bool = false) {
|
||||||
guard let item = self.item else {
|
guard let item = self.item else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2282,7 +2280,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var playedSwipeToReplyHaptic = false
|
private var playedSwipeToReplyHaptic = false
|
||||||
@objc func swipeToReplyGesture(_ recognizer: ChatSwipeToReplyRecognizer) {
|
@objc private func swipeToReplyGesture(_ recognizer: ChatSwipeToReplyRecognizer) {
|
||||||
var offset: CGFloat = 0.0
|
var offset: CGFloat = 0.0
|
||||||
var leftOffset: CGFloat = 0.0
|
var leftOffset: CGFloat = 0.0
|
||||||
var swipeOffset: CGFloat = 45.0
|
var swipeOffset: CGFloat = 45.0
|
||||||
@@ -2406,7 +2404,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
if let shareButtonNode = self.shareButtonNode, shareButtonNode.frame.contains(point) {
|
if let shareButtonNode = self.shareButtonNode, shareButtonNode.frame.contains(point) {
|
||||||
return shareButtonNode.view
|
return shareButtonNode.view
|
||||||
}
|
}
|
||||||
@@ -2421,7 +2419,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
return super.hitTest(point, with: event)
|
return super.hitTest(point, with: event)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func updateSelectionState(animated: Bool) {
|
override public func updateSelectionState(animated: Bool) {
|
||||||
guard let item = self.item else {
|
guard let item = self.item else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2503,7 +2501,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func updateHighlightedState(animated: Bool) {
|
override public func updateHighlightedState(animated: Bool) {
|
||||||
super.updateHighlightedState(animated: animated)
|
super.updateHighlightedState(animated: animated)
|
||||||
|
|
||||||
if let item = self.item {
|
if let item = self.item {
|
||||||
@@ -2528,11 +2526,11 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func cancelInsertionAnimations() {
|
override public func cancelInsertionAnimations() {
|
||||||
self.layer.removeAllAnimations()
|
self.layer.removeAllAnimations()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
|
override public func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
|
||||||
super.animateInsertion(currentTimestamp, duration: duration, short: short)
|
super.animateInsertion(currentTimestamp, duration: duration, short: short)
|
||||||
|
|
||||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
@@ -2550,27 +2548,41 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
override public func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||||
super.animateRemoved(currentTimestamp, duration: duration)
|
super.animateRemoved(currentTimestamp, duration: duration)
|
||||||
|
|
||||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
override public func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
||||||
super.animateAdded(currentTimestamp, duration: duration)
|
super.animateAdded(currentTimestamp, duration: duration)
|
||||||
|
|
||||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func getMessageContextSourceNode(stableId: UInt32?) -> ContextExtractedContentContainingNode? {
|
override public func getMessageContextSourceNode(stableId: UInt32?) -> ContextExtractedContentContainingNode? {
|
||||||
return self.contextSourceNode
|
return self.contextSourceNode
|
||||||
}
|
}
|
||||||
|
|
||||||
override func addAccessoryItemNode(_ accessoryItemNode: ListViewAccessoryItemNode) {
|
override public func addAccessoryItemNode(_ accessoryItemNode: ListViewAccessoryItemNode) {
|
||||||
self.contextSourceNode.contentNode.addSubnode(accessoryItemNode)
|
self.contextSourceNode.contentNode.addSubnode(accessoryItemNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class AnimationTransitionTextInput {
|
||||||
|
public let backgroundView: UIView
|
||||||
|
public let contentView: UIView
|
||||||
|
public let sourceRect: CGRect
|
||||||
|
public let scrollOffset: CGFloat
|
||||||
|
|
||||||
func animateContentFromTextInputField(textInput: ChatMessageTransitionNode.Source.TextInput, transition: CombinedTransition) {
|
public init(backgroundView: UIView, contentView: UIView, sourceRect: CGRect, scrollOffset: CGFloat) {
|
||||||
|
self.backgroundView = backgroundView
|
||||||
|
self.contentView = contentView
|
||||||
|
self.sourceRect = sourceRect
|
||||||
|
self.scrollOffset = scrollOffset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func animateContentFromTextInputField(textInput: AnimationTransitionTextInput, transition: CombinedTransition) {
|
||||||
guard let _ = self.item else {
|
guard let _ = self.item else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2629,8 +2641,56 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
|
|
||||||
self.dateAndStatusNode.layer.animateAlpha(from: 0.0, to: self.dateAndStatusNode.alpha, duration: 0.15, delay: 0.16)
|
self.dateAndStatusNode.layer.animateAlpha(from: 0.0, to: self.dateAndStatusNode.alpha, duration: 0.15, delay: 0.16)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class AnimationTransitionSticker {
|
||||||
|
public let imageNode: TransformImageNode?
|
||||||
|
public let animationNode: ASDisplayNode?
|
||||||
|
public let placeholderNode: ASDisplayNode?
|
||||||
|
public let imageLayer: CALayer?
|
||||||
|
public let relativeSourceRect: CGRect
|
||||||
|
|
||||||
|
var sourceFrame: CGRect {
|
||||||
|
if let imageNode = self.imageNode {
|
||||||
|
return imageNode.frame
|
||||||
|
} else if let imageLayer = self.imageLayer {
|
||||||
|
return imageLayer.bounds
|
||||||
|
} else {
|
||||||
|
return CGRect(origin: CGPoint(), size: relativeSourceRect.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sourceLayer: CALayer? {
|
||||||
|
if let imageNode = self.imageNode {
|
||||||
|
return imageNode.layer
|
||||||
|
} else if let imageLayer = self.imageLayer {
|
||||||
|
return imageLayer
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func snapshotContentTree() -> UIView? {
|
||||||
|
if let animationNode = self.animationNode {
|
||||||
|
return animationNode.view.snapshotContentTree()
|
||||||
|
} else if let imageNode = self.imageNode {
|
||||||
|
return imageNode.view.snapshotContentTree()
|
||||||
|
} else if let sourceLayer = self.imageLayer {
|
||||||
|
return sourceLayer.snapshotContentTreeAsView()
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(imageNode: TransformImageNode?, animationNode: ASDisplayNode?, placeholderNode: ASDisplayNode?, imageLayer: CALayer?, relativeSourceRect: CGRect) {
|
||||||
|
self.imageNode = imageNode
|
||||||
|
self.animationNode = animationNode
|
||||||
|
self.placeholderNode = placeholderNode
|
||||||
|
self.imageLayer = imageLayer
|
||||||
|
self.relativeSourceRect = relativeSourceRect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func animateContentFromStickerGridItem(stickerSource: ChatMessageTransitionNode.Sticker, transition: CombinedTransition) {
|
public func animateContentFromStickerGridItem(stickerSource: AnimationTransitionSticker, transition: CombinedTransition) {
|
||||||
guard let _ = self.item else {
|
guard let _ = self.item else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2716,8 +2776,26 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
placeholderNode.layer.animateAlpha(from: 0.0, to: placeholderNode.alpha, duration: 0.4)
|
placeholderNode.layer.animateAlpha(from: 0.0, to: placeholderNode.alpha, duration: 0.4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class AnimationTransitionReplyPanel {
|
||||||
|
public let titleNode: ASDisplayNode
|
||||||
|
public let textNode: ASDisplayNode
|
||||||
|
public let lineNode: ASDisplayNode
|
||||||
|
public let imageNode: ASDisplayNode
|
||||||
|
public let relativeSourceRect: CGRect
|
||||||
|
public let relativeTargetRect: CGRect
|
||||||
|
|
||||||
func animateReplyPanel(sourceReplyPanel: ChatMessageTransitionNode.ReplyPanel, transition: CombinedTransition) {
|
public init(titleNode: ASDisplayNode, textNode: ASDisplayNode, lineNode: ASDisplayNode, imageNode: ASDisplayNode, relativeSourceRect: CGRect, relativeTargetRect: CGRect) {
|
||||||
|
self.titleNode = titleNode
|
||||||
|
self.textNode = textNode
|
||||||
|
self.lineNode = lineNode
|
||||||
|
self.imageNode = imageNode
|
||||||
|
self.relativeSourceRect = relativeSourceRect
|
||||||
|
self.relativeTargetRect = relativeTargetRect
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func animateReplyPanel(sourceReplyPanel: AnimationTransitionReplyPanel, transition: CombinedTransition) {
|
||||||
if let replyInfoNode = self.replyInfoNode {
|
if let replyInfoNode = self.replyInfoNode {
|
||||||
let localRect = self.contextSourceNode.contentNode.view.convert(sourceReplyPanel.relativeSourceRect, to: replyInfoNode.view)
|
let localRect = self.contextSourceNode.contentNode.view.convert(sourceReplyPanel.relativeSourceRect, to: replyInfoNode.view)
|
||||||
|
|
||||||
@@ -2737,7 +2815,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateFromLoadingPlaceholder(delay: Double, transition: ContainedViewLayoutTransition) {
|
public func animateFromLoadingPlaceholder(delay: Double, transition: ContainedViewLayoutTransition) {
|
||||||
guard let item = self.item else {
|
guard let item = self.item else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -2747,14 +2825,14 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
transition.animateTransformScale(node: self, from: CGPoint(x: 0.85, y: 0.85), delay: delay)
|
transition.animateTransformScale(node: self, from: CGPoint(x: 0.85, y: 0.85), delay: delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func openMessageContextMenu() {
|
override public func openMessageContextMenu() {
|
||||||
guard let item = self.item else {
|
guard let item = self.item else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
item.controllerInteraction.openMessageContextMenu(item.message, false, self, self.imageNode.frame, nil, nil)
|
item.controllerInteraction.openMessageContextMenu(item.message, false, self, self.imageNode.frame, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func targetReactionView(value: MessageReaction.Reaction) -> UIView? {
|
override public func targetReactionView(value: MessageReaction.Reaction) -> UIView? {
|
||||||
if let result = self.reactionButtonsNode?.reactionTargetView(value: value) {
|
if let result = self.reactionButtonsNode?.reactionTargetView(value: value) {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -2764,7 +2842,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
override func targetForStoryTransition(id: StoryId) -> UIView? {
|
override public func targetForStoryTransition(id: StoryId) -> UIView? {
|
||||||
guard let item = self.item else {
|
guard let item = self.item else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -2780,17 +2858,17 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
override func unreadMessageRangeUpdated() {
|
override public func unreadMessageRangeUpdated() {
|
||||||
self.updateVisibility()
|
self.updateVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func contentFrame() -> CGRect {
|
override public func contentFrame() -> CGRect {
|
||||||
return self.imageNode.frame
|
return self.imageNode.frame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AnimatedEmojiSoundsConfiguration {
|
public struct AnimatedEmojiSoundsConfiguration {
|
||||||
static var defaultValue: AnimatedEmojiSoundsConfiguration {
|
public static var defaultValue: AnimatedEmojiSoundsConfiguration {
|
||||||
return AnimatedEmojiSoundsConfiguration(sounds: [:])
|
return AnimatedEmojiSoundsConfiguration(sounds: [:])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2800,7 +2878,7 @@ struct AnimatedEmojiSoundsConfiguration {
|
|||||||
self.sounds = sounds
|
self.sounds = sounds
|
||||||
}
|
}
|
||||||
|
|
||||||
static func with(appConfiguration: AppConfiguration, account: Account) -> AnimatedEmojiSoundsConfiguration {
|
public static func with(appConfiguration: AppConfiguration, account: Account) -> AnimatedEmojiSoundsConfiguration {
|
||||||
if let data = appConfiguration.data, let values = data["emojies_sounds"] as? [String: Any] {
|
if let data = appConfiguration.data, let values = data["emojies_sounds"] as? [String: Any] {
|
||||||
var sounds: [String: TelegramMediaFile] = [:]
|
var sounds: [String: TelegramMediaFile] = [:]
|
||||||
for (key, value) in values {
|
for (key, value) in values {
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
|
swift_library(
|
||||||
|
name = "ChatMessageTransitionNode",
|
||||||
|
module_name = "ChatMessageTransitionNode",
|
||||||
|
srcs = glob([
|
||||||
|
"Sources/**/*.swift",
|
||||||
|
]),
|
||||||
|
copts = [
|
||||||
|
"-warnings-as-errors",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//submodules/AsyncDisplayKit",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageItemView",
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
|
)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import ChatMessageItemView
|
||||||
|
import AsyncDisplayKit
|
||||||
|
|
||||||
|
public protocol ChatMessageTransitionNodeDecorationItemNode: ASDisplayNode {
|
||||||
|
var contentView: UIView { get }
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol ChatMessageTransitionNode: AnyObject {
|
||||||
|
typealias DecorationItemNode = ChatMessageTransitionNodeDecorationItemNode
|
||||||
|
|
||||||
|
func add(decorationView: UIView, itemNode: ChatMessageItemView) -> DecorationItemNode
|
||||||
|
func remove(decorationNode: DecorationItemNode)
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
|
swift_library(
|
||||||
|
name = "ManagedDiceAnimationNode",
|
||||||
|
module_name = "ManagedDiceAnimationNode",
|
||||||
|
srcs = glob([
|
||||||
|
"Sources/**/*.swift",
|
||||||
|
]),
|
||||||
|
copts = [
|
||||||
|
"-warnings-as-errors",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//submodules/Display",
|
||||||
|
"//submodules/AsyncDisplayKit",
|
||||||
|
"//submodules/Postbox",
|
||||||
|
"//submodules/TelegramCore",
|
||||||
|
"//submodules/SSignalKit/SwiftSignalKit",
|
||||||
|
"//submodules/AccountContext",
|
||||||
|
"//submodules/StickerResources",
|
||||||
|
"//submodules/ManagedAnimationNode",
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
|
)
|
||||||
@@ -8,7 +8,7 @@ import AccountContext
|
|||||||
import StickerResources
|
import StickerResources
|
||||||
import ManagedAnimationNode
|
import ManagedAnimationNode
|
||||||
|
|
||||||
enum ManagedDiceAnimationState: Equatable {
|
public enum ManagedDiceAnimationState: Equatable {
|
||||||
case rolling
|
case rolling
|
||||||
case value(Int32, Bool)
|
case value(Int32, Bool)
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ private struct InteractiveEmojiSuccessParameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct InteractiveEmojiConfiguration {
|
public struct InteractiveEmojiConfiguration {
|
||||||
static var defaultValue: InteractiveEmojiConfiguration {
|
public static var defaultValue: InteractiveEmojiConfiguration {
|
||||||
return InteractiveEmojiConfiguration(emojis: [], successParameters: [:])
|
return InteractiveEmojiConfiguration(emojis: [], successParameters: [:])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ public struct InteractiveEmojiConfiguration {
|
|||||||
self.successParameters = successParameters
|
self.successParameters = successParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
static func with(appConfiguration: AppConfiguration) -> InteractiveEmojiConfiguration {
|
public static func with(appConfiguration: AppConfiguration) -> InteractiveEmojiConfiguration {
|
||||||
if let data = appConfiguration.data, let emojis = data["emojies_send_dice"] as? [String] {
|
if let data = appConfiguration.data, let emojis = data["emojies_send_dice"] as? [String] {
|
||||||
var successParameters: [String: InteractiveEmojiSuccessParameters] = [:]
|
var successParameters: [String: InteractiveEmojiSuccessParameters] = [:]
|
||||||
if let success = data["emojies_send_dice_success"] as? [String: [String: Double]] {
|
if let success = data["emojies_send_dice_success"] as? [String: [String: Double]] {
|
||||||
@@ -115,7 +115,7 @@ public struct InteractiveEmojiConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ManagedDiceAnimationNode: ManagedAnimationNode, GenericAnimatedStickerNode {
|
public final class ManagedDiceAnimationNode: ManagedAnimationNode {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let emoji: String
|
private let emoji: String
|
||||||
|
|
||||||
@@ -125,9 +125,9 @@ final class ManagedDiceAnimationNode: ManagedAnimationNode, GenericAnimatedStick
|
|||||||
private let configuration = Promise<InteractiveEmojiConfiguration?>()
|
private let configuration = Promise<InteractiveEmojiConfiguration?>()
|
||||||
private let emojis = Promise<[TelegramMediaFile]>()
|
private let emojis = Promise<[TelegramMediaFile]>()
|
||||||
|
|
||||||
var success: (() -> Void)?
|
public var success: (() -> Void)?
|
||||||
|
|
||||||
init(context: AccountContext, emoji: String) {
|
public init(context: AccountContext, emoji: String) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.emoji = emoji
|
self.emoji = emoji
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ final class ManagedDiceAnimationNode: ManagedAnimationNode, GenericAnimatedStick
|
|||||||
self.disposable.dispose()
|
self.disposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setState(_ diceState: ManagedDiceAnimationState) {
|
public func setState(_ diceState: ManagedDiceAnimationState) {
|
||||||
let previousState = self.diceState
|
let previousState = self.diceState
|
||||||
self.diceState = diceState
|
self.diceState = diceState
|
||||||
|
|
||||||
@@ -203,13 +203,13 @@ final class ManagedDiceAnimationNode: ManagedAnimationNode, GenericAnimatedStick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setOverlayColor(_ color: UIColor?, replace: Bool, animated: Bool) {
|
public func setOverlayColor(_ color: UIColor?, replace: Bool, animated: Bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setFrameIndex(_ frameIndex: Int) {
|
public func setFrameIndex(_ frameIndex: Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentFrameIndex: Int {
|
public var currentFrameIndex: Int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
19
submodules/TelegramUI/Components/Chat/MessageHaptics/BUILD
Normal file
19
submodules/TelegramUI/Components/Chat/MessageHaptics/BUILD
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
|
swift_library(
|
||||||
|
name = "MessageHaptics",
|
||||||
|
module_name = "MessageHaptics",
|
||||||
|
srcs = glob([
|
||||||
|
"Sources/**/*.swift",
|
||||||
|
]),
|
||||||
|
copts = [
|
||||||
|
"-warnings-as-errors",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//submodules/Display",
|
||||||
|
"//submodules/SSignalKit/SwiftSignalKit",
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
|
)
|
||||||
@@ -5,11 +5,11 @@ import SwiftSignalKit
|
|||||||
private let firstImpactTime: Double = 0.4
|
private let firstImpactTime: Double = 0.4
|
||||||
private let secondImpactTime: Double = 0.6
|
private let secondImpactTime: Double = 0.6
|
||||||
|
|
||||||
final class CoffinHaptic: EmojiHaptic {
|
public final class CoffinHaptic: EmojiHaptic {
|
||||||
private var hapticFeedback = HapticFeedback()
|
private var hapticFeedback = HapticFeedback()
|
||||||
private var timer: SwiftSignalKit.Timer?
|
private var timer: SwiftSignalKit.Timer?
|
||||||
private var time: Double = 0.0
|
private var time: Double = 0.0
|
||||||
var enabled: Bool = false {
|
public var enabled: Bool = false {
|
||||||
didSet {
|
didSet {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
self.reset()
|
self.reset()
|
||||||
@@ -17,9 +17,12 @@ final class CoffinHaptic: EmojiHaptic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var active: Bool {
|
public var active: Bool {
|
||||||
return self.timer != nil
|
return self.timer != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
}
|
||||||
|
|
||||||
private func reset() {
|
private func reset() {
|
||||||
if let timer = self.timer {
|
if let timer = self.timer {
|
||||||
@@ -36,7 +39,7 @@ final class CoffinHaptic: EmojiHaptic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func start(time: Double) {
|
public func start(time: Double) {
|
||||||
self.hapticFeedback.prepareImpact()
|
self.hapticFeedback.prepareImpact()
|
||||||
|
|
||||||
if time > firstImpactTime {
|
if time > firstImpactTime {
|
||||||
@@ -2,18 +2,18 @@ import Foundation
|
|||||||
import Display
|
import Display
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
|
|
||||||
protocol EmojiHaptic {
|
public protocol EmojiHaptic {
|
||||||
var enabled: Bool { get set }
|
var enabled: Bool { get set }
|
||||||
var active: Bool { get }
|
var active: Bool { get }
|
||||||
|
|
||||||
func start(time: Double)
|
func start(time: Double)
|
||||||
}
|
}
|
||||||
|
|
||||||
final class HeartbeatHaptic: EmojiHaptic {
|
public final class HeartbeatHaptic: EmojiHaptic {
|
||||||
private var hapticFeedback = HapticFeedback()
|
private var hapticFeedback = HapticFeedback()
|
||||||
private var timer: SwiftSignalKit.Timer?
|
private var timer: SwiftSignalKit.Timer?
|
||||||
private var time: Double = 0.0
|
private var time: Double = 0.0
|
||||||
var enabled: Bool = false {
|
public var enabled: Bool = false {
|
||||||
didSet {
|
didSet {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
self.reset()
|
self.reset()
|
||||||
@@ -21,9 +21,12 @@ final class HeartbeatHaptic: EmojiHaptic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var active: Bool {
|
public var active: Bool {
|
||||||
return self.timer != nil
|
return self.timer != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
}
|
||||||
|
|
||||||
private func reset() {
|
private func reset() {
|
||||||
if let timer = self.timer {
|
if let timer = self.timer {
|
||||||
@@ -42,7 +45,7 @@ final class HeartbeatHaptic: EmojiHaptic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func start(time: Double) {
|
public func start(time: Double) {
|
||||||
self.hapticFeedback.prepareImpact()
|
self.hapticFeedback.prepareImpact()
|
||||||
|
|
||||||
if time > 2.0 {
|
if time > 2.0 {
|
||||||
@@ -4,11 +4,11 @@ import SwiftSignalKit
|
|||||||
|
|
||||||
private let impactTime: Double = 0.6
|
private let impactTime: Double = 0.6
|
||||||
|
|
||||||
final class PeachHaptic: EmojiHaptic {
|
public final class PeachHaptic: EmojiHaptic {
|
||||||
private var hapticFeedback = HapticFeedback()
|
private var hapticFeedback = HapticFeedback()
|
||||||
private var timer: SwiftSignalKit.Timer?
|
private var timer: SwiftSignalKit.Timer?
|
||||||
private var time: Double = 0.0
|
private var time: Double = 0.0
|
||||||
var enabled: Bool = false {
|
public var enabled: Bool = false {
|
||||||
didSet {
|
didSet {
|
||||||
if !self.enabled {
|
if !self.enabled {
|
||||||
self.reset()
|
self.reset()
|
||||||
@@ -16,9 +16,12 @@ final class PeachHaptic: EmojiHaptic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var active: Bool {
|
public var active: Bool {
|
||||||
return self.timer != nil
|
return self.timer != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
}
|
||||||
|
|
||||||
private func reset() {
|
private func reset() {
|
||||||
if let timer = self.timer {
|
if let timer = self.timer {
|
||||||
@@ -35,7 +38,7 @@ final class PeachHaptic: EmojiHaptic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func start(time: Double) {
|
public func start(time: Double) {
|
||||||
self.hapticFeedback.prepareImpact()
|
self.hapticFeedback.prepareImpact()
|
||||||
|
|
||||||
if time > impactTime {
|
if time > impactTime {
|
||||||
@@ -110,6 +110,7 @@ import ChatMessagePollBubbleContentNode
|
|||||||
import ChatMessageItem
|
import ChatMessageItem
|
||||||
import ChatMessageItemView
|
import ChatMessageItemView
|
||||||
import ChatMessageItemCommon
|
import ChatMessageItemCommon
|
||||||
|
import ChatMessageAnimatedStickerItemNode
|
||||||
|
|
||||||
public enum ChatControllerPeekActions {
|
public enum ChatControllerPeekActions {
|
||||||
case standard
|
case standard
|
||||||
@@ -8089,9 +8090,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
} else {
|
} else {
|
||||||
isScheduledMessages = false
|
isScheduledMessages = false
|
||||||
}
|
}
|
||||||
let duration: Double = strongSelf.chatDisplayNode.messageTransitionNode.hasScheduledTransitions ? ChatMessageTransitionNode.animationDuration : 0.18
|
let duration: Double = strongSelf.chatDisplayNode.messageTransitionNode.hasScheduledTransitions ? ChatMessageTransitionNodeImpl.animationDuration : 0.18
|
||||||
let curve: ContainedViewLayoutTransitionCurve = strongSelf.chatDisplayNode.messageTransitionNode.hasScheduledTransitions ? ChatMessageTransitionNode.verticalAnimationCurve : .easeInOut
|
let curve: ContainedViewLayoutTransitionCurve = strongSelf.chatDisplayNode.messageTransitionNode.hasScheduledTransitions ? ChatMessageTransitionNodeImpl.verticalAnimationCurve : .easeInOut
|
||||||
let controlPoints: (Float, Float, Float, Float) = strongSelf.chatDisplayNode.messageTransitionNode.hasScheduledTransitions ? ChatMessageTransitionNode.verticalAnimationControlPoints : (0.5, 0.33, 0.0, 0.0)
|
let controlPoints: (Float, Float, Float, Float) = strongSelf.chatDisplayNode.messageTransitionNode.hasScheduledTransitions ? ChatMessageTransitionNodeImpl.verticalAnimationControlPoints : (0.5, 0.33, 0.0, 0.0)
|
||||||
|
|
||||||
let shouldUseFastMessageSendAnimation = strongSelf.chatDisplayNode.shouldUseFastMessageSendAnimation
|
let shouldUseFastMessageSendAnimation = strongSelf.chatDisplayNode.shouldUseFastMessageSendAnimation
|
||||||
|
|
||||||
@@ -15533,15 +15534,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
if addedTransitions.count > 1 {
|
if addedTransitions.count > 1 {
|
||||||
var transitions: [(Int64, ChatMessageTransitionNode.Source, () -> Void)] = []
|
var transitions: [(Int64, ChatMessageTransitionNodeImpl.Source, () -> Void)] = []
|
||||||
for (correlationId, uniqueIds, initiated) in addedTransitions {
|
for (correlationId, uniqueIds, initiated) in addedTransitions {
|
||||||
var source: ChatMessageTransitionNode.Source?
|
var source: ChatMessageTransitionNodeImpl.Source?
|
||||||
if uniqueIds.count > 1 {
|
if uniqueIds.count > 1 {
|
||||||
source = .groupedMediaInput(ChatMessageTransitionNode.Source.GroupedMediaInput(extractSnapshots: {
|
source = .groupedMediaInput(ChatMessageTransitionNodeImpl.Source.GroupedMediaInput(extractSnapshots: {
|
||||||
return uniqueIds.compactMap({ getAnimatedTransitionSource?($0) })
|
return uniqueIds.compactMap({ getAnimatedTransitionSource?($0) })
|
||||||
}))
|
}))
|
||||||
} else if let uniqueId = uniqueIds.first {
|
} else if let uniqueId = uniqueIds.first {
|
||||||
source = .mediaInput(ChatMessageTransitionNode.Source.MediaInput(extractSnapshot: {
|
source = .mediaInput(ChatMessageTransitionNodeImpl.Source.MediaInput(extractSnapshot: {
|
||||||
return getAnimatedTransitionSource?(uniqueId)
|
return getAnimatedTransitionSource?(uniqueId)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -15551,13 +15552,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
strongSelf.chatDisplayNode.messageTransitionNode.add(grouped: transitions)
|
strongSelf.chatDisplayNode.messageTransitionNode.add(grouped: transitions)
|
||||||
} else if let (correlationId, uniqueIds, initiated) = addedTransitions.first {
|
} else if let (correlationId, uniqueIds, initiated) = addedTransitions.first {
|
||||||
var source: ChatMessageTransitionNode.Source?
|
var source: ChatMessageTransitionNodeImpl.Source?
|
||||||
if uniqueIds.count > 1 {
|
if uniqueIds.count > 1 {
|
||||||
source = .groupedMediaInput(ChatMessageTransitionNode.Source.GroupedMediaInput(extractSnapshots: {
|
source = .groupedMediaInput(ChatMessageTransitionNodeImpl.Source.GroupedMediaInput(extractSnapshots: {
|
||||||
return uniqueIds.compactMap({ getAnimatedTransitionSource?($0) })
|
return uniqueIds.compactMap({ getAnimatedTransitionSource?($0) })
|
||||||
}))
|
}))
|
||||||
} else if let uniqueId = uniqueIds.first {
|
} else if let uniqueId = uniqueIds.first {
|
||||||
source = .mediaInput(ChatMessageTransitionNode.Source.MediaInput(extractSnapshot: {
|
source = .mediaInput(ChatMessageTransitionNodeImpl.Source.MediaInput(extractSnapshot: {
|
||||||
return getAnimatedTransitionSource?(uniqueId)
|
return getAnimatedTransitionSource?(uniqueId)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -15825,7 +15826,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
if strongSelf.chatDisplayNode.shouldAnimateMessageTransition, let extractedView = videoController.extractVideoSnapshot() {
|
if strongSelf.chatDisplayNode.shouldAnimateMessageTransition, let extractedView = videoController.extractVideoSnapshot() {
|
||||||
usedCorrelationId = true
|
usedCorrelationId = true
|
||||||
strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .videoMessage(ChatMessageTransitionNode.Source.VideoMessage(view: extractedView)), initiated: { [weak videoController] in
|
strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .videoMessage(ChatMessageTransitionNodeImpl.Source.VideoMessage(view: extractedView)), initiated: { [weak videoController] in
|
||||||
videoController?.hideVideoSnapshot()
|
videoController?.hideVideoSnapshot()
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@@ -15937,7 +15938,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
if strongSelf.chatDisplayNode.shouldAnimateMessageTransition, let textInputPanelNode = strongSelf.chatDisplayNode.textInputPanelNode, let micButton = textInputPanelNode.micButton {
|
if strongSelf.chatDisplayNode.shouldAnimateMessageTransition, let textInputPanelNode = strongSelf.chatDisplayNode.textInputPanelNode, let micButton = textInputPanelNode.micButton {
|
||||||
usedCorrelationId = true
|
usedCorrelationId = true
|
||||||
strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .audioMicInput(ChatMessageTransitionNode.Source.AudioMicInput(micButton: micButton)), initiated: {
|
strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .audioMicInput(ChatMessageTransitionNodeImpl.Source.AudioMicInput(micButton: micButton)), initiated: {
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import TextSelectionNode
|
|||||||
import ReplyAccessoryPanelNode
|
import ReplyAccessoryPanelNode
|
||||||
import ChatMessageItemView
|
import ChatMessageItemView
|
||||||
import ChatMessageSelectionNode
|
import ChatMessageSelectionNode
|
||||||
|
import ManagedDiceAnimationNode
|
||||||
|
import ChatMessageTransitionNode
|
||||||
|
|
||||||
final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem {
|
final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem {
|
||||||
let itemNode: OverlayMediaItemNode
|
let itemNode: OverlayMediaItemNode
|
||||||
@@ -267,7 +269,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
|
|
||||||
private var dropDimNode: ASDisplayNode?
|
private var dropDimNode: ASDisplayNode?
|
||||||
|
|
||||||
let messageTransitionNode: ChatMessageTransitionNode
|
let messageTransitionNode: ChatMessageTransitionNodeImpl
|
||||||
|
|
||||||
private let presentationContextMarker = ASDisplayNode()
|
private let presentationContextMarker = ASDisplayNode()
|
||||||
|
|
||||||
@@ -589,7 +591,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
source = .default
|
source = .default
|
||||||
}
|
}
|
||||||
|
|
||||||
var getMessageTransitionNode: (() -> ChatMessageTransitionNode?)?
|
var getMessageTransitionNode: (() -> ChatMessageTransitionNodeImpl?)?
|
||||||
self.historyNode = ChatHistoryListNode(context: context, updatedPresentationData: controller?.updatedPresentationData ?? (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, tagMask: nil, source: source, subject: subject, controllerInteraction: controllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), messageTransitionNode: {
|
self.historyNode = ChatHistoryListNode(context: context, updatedPresentationData: controller?.updatedPresentationData ?? (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, tagMask: nil, source: source, subject: subject, controllerInteraction: controllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), messageTransitionNode: {
|
||||||
return getMessageTransitionNode?()
|
return getMessageTransitionNode?()
|
||||||
})
|
})
|
||||||
@@ -605,7 +607,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
|
|
||||||
var getContentAreaInScreenSpaceImpl: (() -> CGRect)?
|
var getContentAreaInScreenSpaceImpl: (() -> CGRect)?
|
||||||
var onTransitionEventImpl: ((ContainedViewLayoutTransition) -> Void)?
|
var onTransitionEventImpl: ((ContainedViewLayoutTransition) -> Void)?
|
||||||
self.messageTransitionNode = ChatMessageTransitionNode(listNode: self.historyNode, getContentAreaInScreenSpace: {
|
self.messageTransitionNode = ChatMessageTransitionNodeImpl(listNode: self.historyNode, getContentAreaInScreenSpace: {
|
||||||
return getContentAreaInScreenSpaceImpl?() ?? CGRect()
|
return getContentAreaInScreenSpaceImpl?() ?? CGRect()
|
||||||
}, onTransitionEvent: { transition in
|
}, onTransitionEvent: { transition in
|
||||||
onTransitionEventImpl?(transition)
|
onTransitionEventImpl?(transition)
|
||||||
@@ -3472,7 +3474,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
if self.shouldAnimateMessageTransition, let inputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode, let textInput = inputPanelNode.makeSnapshotForTransition() {
|
if self.shouldAnimateMessageTransition, let inputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode, let textInput = inputPanelNode.makeSnapshotForTransition() {
|
||||||
usedCorrelationId = correlationId
|
usedCorrelationId = correlationId
|
||||||
let source: ChatMessageTransitionNode.Source = .textInput(textInput: textInput, replyPanel: replyPanel)
|
let source: ChatMessageTransitionNodeImpl.Source = .textInput(textInput: textInput, replyPanel: replyPanel)
|
||||||
self.messageTransitionNode.add(correlationId: correlationId, source: source, initiated: {
|
self.messageTransitionNode.add(correlationId: correlationId, source: source, initiated: {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import ChatOverscrollControl
|
|||||||
import ChatBotInfoItem
|
import ChatBotInfoItem
|
||||||
import ChatMessageItem
|
import ChatMessageItem
|
||||||
import ChatMessageItemView
|
import ChatMessageItemView
|
||||||
|
import ChatMessageTransitionNode
|
||||||
|
|
||||||
struct ChatTopVisibleMessageRange: Equatable {
|
struct ChatTopVisibleMessageRange: Equatable {
|
||||||
var lowerBound: MessageIndex
|
var lowerBound: MessageIndex
|
||||||
@@ -662,7 +663,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
|
|
||||||
private var toLang: String?
|
private var toLang: String?
|
||||||
|
|
||||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>), chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, tagMask: MessageTags?, source: ChatHistoryListSource = .default, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, selectedMessages: Signal<Set<MessageId>?, NoError>, mode: ChatHistoryListMode = .bubbles, messageTransitionNode: @escaping () -> ChatMessageTransitionNode? = { nil }) {
|
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>), chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, tagMask: MessageTags?, source: ChatHistoryListSource = .default, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, selectedMessages: Signal<Set<MessageId>?, NoError>, mode: ChatHistoryListMode = .bubbles, messageTransitionNode: @escaping () -> ChatMessageTransitionNodeImpl? = { nil }) {
|
||||||
var tagMask = tagMask
|
var tagMask = tagMask
|
||||||
if case .pinnedMessages = subject {
|
if case .pinnedMessages = subject {
|
||||||
tagMask = .pinned
|
tagMask = .pinned
|
||||||
@@ -1015,7 +1016,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
|
|
||||||
private func beginChatHistoryTransitions(
|
private func beginChatHistoryTransitions(
|
||||||
selectedMessages: Signal<Set<MessageId>?, NoError>,
|
selectedMessages: Signal<Set<MessageId>?, NoError>,
|
||||||
messageTransitionNode: @escaping () -> ChatMessageTransitionNode?
|
messageTransitionNode: @escaping () -> ChatMessageTransitionNodeImpl?
|
||||||
) {
|
) {
|
||||||
let context = self.context
|
let context = self.context
|
||||||
let chatLocation = self.chatLocation
|
let chatLocation = self.chatLocation
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import ChatMessageItem
|
|||||||
import ChatMessageItemView
|
import ChatMessageItemView
|
||||||
import ChatMessageStickerItemNode
|
import ChatMessageStickerItemNode
|
||||||
import ChatMessageInstantVideoItemNode
|
import ChatMessageInstantVideoItemNode
|
||||||
|
import ChatMessageAnimatedStickerItemNode
|
||||||
|
|
||||||
final class ChatLoadingNode: ASDisplayNode {
|
final class ChatLoadingNode: ASDisplayNode {
|
||||||
private let backgroundNode: NavigationBackgroundNode
|
private let backgroundNode: NavigationBackgroundNode
|
||||||
|
|||||||
@@ -851,7 +851,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
transition.animateTransformScale(node: self, from: CGPoint(x: 0.85, y: 0.85), delay: delay)
|
transition.animateTransformScale(node: self, from: CGPoint(x: 0.85, y: 0.85), delay: delay)
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateContentFromTextInputField(textInput: ChatMessageTransitionNode.Source.TextInput, transition: CombinedTransition) {
|
func animateContentFromTextInputField(textInput: ChatMessageTransitionNodeImpl.Source.TextInput, transition: CombinedTransition) {
|
||||||
let widthDifference = self.backgroundNode.frame.width - textInput.backgroundView.frame.width
|
let widthDifference = self.backgroundNode.frame.width - textInput.backgroundView.frame.width
|
||||||
let heightDifference = self.backgroundNode.frame.height - textInput.backgroundView.frame.height
|
let heightDifference = self.backgroundNode.frame.height - textInput.backgroundView.frame.height
|
||||||
|
|
||||||
@@ -884,7 +884,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateReplyPanel(sourceReplyPanel: ChatMessageTransitionNode.ReplyPanel, transition: CombinedTransition) {
|
func animateReplyPanel(sourceReplyPanel: ChatMessageTransitionNodeImpl.ReplyPanel, transition: CombinedTransition) {
|
||||||
if let replyInfoNode = self.replyInfoNode {
|
if let replyInfoNode = self.replyInfoNode {
|
||||||
let localRect = self.mainContextSourceNode.contentNode.view.convert(sourceReplyPanel.relativeSourceRect, to: replyInfoNode.view)
|
let localRect = self.mainContextSourceNode.contentNode.view.convert(sourceReplyPanel.relativeSourceRect, to: replyInfoNode.view)
|
||||||
let mappedPanel = ChatMessageReplyInfoNode.TransitionReplyPanel(
|
let mappedPanel = ChatMessageReplyInfoNode.TransitionReplyPanel(
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import ChatHistoryEntry
|
|||||||
import ChatMessageItem
|
import ChatMessageItem
|
||||||
import ChatMessageItemView
|
import ChatMessageItemView
|
||||||
import ChatMessageStickerItemNode
|
import ChatMessageStickerItemNode
|
||||||
|
import ChatMessageAnimatedStickerItemNode
|
||||||
|
|
||||||
private func mediaMergeableStyle(_ media: Media) -> ChatMessageMerge {
|
private func mediaMergeableStyle(_ media: Media) -> ChatMessageMerge {
|
||||||
if let story = media as? TelegramMediaStory, story.isMention {
|
if let story = media as? TelegramMediaStory, story.isMention {
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import ReplyAccessoryPanelNode
|
|||||||
import ChatMessageItemView
|
import ChatMessageItemView
|
||||||
import ChatMessageStickerItemNode
|
import ChatMessageStickerItemNode
|
||||||
import ChatMessageInstantVideoItemNode
|
import ChatMessageInstantVideoItemNode
|
||||||
|
import ChatMessageAnimatedStickerItemNode
|
||||||
|
import ChatMessageTransitionNode
|
||||||
|
|
||||||
private func convertAnimatingSourceRect(_ rect: CGRect, fromView: UIView, toView: UIView?) -> CGRect {
|
private func convertAnimatingSourceRect(_ rect: CGRect, fromView: UIView, toView: UIView?) -> CGRect {
|
||||||
if let presentationLayer = fromView.layer.presentation() {
|
if let presentationLayer = fromView.layer.presentation() {
|
||||||
@@ -100,7 +102,7 @@ private final class OverlayTransitionContainerController: ViewController, Standa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransitionProtocol {
|
public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTransitionNode, ChatMessageTransitionProtocol {
|
||||||
static let animationDuration: Double = 0.3
|
static let animationDuration: Double = 0.3
|
||||||
|
|
||||||
static let verticalAnimationControlPoints: (Float, Float, Float, Float) = (0.19919472913616398, 0.010644531250000006, 0.27920937042459737, 0.91025390625)
|
static let verticalAnimationControlPoints: (Float, Float, Float, Float) = (0.19919472913616398, 0.010644531250000006, 0.27920937042459737, 0.91025390625)
|
||||||
@@ -235,7 +237,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
case groupedMediaInput(GroupedMediaInput)
|
case groupedMediaInput(GroupedMediaInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
final class DecorationItemNode: ASDisplayNode {
|
final class DecorationItemNodeImpl: ASDisplayNode, ChatMessageTransitionNode.DecorationItemNode {
|
||||||
let itemNode: ChatMessageItemView
|
let itemNode: ChatMessageItemView
|
||||||
let contentView: UIView
|
let contentView: UIView
|
||||||
private let getContentAreaInScreenSpace: () -> CGRect
|
private let getContentAreaInScreenSpace: () -> CGRect
|
||||||
@@ -288,7 +290,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
private final class AnimatingItemNode: ASDisplayNode {
|
private final class AnimatingItemNode: ASDisplayNode {
|
||||||
let itemNode: ChatMessageItemView
|
let itemNode: ChatMessageItemView
|
||||||
private let contextSourceNode: ContextExtractedContentContainingNode
|
private let contextSourceNode: ContextExtractedContentContainingNode
|
||||||
private let source: ChatMessageTransitionNode.Source
|
private let source: ChatMessageTransitionNodeImpl.Source
|
||||||
private let getContentAreaInScreenSpace: () -> CGRect
|
private let getContentAreaInScreenSpace: () -> CGRect
|
||||||
|
|
||||||
private let scrollingContainer: ASDisplayNode
|
private let scrollingContainer: ASDisplayNode
|
||||||
@@ -300,7 +302,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
var animationEnded: (() -> Void)?
|
var animationEnded: (() -> Void)?
|
||||||
var updateAfterCompletion: Bool = false
|
var updateAfterCompletion: Bool = false
|
||||||
|
|
||||||
init(itemNode: ChatMessageItemView, contextSourceNode: ContextExtractedContentContainingNode, source: ChatMessageTransitionNode.Source, getContentAreaInScreenSpace: @escaping () -> CGRect) {
|
init(itemNode: ChatMessageItemView, contextSourceNode: ContextExtractedContentContainingNode, source: ChatMessageTransitionNodeImpl.Source, getContentAreaInScreenSpace: @escaping () -> CGRect) {
|
||||||
self.itemNode = itemNode
|
self.itemNode = itemNode
|
||||||
self.getContentAreaInScreenSpace = getContentAreaInScreenSpace
|
self.getContentAreaInScreenSpace = getContentAreaInScreenSpace
|
||||||
|
|
||||||
@@ -328,7 +330,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
}
|
}
|
||||||
|
|
||||||
func beginAnimation() {
|
func beginAnimation() {
|
||||||
let verticalDuration: Double = ChatMessageTransitionNode.animationDuration
|
let verticalDuration: Double = ChatMessageTransitionNodeImpl.animationDuration
|
||||||
let horizontalDuration: Double = verticalDuration
|
let horizontalDuration: Double = verticalDuration
|
||||||
let delay: Double = 0.0
|
let delay: Double = 0.0
|
||||||
|
|
||||||
@@ -367,7 +369,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
let sourceBackgroundAbsoluteRect = initialTextInput.backgroundView.frame.offsetBy(dx: sourceRect.minX, dy: sourceRect.minY)
|
let sourceBackgroundAbsoluteRect = initialTextInput.backgroundView.frame.offsetBy(dx: sourceRect.minX, dy: sourceRect.minY)
|
||||||
let sourceAbsoluteRect = CGRect(origin: CGPoint(x: sourceBackgroundAbsoluteRect.minX, y: sourceBackgroundAbsoluteRect.maxY - self.contextSourceNode.contentRect.height), size: self.contextSourceNode.contentRect.size)
|
let sourceAbsoluteRect = CGRect(origin: CGPoint(x: sourceBackgroundAbsoluteRect.minX, y: sourceBackgroundAbsoluteRect.maxY - self.contextSourceNode.contentRect.height), size: self.contextSourceNode.contentRect.size)
|
||||||
|
|
||||||
let textInput = ChatMessageTransitionNode.Source.TextInput(backgroundView: initialTextInput.backgroundView, contentView: initialTextInput.contentView, sourceRect: sourceRect, scrollOffset: initialTextInput.scrollOffset)
|
let textInput = ChatMessageTransitionNodeImpl.Source.TextInput(backgroundView: initialTextInput.backgroundView, contentView: initialTextInput.contentView, sourceRect: sourceRect, scrollOffset: initialTextInput.scrollOffset)
|
||||||
|
|
||||||
textInput.backgroundView.frame = CGRect(origin: CGPoint(x: 0.0, y: sourceAbsoluteRect.height - sourceBackgroundAbsoluteRect.height), size: textInput.backgroundView.bounds.size)
|
textInput.backgroundView.frame = CGRect(origin: CGPoint(x: 0.0, y: sourceAbsoluteRect.height - sourceBackgroundAbsoluteRect.height), size: textInput.backgroundView.bounds.size)
|
||||||
textInput.contentView.frame = textInput.contentView.frame.offsetBy(dx: 0.0, dy: sourceAbsoluteRect.height - sourceBackgroundAbsoluteRect.height)
|
textInput.contentView.frame = textInput.contentView.frame.offsetBy(dx: 0.0, dy: sourceAbsoluteRect.height - sourceBackgroundAbsoluteRect.height)
|
||||||
@@ -390,9 +392,9 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
|
|
||||||
self.itemNode.cancelInsertionAnimations()
|
self.itemNode.cancelInsertionAnimations()
|
||||||
|
|
||||||
let horizontalCurve = ChatMessageTransitionNode.horizontalAnimationCurve
|
let horizontalCurve = ChatMessageTransitionNodeImpl.horizontalAnimationCurve
|
||||||
let horizontalTransition: ContainedViewLayoutTransition = .animated(duration: horizontalDuration, curve: horizontalCurve)
|
let horizontalTransition: ContainedViewLayoutTransition = .animated(duration: horizontalDuration, curve: horizontalCurve)
|
||||||
let verticalCurve = ChatMessageTransitionNode.verticalAnimationCurve
|
let verticalCurve = ChatMessageTransitionNodeImpl.verticalAnimationCurve
|
||||||
let verticalTransition: ContainedViewLayoutTransition = .animated(duration: verticalDuration, curve: verticalCurve)
|
let verticalTransition: ContainedViewLayoutTransition = .animated(duration: verticalDuration, curve: verticalCurve)
|
||||||
|
|
||||||
let combinedTransition = CombinedTransition(horizontal: horizontalTransition, vertical: verticalTransition)
|
let combinedTransition = CombinedTransition(horizontal: horizontalTransition, vertical: verticalTransition)
|
||||||
@@ -415,9 +417,27 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
itemNode.animateReplyPanel(sourceReplyPanel: sourceReplyPanel, transition: combinedTransition)
|
itemNode.animateReplyPanel(sourceReplyPanel: sourceReplyPanel, transition: combinedTransition)
|
||||||
}
|
}
|
||||||
} else if let itemNode = self.itemNode as? ChatMessageAnimatedStickerItemNode {
|
} else if let itemNode = self.itemNode as? ChatMessageAnimatedStickerItemNode {
|
||||||
itemNode.animateContentFromTextInputField(textInput: textInput, transition: combinedTransition)
|
itemNode.animateContentFromTextInputField(
|
||||||
|
textInput: ChatMessageAnimatedStickerItemNode.AnimationTransitionTextInput(
|
||||||
|
backgroundView: textInput.backgroundView,
|
||||||
|
contentView: textInput.contentView,
|
||||||
|
sourceRect: textInput.sourceRect,
|
||||||
|
scrollOffset: textInput.scrollOffset
|
||||||
|
),
|
||||||
|
transition: combinedTransition
|
||||||
|
)
|
||||||
if let sourceReplyPanel = sourceReplyPanel {
|
if let sourceReplyPanel = sourceReplyPanel {
|
||||||
itemNode.animateReplyPanel(sourceReplyPanel: sourceReplyPanel, transition: combinedTransition)
|
itemNode.animateReplyPanel(
|
||||||
|
sourceReplyPanel: ChatMessageAnimatedStickerItemNode.AnimationTransitionReplyPanel(
|
||||||
|
titleNode: sourceReplyPanel.titleNode,
|
||||||
|
textNode: sourceReplyPanel.textNode,
|
||||||
|
lineNode: sourceReplyPanel.lineNode,
|
||||||
|
imageNode: sourceReplyPanel.imageNode,
|
||||||
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
|
),
|
||||||
|
transition: combinedTransition
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else if let itemNode = self.itemNode as? ChatMessageStickerItemNode {
|
} else if let itemNode = self.itemNode as? ChatMessageStickerItemNode {
|
||||||
itemNode.animateContentFromTextInputField(
|
itemNode.animateContentFromTextInputField(
|
||||||
@@ -479,15 +499,34 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
sourceReplyPanel = ReplyPanel(titleNode: replyPanel.titleNode, textNode: replyPanel.textNode, lineNode: replyPanel.lineNode, imageNode: replyPanel.imageNode, relativeSourceRect: replySourceAbsoluteFrame, relativeTargetRect: replySourceAbsoluteFrame.offsetBy(dx: 0.0, dy: replySourceAbsoluteFrame.height))
|
sourceReplyPanel = ReplyPanel(titleNode: replyPanel.titleNode, textNode: replyPanel.textNode, lineNode: replyPanel.lineNode, imageNode: replyPanel.imageNode, relativeSourceRect: replySourceAbsoluteFrame, relativeTargetRect: replySourceAbsoluteFrame.offsetBy(dx: 0.0, dy: replySourceAbsoluteFrame.height))
|
||||||
}
|
}
|
||||||
|
|
||||||
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNode.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNode.verticalAnimationCurve))
|
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNodeImpl.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNodeImpl.verticalAnimationCurve))
|
||||||
|
|
||||||
if let itemNode = self.itemNode as? ChatMessageAnimatedStickerItemNode {
|
if let itemNode = self.itemNode as? ChatMessageAnimatedStickerItemNode {
|
||||||
itemNode.animateContentFromStickerGridItem(stickerSource: stickerSource, transition: combinedTransition)
|
itemNode.animateContentFromStickerGridItem(
|
||||||
|
stickerSource: ChatMessageAnimatedStickerItemNode.AnimationTransitionSticker(
|
||||||
|
imageNode: stickerSource.imageNode,
|
||||||
|
animationNode: stickerSource.animationNode,
|
||||||
|
placeholderNode: stickerSource.placeholderNode,
|
||||||
|
imageLayer: stickerSource.imageLayer,
|
||||||
|
relativeSourceRect: stickerSource.relativeSourceRect
|
||||||
|
),
|
||||||
|
transition: combinedTransition
|
||||||
|
)
|
||||||
if let sourceAnimationNode = stickerSource.animationNode {
|
if let sourceAnimationNode = stickerSource.animationNode {
|
||||||
itemNode.animationNode?.setFrameIndex(sourceAnimationNode.currentFrameIndex)
|
itemNode.animationNode?.setFrameIndex(sourceAnimationNode.currentFrameIndex)
|
||||||
}
|
}
|
||||||
if let sourceReplyPanel = sourceReplyPanel {
|
if let sourceReplyPanel = sourceReplyPanel {
|
||||||
itemNode.animateReplyPanel(sourceReplyPanel: sourceReplyPanel, transition: combinedTransition)
|
itemNode.animateReplyPanel(
|
||||||
|
sourceReplyPanel: ChatMessageAnimatedStickerItemNode.AnimationTransitionReplyPanel(
|
||||||
|
titleNode: sourceReplyPanel.titleNode,
|
||||||
|
textNode: sourceReplyPanel.textNode,
|
||||||
|
lineNode: sourceReplyPanel.lineNode,
|
||||||
|
imageNode: sourceReplyPanel.imageNode,
|
||||||
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
|
),
|
||||||
|
transition: combinedTransition
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else if let itemNode = self.itemNode as? ChatMessageStickerItemNode {
|
} else if let itemNode = self.itemNode as? ChatMessageStickerItemNode {
|
||||||
itemNode.animateContentFromStickerGridItem(
|
itemNode.animateContentFromStickerGridItem(
|
||||||
@@ -517,15 +556,15 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
|
|
||||||
self.containerNode.frame = targetAbsoluteRect.offsetBy(dx: -self.contextSourceNode.contentRect.minX, dy: -self.contextSourceNode.contentRect.minY)
|
self.containerNode.frame = targetAbsoluteRect.offsetBy(dx: -self.contextSourceNode.contentRect.minX, dy: -self.contextSourceNode.contentRect.minY)
|
||||||
self.contextSourceNode.updateAbsoluteRect?(self.containerNode.frame, UIScreen.main.bounds.size)
|
self.contextSourceNode.updateAbsoluteRect?(self.containerNode.frame, UIScreen.main.bounds.size)
|
||||||
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.verticalAnimationCurve.mediaTimingFunction, additive: true, force: true, completion: { [weak self] _ in
|
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNodeImpl.verticalAnimationCurve.mediaTimingFunction, additive: true, force: true, completion: { [weak self] _ in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.endAnimation()
|
strongSelf.endAnimation()
|
||||||
})
|
})
|
||||||
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), ChatMessageTransitionNode.horizontalAnimationCurve, horizontalDuration)
|
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), ChatMessageTransitionNodeImpl.horizontalAnimationCurve, horizontalDuration)
|
||||||
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), ChatMessageTransitionNode.verticalAnimationCurve, verticalDuration)
|
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), ChatMessageTransitionNodeImpl.verticalAnimationCurve, verticalDuration)
|
||||||
self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.horizontalAnimationCurve.mediaTimingFunction, additive: true)
|
self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNodeImpl.horizontalAnimationCurve.mediaTimingFunction, additive: true)
|
||||||
|
|
||||||
switch stickerMediaInput {
|
switch stickerMediaInput {
|
||||||
case .inputPanel, .universal:
|
case .inputPanel, .universal:
|
||||||
@@ -544,7 +583,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
|
|
||||||
container.isHidden = true
|
container.isHidden = true
|
||||||
|
|
||||||
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNode.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNode.verticalAnimationCurve))
|
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNodeImpl.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNodeImpl.verticalAnimationCurve))
|
||||||
|
|
||||||
if let itemNode = self.itemNode as? ChatMessageBubbleItemNode {
|
if let itemNode = self.itemNode as? ChatMessageBubbleItemNode {
|
||||||
if let contextContainer = itemNode.animateFromMicInput(micInputNode: snapshotView, transition: combinedTransition) {
|
if let contextContainer = itemNode.animateFromMicInput(micInputNode: snapshotView, transition: combinedTransition) {
|
||||||
@@ -554,7 +593,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
|
|
||||||
self.containerNode.frame = targetAbsoluteRect.offsetBy(dx: -contextContainer.contentRect.minX, dy: -contextContainer.contentRect.minY)
|
self.containerNode.frame = targetAbsoluteRect.offsetBy(dx: -contextContainer.contentRect.minX, dy: -contextContainer.contentRect.minY)
|
||||||
contextContainer.updateAbsoluteRect?(self.containerNode.frame, UIScreen.main.bounds.size)
|
contextContainer.updateAbsoluteRect?(self.containerNode.frame, UIScreen.main.bounds.size)
|
||||||
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.verticalAnimationCurve.mediaTimingFunction, additive: true, force: true, completion: { [weak self, weak contextContainer, weak container] _ in
|
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNodeImpl.verticalAnimationCurve.mediaTimingFunction, additive: true, force: true, completion: { [weak self, weak contextContainer, weak container] _ in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -569,13 +608,13 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
strongSelf.endAnimation()
|
strongSelf.endAnimation()
|
||||||
})
|
})
|
||||||
|
|
||||||
self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.horizontalAnimationCurve.mediaTimingFunction, additive: true)
|
self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNodeImpl.horizontalAnimationCurve.mediaTimingFunction, additive: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case let .videoMessage(videoMessage):
|
case let .videoMessage(videoMessage):
|
||||||
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNode.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNode.verticalAnimationCurve))
|
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNodeImpl.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNodeImpl.verticalAnimationCurve))
|
||||||
|
|
||||||
if let itemNode = self.itemNode as? ChatMessageInstantVideoItemNode {
|
if let itemNode = self.itemNode as? ChatMessageInstantVideoItemNode {
|
||||||
itemNode.cancelInsertionAnimations()
|
itemNode.cancelInsertionAnimations()
|
||||||
@@ -591,9 +630,9 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
videoMessage.view.frame = videoMessage.view.frame.offsetBy(dx: targetAbsoluteRect.midX - sourceAbsoluteRect.midX, dy: targetAbsoluteRect.midY - sourceAbsoluteRect.midY)
|
videoMessage.view.frame = videoMessage.view.frame.offsetBy(dx: targetAbsoluteRect.midX - sourceAbsoluteRect.midX, dy: targetAbsoluteRect.midY - sourceAbsoluteRect.midY)
|
||||||
|
|
||||||
self.containerNode.frame = targetAbsoluteRect.offsetBy(dx: -self.contextSourceNode.contentRect.minX, dy: -self.contextSourceNode.contentRect.minY)
|
self.containerNode.frame = targetAbsoluteRect.offsetBy(dx: -self.contextSourceNode.contentRect.minX, dy: -self.contextSourceNode.contentRect.minY)
|
||||||
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.horizontalAnimationCurve.mediaTimingFunction, additive: true, force: true)
|
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNodeImpl.horizontalAnimationCurve.mediaTimingFunction, additive: true, force: true)
|
||||||
|
|
||||||
self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.verticalAnimationCurve.mediaTimingFunction, additive: true, completion: { [weak self] _ in
|
self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNodeImpl.verticalAnimationCurve.mediaTimingFunction, additive: true, completion: { [weak self] _ in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -618,7 +657,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
let sourceBackgroundAbsoluteRect = snapshotView.frame
|
let sourceBackgroundAbsoluteRect = snapshotView.frame
|
||||||
let sourceAbsoluteRect = CGRect(origin: CGPoint(x: sourceBackgroundAbsoluteRect.midX - self.contextSourceNode.contentRect.size.width / 2.0, y: sourceBackgroundAbsoluteRect.midY - self.contextSourceNode.contentRect.size.height / 2.0), size: self.contextSourceNode.contentRect.size)
|
let sourceAbsoluteRect = CGRect(origin: CGPoint(x: sourceBackgroundAbsoluteRect.midX - self.contextSourceNode.contentRect.size.width / 2.0, y: sourceBackgroundAbsoluteRect.midY - self.contextSourceNode.contentRect.size.height / 2.0), size: self.contextSourceNode.contentRect.size)
|
||||||
|
|
||||||
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNode.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNode.verticalAnimationCurve))
|
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNodeImpl.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNodeImpl.verticalAnimationCurve))
|
||||||
|
|
||||||
if let itemNode = self.itemNode as? ChatMessageBubbleItemNode {
|
if let itemNode = self.itemNode as? ChatMessageBubbleItemNode {
|
||||||
itemNode.animateContentFromMediaInput(snapshotView: snapshotView, transition: combinedTransition)
|
itemNode.animateContentFromMediaInput(snapshotView: snapshotView, transition: combinedTransition)
|
||||||
@@ -631,8 +670,8 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
|
|
||||||
self.contextSourceNode.updateAbsoluteRect?(self.containerNode.frame, UIScreen.main.bounds.size)
|
self.contextSourceNode.updateAbsoluteRect?(self.containerNode.frame, UIScreen.main.bounds.size)
|
||||||
|
|
||||||
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.horizontalAnimationCurve.mediaTimingFunction, additive: true, force: true)
|
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNodeImpl.horizontalAnimationCurve.mediaTimingFunction, additive: true, force: true)
|
||||||
self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.verticalAnimationCurve.mediaTimingFunction, additive: true, force: true, completion: { [weak self] _ in
|
self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNodeImpl.verticalAnimationCurve.mediaTimingFunction, additive: true, force: true, completion: { [weak self] _ in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -647,8 +686,8 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
snapshotView?.removeFromSuperview()
|
snapshotView?.removeFromSuperview()
|
||||||
})
|
})
|
||||||
|
|
||||||
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: sourceAbsoluteRect.minX - targetAbsoluteRect.minX, y: 0.0), ChatMessageTransitionNode.horizontalAnimationCurve, horizontalDuration)
|
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: sourceAbsoluteRect.minX - targetAbsoluteRect.minX, y: 0.0), ChatMessageTransitionNodeImpl.horizontalAnimationCurve, horizontalDuration)
|
||||||
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: 0.0, y: sourceAbsoluteRect.maxY - targetAbsoluteRect.maxY), ChatMessageTransitionNode.verticalAnimationCurve, verticalDuration)
|
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: 0.0, y: sourceAbsoluteRect.maxY - targetAbsoluteRect.maxY), ChatMessageTransitionNodeImpl.verticalAnimationCurve, verticalDuration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -669,7 +708,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
|
|
||||||
self.containerNode.addSubnode(self.contextSourceNode.contentNode)
|
self.containerNode.addSubnode(self.contextSourceNode.contentNode)
|
||||||
|
|
||||||
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNode.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNode.verticalAnimationCurve))
|
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNodeImpl.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNodeImpl.verticalAnimationCurve))
|
||||||
|
|
||||||
var targetContentRects: [CGRect] = []
|
var targetContentRects: [CGRect] = []
|
||||||
if let itemNode = self.itemNode as? ChatMessageBubbleItemNode {
|
if let itemNode = self.itemNode as? ChatMessageBubbleItemNode {
|
||||||
@@ -709,8 +748,8 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
|
|
||||||
self.contextSourceNode.updateAbsoluteRect?(self.containerNode.frame, UIScreen.main.bounds.size)
|
self.contextSourceNode.updateAbsoluteRect?(self.containerNode.frame, UIScreen.main.bounds.size)
|
||||||
|
|
||||||
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.horizontalAnimationCurve.mediaTimingFunction, additive: true, force: true)
|
self.containerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: sourceAbsoluteRect.midY - targetAbsoluteRect.midY), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNodeImpl.horizontalAnimationCurve.mediaTimingFunction, additive: true, force: true)
|
||||||
self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.verticalAnimationCurve.mediaTimingFunction, additive: true, force: true, completion: { [weak self] _ in
|
self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: verticalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNodeImpl.verticalAnimationCurve.mediaTimingFunction, additive: true, force: true, completion: { [weak self] _ in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -736,8 +775,8 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: sourceAbsoluteRect.minX - targetAbsoluteRect.minX, y: 0.0), ChatMessageTransitionNode.horizontalAnimationCurve, horizontalDuration)
|
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: sourceAbsoluteRect.minX - targetAbsoluteRect.minX, y: 0.0), ChatMessageTransitionNodeImpl.horizontalAnimationCurve, horizontalDuration)
|
||||||
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: 0.0, y: sourceAbsoluteRect.maxY - targetAbsoluteRect.maxY), ChatMessageTransitionNode.verticalAnimationCurve, verticalDuration)
|
self.contextSourceNode.applyAbsoluteOffset?(CGPoint(x: 0.0, y: sourceAbsoluteRect.maxY - targetAbsoluteRect.maxY), ChatMessageTransitionNodeImpl.verticalAnimationCurve, verticalDuration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -838,7 +877,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
private var currentPendingItems: [Int64: (Source, () -> Void)] = [:]
|
private var currentPendingItems: [Int64: (Source, () -> Void)] = [:]
|
||||||
|
|
||||||
private var animatingItemNodes: [AnimatingItemNode] = []
|
private var animatingItemNodes: [AnimatingItemNode] = []
|
||||||
private var decorationItemNodes: [DecorationItemNode] = []
|
private var decorationItemNodes: [DecorationItemNodeImpl] = []
|
||||||
private var messageReactionContexts: [MessageReactionContext] = []
|
private var messageReactionContexts: [MessageReactionContext] = []
|
||||||
|
|
||||||
var hasScheduledTransitions: Bool {
|
var hasScheduledTransitions: Bool {
|
||||||
@@ -891,8 +930,8 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
self.listNode.setCurrentSendAnimationCorrelationIds(correlationIds)
|
self.listNode.setCurrentSendAnimationCorrelationIds(correlationIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(decorationView: UIView, itemNode: ChatMessageItemView) -> DecorationItemNode {
|
public func add(decorationView: UIView, itemNode: ChatMessageItemView) -> DecorationItemNode {
|
||||||
let decorationItemNode = DecorationItemNode(itemNode: itemNode, contentView: decorationView, getContentAreaInScreenSpace: self.getContentAreaInScreenSpace)
|
let decorationItemNode = DecorationItemNodeImpl(itemNode: itemNode, contentView: decorationView, getContentAreaInScreenSpace: self.getContentAreaInScreenSpace)
|
||||||
decorationItemNode.updateLayout(size: self.bounds.size)
|
decorationItemNode.updateLayout(size: self.bounds.size)
|
||||||
|
|
||||||
self.decorationItemNodes.append(decorationItemNode)
|
self.decorationItemNodes.append(decorationItemNode)
|
||||||
@@ -907,10 +946,12 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
return decorationItemNode
|
return decorationItemNode
|
||||||
}
|
}
|
||||||
|
|
||||||
func remove(decorationNode: DecorationItemNode) {
|
public func remove(decorationNode: DecorationItemNode) {
|
||||||
self.decorationItemNodes.removeAll(where: { $0 === decorationNode })
|
self.decorationItemNodes.removeAll(where: { $0 === decorationNode })
|
||||||
decorationNode.removeFromSupernode()
|
decorationNode.removeFromSupernode()
|
||||||
decorationNode.overlayController?.dismiss()
|
if let decorationNode = decorationNode as? DecorationItemNodeImpl {
|
||||||
|
decorationNode.overlayController?.dismiss()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func beginAnimation(itemNode: ChatMessageItemView, source: Source) {
|
private func beginAnimation(itemNode: ChatMessageItemView, source: Source) {
|
||||||
@@ -961,7 +1002,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
|
|||||||
animatingItemNode.frame = self.bounds
|
animatingItemNode.frame = self.bounds
|
||||||
animatingItemNode.beginAnimation()
|
animatingItemNode.beginAnimation()
|
||||||
|
|
||||||
self.onTransitionEvent(.animated(duration: ChatMessageTransitionNode.animationDuration, curve: ChatMessageTransitionNode.verticalAnimationCurve))
|
self.onTransitionEvent(.animated(duration: ChatMessageTransitionNodeImpl.animationDuration, curve: ChatMessageTransitionNodeImpl.verticalAnimationCurve))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4219,7 +4219,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeSnapshotForTransition() -> ChatMessageTransitionNode.Source.TextInput? {
|
func makeSnapshotForTransition() -> ChatMessageTransitionNodeImpl.Source.TextInput? {
|
||||||
guard let backgroundImage = self.transparentTextInputBackgroundImage else {
|
guard let backgroundImage = self.transparentTextInputBackgroundImage else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -4242,7 +4242,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch
|
|||||||
|
|
||||||
contentView.frame = textInputNode.frame
|
contentView.frame = textInputNode.frame
|
||||||
|
|
||||||
return ChatMessageTransitionNode.Source.TextInput(
|
return ChatMessageTransitionNodeImpl.Source.TextInput(
|
||||||
backgroundView: backgroundView,
|
backgroundView: backgroundView,
|
||||||
contentView: contentView,
|
contentView: contentView,
|
||||||
sourceRect: self.view.convert(self.bounds, to: nil),
|
sourceRect: self.view.convert(self.bounds, to: nil),
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import StickerResources
|
|||||||
import Emoji
|
import Emoji
|
||||||
import UniversalMediaPlayer
|
import UniversalMediaPlayer
|
||||||
import ChatMessageInteractiveMediaNode
|
import ChatMessageInteractiveMediaNode
|
||||||
|
import ChatMessageAnimatedStickerItemNode
|
||||||
|
|
||||||
private final class PrefetchMediaContext {
|
private final class PrefetchMediaContext {
|
||||||
let fetchDisposable = MetaDisposable()
|
let fetchDisposable = MetaDisposable()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import AccountContext
|
|||||||
import ChatControllerInteraction
|
import ChatControllerInteraction
|
||||||
import ChatHistoryEntry
|
import ChatHistoryEntry
|
||||||
|
|
||||||
func preparedChatHistoryViewTransition(from fromView: ChatHistoryView?, to toView: ChatHistoryView, reason: ChatHistoryViewTransitionReason, reverse: Bool, chatLocation: ChatLocation, controllerInteraction: ChatControllerInteraction, scrollPosition: ChatHistoryViewScrollPosition?, scrollAnimationCurve: ListViewAnimationCurve?, initialData: InitialMessageHistoryData?, keyboardButtonsMessage: Message?, cachedData: CachedPeerData?, cachedDataMessages: [MessageId: Message]?, readStateData: [PeerId: ChatHistoryCombinedInitialReadStateData]?, flashIndicators: Bool, updatedMessageSelection: Bool, messageTransitionNode: ChatMessageTransitionNode?, allUpdated: Bool) -> ChatHistoryViewTransition {
|
func preparedChatHistoryViewTransition(from fromView: ChatHistoryView?, to toView: ChatHistoryView, reason: ChatHistoryViewTransitionReason, reverse: Bool, chatLocation: ChatLocation, controllerInteraction: ChatControllerInteraction, scrollPosition: ChatHistoryViewScrollPosition?, scrollAnimationCurve: ListViewAnimationCurve?, initialData: InitialMessageHistoryData?, keyboardButtonsMessage: Message?, cachedData: CachedPeerData?, cachedDataMessages: [MessageId: Message]?, readStateData: [PeerId: ChatHistoryCombinedInitialReadStateData]?, flashIndicators: Bool, updatedMessageSelection: Bool, messageTransitionNode: ChatMessageTransitionNodeImpl?, allUpdated: Bool) -> ChatHistoryViewTransition {
|
||||||
var mergeResult: (deleteIndices: [Int], indicesAndItems: [(Int, ChatHistoryEntry, Int?)], updateIndices: [(Int, ChatHistoryEntry, Int)])
|
var mergeResult: (deleteIndices: [Int], indicesAndItems: [(Int, ChatHistoryEntry, Int?)], updateIndices: [(Int, ChatHistoryEntry, Int)])
|
||||||
let allUpdated = allUpdated || (fromView?.associatedData != toView.associatedData)
|
let allUpdated = allUpdated || (fromView?.associatedData != toView.associatedData)
|
||||||
if reverse {
|
if reverse {
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
module TelegramUIPrivate {
|
|
||||||
export *
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user