mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 21:41:45 +00:00
[WIP] Quotes
This commit is contained in:
parent
eae866c77e
commit
f8626f2c2c
@ -298,6 +298,7 @@ public enum PresentationResourceKey: Int32 {
|
|||||||
case navigationPostStoryIcon
|
case navigationPostStoryIcon
|
||||||
|
|
||||||
case chatReplyBackgroundTemplateImage
|
case chatReplyBackgroundTemplateImage
|
||||||
|
case chatReplyServiceBackgroundTemplateImage
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ChatExpiredStoryIndicatorType: Hashable {
|
public enum ChatExpiredStoryIndicatorType: Hashable {
|
||||||
|
|||||||
@ -1303,4 +1303,17 @@ public struct PresentationResourcesChat {
|
|||||||
})?.stretchableImage(withLeftCapWidth: Int(radius), topCapHeight: Int(radius)).withRenderingMode(.alwaysTemplate)
|
})?.stretchableImage(withLeftCapWidth: Int(radius), topCapHeight: Int(radius)).withRenderingMode(.alwaysTemplate)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func chatReplyServiceBackgroundTemplateImage(_ theme: PresentationTheme) -> UIImage? {
|
||||||
|
return theme.image(PresentationResourceKey.chatReplyServiceBackgroundTemplateImage.rawValue, { theme in
|
||||||
|
let radius: CGFloat = 3.0
|
||||||
|
|
||||||
|
return generateImage(CGSize(width: radius * 2.0 + 1.0, height: radius * 2.0), rotatedContext: { size, context in
|
||||||
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
context.addPath(UIBezierPath(roundedRect: CGRect(origin: CGPoint(), size: CGSize(width: radius, height: size.height)), cornerRadius: radius).cgPath)
|
||||||
|
context.fillPath()
|
||||||
|
})?.stretchableImage(withLeftCapWidth: Int(radius), topCapHeight: Int(radius)).withRenderingMode(.alwaysTemplate)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -347,6 +347,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode",
|
"//submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode",
|
||||||
"//submodules/TelegramUI/Components/Chat/EditableTokenListNode",
|
"//submodules/TelegramUI/Components/Chat/EditableTokenListNode",
|
||||||
"//submodules/TelegramUI/Components/Chat/ChatInputTextNode",
|
"//submodules/TelegramUI/Components/Chat/ChatInputTextNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode",
|
||||||
] + 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": [],
|
||||||
|
|||||||
@ -190,3 +190,13 @@ public func canViewMessageReactionList(message: Message) -> Bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public let chatMessagePeerIdColors: [UIColor] = [
|
||||||
|
UIColor(rgb: 0xfc5c51),
|
||||||
|
UIColor(rgb: 0xfa790f),
|
||||||
|
UIColor(rgb: 0x895dd5),
|
||||||
|
UIColor(rgb: 0x0fb297),
|
||||||
|
UIColor(rgb: 0x00c0c2),
|
||||||
|
UIColor(rgb: 0x3ca5ec),
|
||||||
|
UIColor(rgb: 0x3d72ed)
|
||||||
|
]
|
||||||
|
|||||||
@ -11,8 +11,21 @@ swift_library(
|
|||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//submodules/AsyncDisplayKit",
|
"//submodules/AsyncDisplayKit",
|
||||||
|
"//submodules/Postbox",
|
||||||
|
"//submodules/Display",
|
||||||
|
"//submodules/TelegramCore",
|
||||||
|
"//submodules/SSignalKit/SwiftSignalKit",
|
||||||
"//submodules/TelegramPresentationData",
|
"//submodules/TelegramPresentationData",
|
||||||
"//submodules/ChatPresentationInterfaceState",
|
"//submodules/AccountContext",
|
||||||
|
"//submodules/LocalizedPeerData",
|
||||||
|
"//submodules/PhotoResources",
|
||||||
|
"//submodules/TelegramStringFormatting",
|
||||||
|
"//submodules/TextFormat",
|
||||||
|
"//submodules/InvisibleInkDustNode",
|
||||||
|
"//submodules/TelegramUI/Components/TextNodeWithEntities",
|
||||||
|
"//submodules/TelegramUI/Components/AnimationCache",
|
||||||
|
"//submodules/TelegramUI/Components/MultiAnimationRenderer",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@ -1,23 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
import AsyncDisplayKit
|
|
||||||
import TelegramPresentationData
|
|
||||||
import ChatPresentationInterfaceState
|
|
||||||
|
|
||||||
open class AccessoryPanelNode: ASDisplayNode {
|
|
||||||
open var originalFrameBeforeDismissed: CGRect?
|
|
||||||
open var dismiss: (() -> Void)?
|
|
||||||
open var interfaceInteraction: ChatPanelInterfaceInteraction?
|
|
||||||
|
|
||||||
open func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
|
||||||
}
|
|
||||||
|
|
||||||
open func updateState(size: CGSize, inset: CGFloat, interfaceState: ChatPresentationInterfaceState) {
|
|
||||||
}
|
|
||||||
|
|
||||||
open func animateIn() {
|
|
||||||
}
|
|
||||||
|
|
||||||
open func animateOut() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -15,13 +15,36 @@ import InvisibleInkDustNode
|
|||||||
import TextNodeWithEntities
|
import TextNodeWithEntities
|
||||||
import AnimationCache
|
import AnimationCache
|
||||||
import MultiAnimationRenderer
|
import MultiAnimationRenderer
|
||||||
|
import ChatMessageItemCommon
|
||||||
|
|
||||||
public enum ChatMessageReplyInfoType {
|
public enum ChatMessageReplyInfoType {
|
||||||
case bubble(incoming: Bool)
|
case bubble(incoming: Bool)
|
||||||
case standalone
|
case standalone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private let quoteIcon: UIImage = {
|
||||||
|
return UIImage(bundleImageName: "Chat/Message/ReplyQuoteIcon")!.precomposed().withRenderingMode(.alwaysTemplate)
|
||||||
|
}()
|
||||||
|
|
||||||
public class ChatMessageReplyInfoNode: ASDisplayNode {
|
public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||||
|
public final class TransitionReplyPanel {
|
||||||
|
public let titleNode: ASDisplayNode
|
||||||
|
public let textNode: ASDisplayNode
|
||||||
|
public let lineNode: ASDisplayNode
|
||||||
|
public let imageNode: ASDisplayNode
|
||||||
|
public let relativeSourceRect: CGRect
|
||||||
|
public let relativeTargetRect: CGRect
|
||||||
|
|
||||||
|
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 class Arguments {
|
public class Arguments {
|
||||||
public let presentationData: ChatPresentationData
|
public let presentationData: ChatPresentationData
|
||||||
public let strings: PresentationStrings
|
public let strings: PresentationStrings
|
||||||
@ -74,6 +97,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private let backgroundView: UIImageView
|
private let backgroundView: UIImageView
|
||||||
|
private var quoteIconView: UIImageView?
|
||||||
private let contentNode: ASDisplayNode
|
private let contentNode: ASDisplayNode
|
||||||
private var titleNode: TextNode?
|
private var titleNode: TextNode?
|
||||||
private var textNode: TextNodeWithEntities?
|
private var textNode: TextNodeWithEntities?
|
||||||
@ -331,23 +355,29 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
|
|
||||||
let textInsets = UIEdgeInsets(top: 3.0, left: 0.0, bottom: 3.0, right: 0.0)
|
let textInsets = UIEdgeInsets(top: 3.0, left: 0.0, bottom: 3.0, right: 0.0)
|
||||||
|
|
||||||
let (titleLayout, titleApply) = titleNodeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: titleString, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: contrainedTextSize, alignment: .natural, cutout: nil, insets: textInsets))
|
var additionalTitleWidth: CGFloat = 0.0
|
||||||
if isExpiredStory || isStory {
|
|
||||||
contrainedTextSize.width -= 26.0
|
|
||||||
}
|
|
||||||
var maxTextNumberOfLines = 1
|
var maxTextNumberOfLines = 1
|
||||||
var adjustedConstrainedTextSize = contrainedTextSize
|
var adjustedConstrainedTextSize = contrainedTextSize
|
||||||
var textCutout: TextNodeCutout?
|
var textCutout: TextNodeCutout?
|
||||||
var textCutoutWidth: CGFloat = 0.0
|
var textCutoutWidth: CGFloat = 0.0
|
||||||
if arguments.quote != nil {
|
if arguments.quote != nil {
|
||||||
maxTextNumberOfLines = 5
|
additionalTitleWidth += 10.0
|
||||||
if imageTextInset != 0.0 {
|
if case .bubble = arguments.type {
|
||||||
adjustedConstrainedTextSize.width += imageTextInset
|
maxTextNumberOfLines = 5
|
||||||
textCutout = TextNodeCutout(topLeft: CGSize(width: imageTextInset, height: 10.0))
|
if imageTextInset != 0.0 {
|
||||||
textCutoutWidth = imageTextInset + 4.0
|
adjustedConstrainedTextSize.width += imageTextInset
|
||||||
|
textCutout = TextNodeCutout(topLeft: CGSize(width: imageTextInset + 6.0, height: 10.0))
|
||||||
|
textCutoutWidth = imageTextInset + 6.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (textLayout, textApply) = textNodeLayout(TextNodeLayoutArguments(attributedString: messageText, backgroundColor: nil, maximumNumberOfLines: maxTextNumberOfLines, truncationType: .end, constrainedSize: adjustedConstrainedTextSize, alignment: .natural, lineSpacing: 0.05, cutout: textCutout, insets: textInsets))
|
|
||||||
|
let (titleLayout, titleApply) = titleNodeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: titleString, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: contrainedTextSize.width - additionalTitleWidth, height: contrainedTextSize.height), alignment: .natural, cutout: nil, insets: textInsets))
|
||||||
|
if isExpiredStory || isStory {
|
||||||
|
contrainedTextSize.width -= 26.0
|
||||||
|
}
|
||||||
|
|
||||||
|
let (textLayout, textApply) = textNodeLayout(TextNodeLayoutArguments(attributedString: messageText, backgroundColor: nil, maximumNumberOfLines: maxTextNumberOfLines, truncationType: .end, constrainedSize: adjustedConstrainedTextSize, alignment: .natural, lineSpacing: 0.07, cutout: textCutout, insets: textInsets))
|
||||||
|
|
||||||
let imageSide: CGFloat
|
let imageSide: CGFloat
|
||||||
imageSide = titleLayout.size.height + titleLayout.size.height - 14.0
|
imageSide = titleLayout.size.height + titleLayout.size.height - 14.0
|
||||||
@ -401,7 +431,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var size = CGSize(width: max(titleLayout.size.width - textInsets.left - textInsets.right, textLayout.size.width - textInsets.left - textInsets.right - textCutoutWidth) + leftInset + 6.0, height: titleLayout.size.height + textLayout.size.height - 2 * (textInsets.top + textInsets.bottom) + 2 * spacing)
|
var size = CGSize(width: max(titleLayout.size.width + additionalTitleWidth - textInsets.left - textInsets.right, textLayout.size.width - textInsets.left - textInsets.right - textCutoutWidth) + leftInset + 6.0, height: titleLayout.size.height + textLayout.size.height - 2 * (textInsets.top + textInsets.bottom) + 2 * spacing)
|
||||||
if isExpiredStory || isStory {
|
if isExpiredStory || isStory {
|
||||||
size.width += 16.0
|
size.width += 16.0
|
||||||
}
|
}
|
||||||
@ -446,7 +476,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
node.addSubnode(imageNode)
|
node.addSubnode(imageNode)
|
||||||
node.imageNode = imageNode
|
node.imageNode = imageNode
|
||||||
}
|
}
|
||||||
imageNode.frame = CGRect(origin: CGPoint(x: 9.0, y: 4.0), size: CGSize(width: imageSide, height: imageSide))
|
imageNode.frame = CGRect(origin: CGPoint(x: 9.0, y: 3.0 + UIScreenPixel), size: CGSize(width: imageSide, height: imageSide))
|
||||||
|
|
||||||
if let updateImageSignal = updateImageSignal {
|
if let updateImageSignal = updateImageSignal {
|
||||||
imageNode.setSignal(updateImageSignal)
|
imageNode.setSignal(updateImageSignal)
|
||||||
@ -519,14 +549,41 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if node.backgroundView.image == nil {
|
if node.backgroundView.image == nil {
|
||||||
node.backgroundView.image = PresentationResourcesChat.chatReplyBackgroundTemplateImage(arguments.presentationData.theme.theme)
|
if case .standalone = arguments.type {
|
||||||
|
node.backgroundView.image = PresentationResourcesChat.chatReplyServiceBackgroundTemplateImage(arguments.presentationData.theme.theme)
|
||||||
|
} else {
|
||||||
|
node.backgroundView.image = PresentationResourcesChat.chatReplyBackgroundTemplateImage(arguments.presentationData.theme.theme)
|
||||||
|
}
|
||||||
if node.backgroundView.superview == nil {
|
if node.backgroundView.superview == nil {
|
||||||
node.contentNode.view.insertSubview(node.backgroundView, at: 0)
|
node.contentNode.view.insertSubview(node.backgroundView, at: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: realSize.width, height: realSize.height + 2.0))
|
||||||
|
if case .standalone = arguments.type {
|
||||||
|
backgroundFrame.size.height -= 1.0
|
||||||
|
}
|
||||||
|
|
||||||
node.backgroundView.tintColor = mainColor
|
node.backgroundView.tintColor = mainColor
|
||||||
node.backgroundView.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: realSize.width, height: realSize.height + 2.0))
|
node.backgroundView.frame = backgroundFrame
|
||||||
|
|
||||||
|
if arguments.quote != nil {
|
||||||
|
let quoteIconView: UIImageView
|
||||||
|
if let current = node.quoteIconView {
|
||||||
|
quoteIconView = current
|
||||||
|
} else {
|
||||||
|
quoteIconView = UIImageView(image: quoteIcon)
|
||||||
|
node.quoteIconView = quoteIconView
|
||||||
|
node.contentNode.view.addSubview(quoteIconView)
|
||||||
|
}
|
||||||
|
quoteIconView.tintColor = mainColor
|
||||||
|
quoteIconView.frame = CGRect(origin: CGPoint(x: backgroundFrame.maxX - 4.0 - quoteIcon.size.width, y: backgroundFrame.minY + 4.0), size: quoteIcon.size)
|
||||||
|
} else {
|
||||||
|
if let quoteIconView = node.quoteIconView {
|
||||||
|
node.quoteIconView = nil
|
||||||
|
quoteIconView.removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node.contentNode.frame = CGRect(origin: CGPoint(), size: size)
|
node.contentNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||||
|
|
||||||
@ -535,7 +592,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateFromInputPanel(sourceReplyPanel: ChatMessageTransitionNode.ReplyPanel, unclippedTransitionNode: ASDisplayNode? = nil, localRect: CGRect, transition: CombinedTransition) -> CGPoint {
|
public func animateFromInputPanel(sourceReplyPanel: TransitionReplyPanel, unclippedTransitionNode: ASDisplayNode? = nil, localRect: CGRect, transition: CombinedTransition) -> CGPoint {
|
||||||
let sourceParentNode = ASDisplayNode()
|
let sourceParentNode = ASDisplayNode()
|
||||||
|
|
||||||
let sourceParentOffset: CGPoint
|
let sourceParentOffset: CGPoint
|
||||||
@ -32,6 +32,7 @@ import ChatMessageForwardInfoNode
|
|||||||
import ChatMessageDateAndStatusNode
|
import ChatMessageDateAndStatusNode
|
||||||
import ChatMessageItemCommon
|
import ChatMessageItemCommon
|
||||||
import ChatMessageBubbleContentNode
|
import ChatMessageBubbleContentNode
|
||||||
|
import ChatMessageReplyInfoNode
|
||||||
|
|
||||||
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)
|
||||||
@ -2874,7 +2875,15 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
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)
|
||||||
|
|
||||||
let offset = replyInfoNode.animateFromInputPanel(sourceReplyPanel: sourceReplyPanel, localRect: localRect, transition: transition)
|
let mappedPanel = ChatMessageReplyInfoNode.TransitionReplyPanel(
|
||||||
|
titleNode: sourceReplyPanel.titleNode,
|
||||||
|
textNode: sourceReplyPanel.textNode,
|
||||||
|
lineNode: sourceReplyPanel.lineNode,
|
||||||
|
imageNode: sourceReplyPanel.imageNode,
|
||||||
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
|
)
|
||||||
|
let offset = replyInfoNode.animateFromInputPanel(sourceReplyPanel: mappedPanel, localRect: localRect, transition: transition)
|
||||||
if let replyBackgroundNode = self.replyBackgroundNode {
|
if let replyBackgroundNode = self.replyBackgroundNode {
|
||||||
transition.animatePositionAdditive(layer: replyBackgroundNode.layer, offset: offset)
|
transition.animatePositionAdditive(layer: replyBackgroundNode.layer, offset: offset)
|
||||||
replyBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
replyBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||||
|
|||||||
@ -35,6 +35,7 @@ import ChatMessageBubbleContentNode
|
|||||||
import ChatHistoryEntry
|
import ChatHistoryEntry
|
||||||
import ChatMessageTextBubbleContentNode
|
import ChatMessageTextBubbleContentNode
|
||||||
import ChatMessageItemCommon
|
import ChatMessageItemCommon
|
||||||
|
import ChatMessageReplyInfoNode
|
||||||
|
|
||||||
enum InternalBubbleTapAction {
|
enum InternalBubbleTapAction {
|
||||||
case action(() -> Void)
|
case action(() -> Void)
|
||||||
@ -357,16 +358,6 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> ([
|
|||||||
return (result, needSeparateContainers, needReactions)
|
return (result, needSeparateContainers, needReactions)
|
||||||
}
|
}
|
||||||
|
|
||||||
let chatMessagePeerIdColors: [UIColor] = [
|
|
||||||
UIColor(rgb: 0xfc5c51),
|
|
||||||
UIColor(rgb: 0xfa790f),
|
|
||||||
UIColor(rgb: 0x895dd5),
|
|
||||||
UIColor(rgb: 0x0fb297),
|
|
||||||
UIColor(rgb: 0x00c0c2),
|
|
||||||
UIColor(rgb: 0x3ca5ec),
|
|
||||||
UIColor(rgb: 0x3d72ed)
|
|
||||||
]
|
|
||||||
|
|
||||||
private enum ContentNodeOperation {
|
private enum ContentNodeOperation {
|
||||||
case remove(index: Int)
|
case remove(index: Int)
|
||||||
case insert(index: Int, node: ChatMessageBubbleContentNode)
|
case insert(index: Int, node: ChatMessageBubbleContentNode)
|
||||||
@ -926,7 +917,15 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
func animateReplyPanel(sourceReplyPanel: ChatMessageTransitionNode.ReplyPanel, transition: CombinedTransition) {
|
func animateReplyPanel(sourceReplyPanel: ChatMessageTransitionNode.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 _ = replyInfoNode.animateFromInputPanel(sourceReplyPanel: sourceReplyPanel, unclippedTransitionNode: self.mainContextSourceNode.contentNode, localRect: localRect, transition: transition)
|
let mappedPanel = ChatMessageReplyInfoNode.TransitionReplyPanel(
|
||||||
|
titleNode: sourceReplyPanel.titleNode,
|
||||||
|
textNode: sourceReplyPanel.textNode,
|
||||||
|
lineNode: sourceReplyPanel.lineNode,
|
||||||
|
imageNode: sourceReplyPanel.imageNode,
|
||||||
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
|
)
|
||||||
|
let _ = replyInfoNode.animateFromInputPanel(sourceReplyPanel: mappedPanel, unclippedTransitionNode: self.mainContextSourceNode.contentNode, localRect: localRect, transition: transition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import ChatMessageForwardInfoNode
|
|||||||
import ChatMessageDateAndStatusNode
|
import ChatMessageDateAndStatusNode
|
||||||
import ChatMessageItemCommon
|
import ChatMessageItemCommon
|
||||||
import ChatMessageBubbleContentNode
|
import ChatMessageBubbleContentNode
|
||||||
|
import ChatMessageReplyInfoNode
|
||||||
|
|
||||||
private let nameFont = Font.medium(14.0)
|
private let nameFont = Font.medium(14.0)
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import ChatMessageForwardInfoNode
|
|||||||
import ChatMessageDateAndStatusNode
|
import ChatMessageDateAndStatusNode
|
||||||
import ChatMessageItemCommon
|
import ChatMessageItemCommon
|
||||||
import ChatMessageBubbleContentNode
|
import ChatMessageBubbleContentNode
|
||||||
|
import ChatMessageReplyInfoNode
|
||||||
|
|
||||||
struct ChatMessageInstantVideoItemLayoutResult {
|
struct ChatMessageInstantVideoItemLayoutResult {
|
||||||
let contentSize: CGSize
|
let contentSize: CGSize
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import ChatControllerInteraction
|
|||||||
import ChatMessageForwardInfoNode
|
import ChatMessageForwardInfoNode
|
||||||
import ChatMessageDateAndStatusNode
|
import ChatMessageDateAndStatusNode
|
||||||
import ChatMessageItemCommon
|
import ChatMessageItemCommon
|
||||||
|
import ChatMessageReplyInfoNode
|
||||||
|
|
||||||
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)
|
||||||
@ -1847,8 +1848,16 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
func animateReplyPanel(sourceReplyPanel: ChatMessageTransitionNode.ReplyPanel, transition: CombinedTransition) {
|
func animateReplyPanel(sourceReplyPanel: ChatMessageTransitionNode.ReplyPanel, 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)
|
||||||
|
let mappedPanel = ChatMessageReplyInfoNode.TransitionReplyPanel(
|
||||||
|
titleNode: sourceReplyPanel.titleNode,
|
||||||
|
textNode: sourceReplyPanel.textNode,
|
||||||
|
lineNode: sourceReplyPanel.lineNode,
|
||||||
|
imageNode: sourceReplyPanel.imageNode,
|
||||||
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
|
)
|
||||||
|
|
||||||
let offset = replyInfoNode.animateFromInputPanel(sourceReplyPanel: sourceReplyPanel, localRect: localRect, transition: transition)
|
let offset = replyInfoNode.animateFromInputPanel(sourceReplyPanel: mappedPanel, localRect: localRect, transition: transition)
|
||||||
if let replyBackgroundNode = self.replyBackgroundNode {
|
if let replyBackgroundNode = self.replyBackgroundNode {
|
||||||
transition.animatePositionAdditive(layer: replyBackgroundNode.layer, offset: offset)
|
transition.animatePositionAdditive(layer: replyBackgroundNode.layer, offset: offset)
|
||||||
replyBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
replyBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user