mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-28 10:55:40 +00:00
Text input updates
This commit is contained in:
parent
c962e6f56a
commit
06936fa06c
@ -39,6 +39,22 @@ public final class ChatInputAccessoryPanelEnvironment: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class ChatInputAccessoryPanelTransitionData {
|
||||||
|
public let titleView: UIView
|
||||||
|
public let textView: UIView
|
||||||
|
public let lineView: UIView
|
||||||
|
public let imageView: UIView?
|
||||||
|
|
||||||
|
public init(titleView: UIView, textView: UIView, lineView: UIView, imageView: UIView?) {
|
||||||
|
self.titleView = titleView
|
||||||
|
self.textView = textView
|
||||||
|
self.lineView = lineView
|
||||||
|
self.imageView = imageView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public protocol ChatInputAccessoryPanelView: UIView {
|
public protocol ChatInputAccessoryPanelView: UIView {
|
||||||
var contentTintView: UIView { get }
|
var contentTintView: UIView { get }
|
||||||
|
var storedFrameBeforeDismissed: CGRect? { get set }
|
||||||
|
var transitionData: ChatInputAccessoryPanelTransitionData? { get }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -276,6 +276,20 @@ public final class ChatInputMessageAccessoryPanel: Component {
|
|||||||
private var inlineTextStarImage: UIImage?
|
private var inlineTextStarImage: UIImage?
|
||||||
private var inlineTextTonImage: (UIImage, UIColor)?
|
private var inlineTextTonImage: (UIImage, UIColor)?
|
||||||
|
|
||||||
|
public var transitionData: ChatInputAccessoryPanelTransitionData? {
|
||||||
|
guard let textView = self.text.view else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return ChatInputAccessoryPanelTransitionData(
|
||||||
|
titleView: self.titleNode.view,
|
||||||
|
textView: textView,
|
||||||
|
lineView: self.lineView,
|
||||||
|
imageView: nil
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public var storedFrameBeforeDismissed: CGRect?
|
||||||
|
|
||||||
override public init(frame: CGRect) {
|
override public init(frame: CGRect) {
|
||||||
self.contentTintView = UIView()
|
self.contentTintView = UIView()
|
||||||
|
|
||||||
|
|||||||
@ -3044,18 +3044,18 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class AnimationTransitionReplyPanel {
|
public final class AnimationTransitionReplyPanel {
|
||||||
public let titleNode: ASDisplayNode
|
public let titleView: UIView
|
||||||
public let textNode: ASDisplayNode
|
public let textView: UIView
|
||||||
public let lineNode: ASDisplayNode
|
public let lineView: UIView
|
||||||
public let imageNode: ASDisplayNode
|
public let imageView: UIView?
|
||||||
public let relativeSourceRect: CGRect
|
public let relativeSourceRect: CGRect
|
||||||
public let relativeTargetRect: CGRect
|
public let relativeTargetRect: CGRect
|
||||||
|
|
||||||
public init(titleNode: ASDisplayNode, textNode: ASDisplayNode, lineNode: ASDisplayNode, imageNode: ASDisplayNode, relativeSourceRect: CGRect, relativeTargetRect: CGRect) {
|
public init(titleView: UIView, textView: UIView, lineView: UIView, imageView: UIView?, relativeSourceRect: CGRect, relativeTargetRect: CGRect) {
|
||||||
self.titleNode = titleNode
|
self.titleView = titleView
|
||||||
self.textNode = textNode
|
self.textView = textView
|
||||||
self.lineNode = lineNode
|
self.lineView = lineView
|
||||||
self.imageNode = imageNode
|
self.imageView = imageView
|
||||||
self.relativeSourceRect = relativeSourceRect
|
self.relativeSourceRect = relativeSourceRect
|
||||||
self.relativeTargetRect = relativeTargetRect
|
self.relativeTargetRect = relativeTargetRect
|
||||||
}
|
}
|
||||||
@ -3066,10 +3066,10 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
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(
|
let mappedPanel = ChatMessageReplyInfoNode.TransitionReplyPanel(
|
||||||
titleNode: sourceReplyPanel.titleNode,
|
titleView: sourceReplyPanel.titleView,
|
||||||
textNode: sourceReplyPanel.textNode,
|
textView: sourceReplyPanel.textView,
|
||||||
lineNode: sourceReplyPanel.lineNode,
|
lineView: sourceReplyPanel.lineView,
|
||||||
imageNode: sourceReplyPanel.imageNode,
|
imageView: sourceReplyPanel.imageView,
|
||||||
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1094,18 +1094,18 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class AnimationTransitionReplyPanel {
|
public final class AnimationTransitionReplyPanel {
|
||||||
public let titleNode: ASDisplayNode
|
public let titleView: UIView
|
||||||
public let textNode: ASDisplayNode
|
public let textView: UIView
|
||||||
public let lineNode: ASDisplayNode
|
public let lineView: UIView
|
||||||
public let imageNode: ASDisplayNode
|
public let imageView: UIView?
|
||||||
public let relativeSourceRect: CGRect
|
public let relativeSourceRect: CGRect
|
||||||
public let relativeTargetRect: CGRect
|
public let relativeTargetRect: CGRect
|
||||||
|
|
||||||
public init(titleNode: ASDisplayNode, textNode: ASDisplayNode, lineNode: ASDisplayNode, imageNode: ASDisplayNode, relativeSourceRect: CGRect, relativeTargetRect: CGRect) {
|
public init(titleView: UIView, textView: UIView, lineView: UIView, imageView: UIView?, relativeSourceRect: CGRect, relativeTargetRect: CGRect) {
|
||||||
self.titleNode = titleNode
|
self.titleView = titleView
|
||||||
self.textNode = textNode
|
self.textView = textView
|
||||||
self.lineNode = lineNode
|
self.lineView = lineView
|
||||||
self.imageNode = imageNode
|
self.imageView = imageView
|
||||||
self.relativeSourceRect = relativeSourceRect
|
self.relativeSourceRect = relativeSourceRect
|
||||||
self.relativeTargetRect = relativeTargetRect
|
self.relativeTargetRect = relativeTargetRect
|
||||||
}
|
}
|
||||||
@ -1115,10 +1115,10 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
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(
|
||||||
titleNode: sourceReplyPanel.titleNode,
|
titleView: sourceReplyPanel.titleView,
|
||||||
textNode: sourceReplyPanel.textNode,
|
textView: sourceReplyPanel.textView,
|
||||||
lineNode: sourceReplyPanel.lineNode,
|
lineView: sourceReplyPanel.lineView,
|
||||||
imageNode: sourceReplyPanel.imageNode,
|
imageView: sourceReplyPanel.imageView,
|
||||||
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
)
|
)
|
||||||
|
|||||||
@ -58,18 +58,18 @@ private let groupIcon: UIImage = {
|
|||||||
|
|
||||||
public class ChatMessageReplyInfoNode: ASDisplayNode {
|
public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||||
public final class TransitionReplyPanel {
|
public final class TransitionReplyPanel {
|
||||||
public let titleNode: ASDisplayNode
|
public let titleView: UIView
|
||||||
public let textNode: ASDisplayNode
|
public let textView: UIView
|
||||||
public let lineNode: ASDisplayNode
|
public let lineView: UIView
|
||||||
public let imageNode: ASDisplayNode
|
public let imageView: UIView?
|
||||||
public let relativeSourceRect: CGRect
|
public let relativeSourceRect: CGRect
|
||||||
public let relativeTargetRect: CGRect
|
public let relativeTargetRect: CGRect
|
||||||
|
|
||||||
public init(titleNode: ASDisplayNode, textNode: ASDisplayNode, lineNode: ASDisplayNode, imageNode: ASDisplayNode, relativeSourceRect: CGRect, relativeTargetRect: CGRect) {
|
public init(titleView: UIView, textView: UIView, lineView: UIView, imageView: UIView?, relativeSourceRect: CGRect, relativeTargetRect: CGRect) {
|
||||||
self.titleNode = titleNode
|
self.titleView = titleView
|
||||||
self.textNode = textNode
|
self.textView = textView
|
||||||
self.lineNode = lineNode
|
self.lineView = lineView
|
||||||
self.imageNode = imageNode
|
self.imageView = imageView
|
||||||
self.relativeSourceRect = relativeSourceRect
|
self.relativeSourceRect = relativeSourceRect
|
||||||
self.relativeTargetRect = relativeTargetRect
|
self.relativeTargetRect = relativeTargetRect
|
||||||
}
|
}
|
||||||
@ -971,84 +971,88 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
|
|
||||||
if let titleNode = self.titleNode {
|
if let titleNode = self.titleNode {
|
||||||
let offset = CGPoint(
|
let offset = CGPoint(
|
||||||
x: localRect.minX + sourceReplyPanel.titleNode.frame.minX - titleNode.frame.minX,
|
x: localRect.minX + sourceReplyPanel.titleView.frame.minX - titleNode.frame.minX,
|
||||||
y: localRect.minY + sourceReplyPanel.titleNode.frame.midY - titleNode.frame.midY
|
y: localRect.minY + sourceReplyPanel.titleView.frame.midY - titleNode.frame.midY
|
||||||
)
|
)
|
||||||
|
|
||||||
transition.horizontal.animatePositionAdditive(node: titleNode, offset: CGPoint(x: offset.x, y: 0.0))
|
transition.horizontal.animatePositionAdditive(node: titleNode, offset: CGPoint(x: offset.x, y: 0.0))
|
||||||
transition.vertical.animatePositionAdditive(node: titleNode, offset: CGPoint(x: 0.0, y: offset.y))
|
transition.vertical.animatePositionAdditive(node: titleNode, offset: CGPoint(x: 0.0, y: offset.y))
|
||||||
|
|
||||||
sourceParentNode.addSubnode(sourceReplyPanel.titleNode)
|
sourceParentNode.view.addSubview(sourceReplyPanel.titleView)
|
||||||
|
|
||||||
titleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
titleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||||
|
|
||||||
sourceReplyPanel.titleNode.frame = sourceReplyPanel.titleNode.frame
|
sourceReplyPanel.titleView.frame = sourceReplyPanel.titleView.frame
|
||||||
.offsetBy(dx: sourceParentOffset.x, dy: sourceParentOffset.y)
|
.offsetBy(dx: sourceParentOffset.x, dy: sourceParentOffset.y)
|
||||||
.offsetBy(dx: localRect.minX - offset.x, dy: localRect.minY - offset.y)
|
.offsetBy(dx: localRect.minX - offset.x, dy: localRect.minY - offset.y)
|
||||||
transition.horizontal.animatePositionAdditive(node: sourceReplyPanel.titleNode, offset: CGPoint(x: offset.x, y: 0.0), removeOnCompletion: false)
|
transition.horizontal.animatePositionAdditive(layer: sourceReplyPanel.titleView.layer, offset: CGPoint(x: offset.x, y: 0.0), removeOnCompletion: false)
|
||||||
transition.vertical.animatePositionAdditive(node: sourceReplyPanel.titleNode, offset: CGPoint(x: 0.0, y: offset.y), removeOnCompletion: false)
|
transition.vertical.animatePositionAdditive(layer: sourceReplyPanel.titleView.layer, offset: CGPoint(x: 0.0, y: offset.y), removeOnCompletion: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let textNode = self.textNode {
|
if let textNode = self.textNode {
|
||||||
let offset = CGPoint(
|
let offset = CGPoint(
|
||||||
x: localRect.minX + sourceReplyPanel.textNode.frame.minX - textNode.textNode.frame.minX,
|
x: localRect.minX + sourceReplyPanel.textView.frame.minX - textNode.textNode.frame.minX,
|
||||||
y: localRect.minY + sourceReplyPanel.textNode.frame.midY - textNode.textNode.frame.midY
|
y: localRect.minY + sourceReplyPanel.textView.frame.midY - textNode.textNode.frame.midY
|
||||||
)
|
)
|
||||||
|
|
||||||
transition.horizontal.animatePositionAdditive(node: textNode.textNode, offset: CGPoint(x: offset.x, y: 0.0))
|
transition.horizontal.animatePositionAdditive(node: textNode.textNode, offset: CGPoint(x: offset.x, y: 0.0))
|
||||||
transition.vertical.animatePositionAdditive(node: textNode.textNode, offset: CGPoint(x: 0.0, y: offset.y))
|
transition.vertical.animatePositionAdditive(node: textNode.textNode, offset: CGPoint(x: 0.0, y: offset.y))
|
||||||
|
|
||||||
sourceParentNode.addSubnode(sourceReplyPanel.textNode)
|
sourceParentNode.view.addSubview(sourceReplyPanel.textView)
|
||||||
|
|
||||||
textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||||
|
|
||||||
sourceReplyPanel.textNode.frame = sourceReplyPanel.textNode.frame
|
sourceReplyPanel.textView.frame = sourceReplyPanel.textView.frame
|
||||||
.offsetBy(dx: sourceParentOffset.x, dy: sourceParentOffset.y)
|
.offsetBy(dx: sourceParentOffset.x, dy: sourceParentOffset.y)
|
||||||
.offsetBy(dx: localRect.minX - offset.x, dy: localRect.minY - offset.y)
|
.offsetBy(dx: localRect.minX - offset.x, dy: localRect.minY - offset.y)
|
||||||
transition.horizontal.animatePositionAdditive(node: sourceReplyPanel.textNode, offset: CGPoint(x: offset.x, y: 0.0), removeOnCompletion: false)
|
transition.horizontal.animatePositionAdditive(layer: sourceReplyPanel.textView.layer, offset: CGPoint(x: offset.x, y: 0.0), removeOnCompletion: false)
|
||||||
transition.vertical.animatePositionAdditive(node: sourceReplyPanel.textNode, offset: CGPoint(x: 0.0, y: offset.y), removeOnCompletion: false)
|
transition.vertical.animatePositionAdditive(layer: sourceReplyPanel.textView.layer, offset: CGPoint(x: 0.0, y: offset.y), removeOnCompletion: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let imageNode = self.imageNode {
|
if let imageNode = self.imageNode {
|
||||||
let offset = CGPoint(
|
if let sourceImageView = sourceReplyPanel.imageView {
|
||||||
x: localRect.minX + sourceReplyPanel.imageNode.frame.midX - imageNode.frame.midX,
|
let offset = CGPoint(
|
||||||
y: localRect.minY + sourceReplyPanel.imageNode.frame.midY - imageNode.frame.midY
|
x: localRect.minX + sourceImageView.frame.midX - imageNode.frame.midX,
|
||||||
)
|
y: localRect.minY + sourceImageView.frame.midY - imageNode.frame.midY
|
||||||
|
)
|
||||||
transition.horizontal.animatePositionAdditive(node: imageNode, offset: CGPoint(x: offset.x, y: 0.0))
|
|
||||||
transition.vertical.animatePositionAdditive(node: imageNode, offset: CGPoint(x: 0.0, y: offset.y))
|
transition.horizontal.animatePositionAdditive(node: imageNode, offset: CGPoint(x: offset.x, y: 0.0))
|
||||||
|
transition.vertical.animatePositionAdditive(node: imageNode, offset: CGPoint(x: 0.0, y: offset.y))
|
||||||
sourceParentNode.addSubnode(sourceReplyPanel.imageNode)
|
|
||||||
|
sourceParentNode.view.addSubview(sourceImageView)
|
||||||
imageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
|
||||||
|
imageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||||
sourceReplyPanel.imageNode.frame = sourceReplyPanel.imageNode.frame
|
|
||||||
.offsetBy(dx: sourceParentOffset.x, dy: sourceParentOffset.y)
|
sourceImageView.frame = sourceImageView.frame
|
||||||
.offsetBy(dx: localRect.minX - offset.x, dy: localRect.minY - offset.y)
|
.offsetBy(dx: sourceParentOffset.x, dy: sourceParentOffset.y)
|
||||||
transition.horizontal.animatePositionAdditive(node: sourceReplyPanel.imageNode, offset: CGPoint(x: offset.x, y: 0.0), removeOnCompletion: false)
|
.offsetBy(dx: localRect.minX - offset.x, dy: localRect.minY - offset.y)
|
||||||
transition.vertical.animatePositionAdditive(node: sourceReplyPanel.imageNode, offset: CGPoint(x: 0.0, y: offset.y), removeOnCompletion: false)
|
transition.horizontal.animatePositionAdditive(layer: sourceImageView.layer, offset: CGPoint(x: offset.x, y: 0.0), removeOnCompletion: false)
|
||||||
|
transition.vertical.animatePositionAdditive(layer: sourceImageView.layer, offset: CGPoint(x: 0.0, y: offset.y), removeOnCompletion: false)
|
||||||
|
} else {
|
||||||
|
imageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let backgroundView = self.backgroundView
|
let backgroundView = self.backgroundView
|
||||||
|
|
||||||
let offset = CGPoint(
|
let offset = CGPoint(
|
||||||
x: localRect.minX + sourceReplyPanel.lineNode.frame.minX - backgroundView.frame.minX,
|
x: localRect.minX + sourceReplyPanel.lineView.frame.minX - backgroundView.frame.minX,
|
||||||
y: localRect.minY + sourceReplyPanel.lineNode.frame.minY - backgroundView.frame.minY
|
y: localRect.minY + sourceReplyPanel.lineView.frame.minY - backgroundView.frame.minY
|
||||||
)
|
)
|
||||||
|
|
||||||
transition.horizontal.animatePositionAdditive(layer: backgroundView.layer, offset: CGPoint(x: offset.x, y: 0.0))
|
transition.horizontal.animatePositionAdditive(layer: backgroundView.layer, offset: CGPoint(x: offset.x, y: 0.0))
|
||||||
transition.vertical.animatePositionAdditive(layer: backgroundView.layer, offset: CGPoint(x: 0.0, y: offset.y))
|
transition.vertical.animatePositionAdditive(layer: backgroundView.layer, offset: CGPoint(x: 0.0, y: offset.y))
|
||||||
|
|
||||||
sourceParentNode.addSubnode(sourceReplyPanel.lineNode)
|
sourceParentNode.view.addSubview(sourceReplyPanel.lineView)
|
||||||
|
|
||||||
backgroundView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
backgroundView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||||
|
|
||||||
sourceReplyPanel.lineNode.frame = sourceReplyPanel.lineNode.frame
|
sourceReplyPanel.lineView.frame = sourceReplyPanel.lineView.frame
|
||||||
.offsetBy(dx: sourceParentOffset.x, dy: sourceParentOffset.y)
|
.offsetBy(dx: sourceParentOffset.x, dy: sourceParentOffset.y)
|
||||||
.offsetBy(dx: localRect.minX - offset.x, dy: localRect.minY - offset.y)
|
.offsetBy(dx: localRect.minX - offset.x, dy: localRect.minY - offset.y)
|
||||||
transition.horizontal.animatePositionAdditive(node: sourceReplyPanel.lineNode, offset: CGPoint(x: offset.x, y: 0.0), removeOnCompletion: false)
|
transition.horizontal.animatePositionAdditive(layer: sourceReplyPanel.lineView.layer, offset: CGPoint(x: offset.x, y: 0.0), removeOnCompletion: false)
|
||||||
transition.vertical.animatePositionAdditive(node: sourceReplyPanel.lineNode, offset: CGPoint(x: 0.0, y: offset.y), removeOnCompletion: false)
|
transition.vertical.animatePositionAdditive(layer: sourceReplyPanel.lineView.layer, offset: CGPoint(x: 0.0, y: offset.y), removeOnCompletion: false)
|
||||||
|
|
||||||
return offset
|
return offset
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2160,18 +2160,18 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class AnimationTransitionReplyPanel {
|
public final class AnimationTransitionReplyPanel {
|
||||||
public let titleNode: ASDisplayNode
|
public let titleView: UIView
|
||||||
public let textNode: ASDisplayNode
|
public let textView: UIView
|
||||||
public let lineNode: ASDisplayNode
|
public let lineView: UIView
|
||||||
public let imageNode: ASDisplayNode
|
public let imageView: UIView?
|
||||||
public let relativeSourceRect: CGRect
|
public let relativeSourceRect: CGRect
|
||||||
public let relativeTargetRect: CGRect
|
public let relativeTargetRect: CGRect
|
||||||
|
|
||||||
public init(titleNode: ASDisplayNode, textNode: ASDisplayNode, lineNode: ASDisplayNode, imageNode: ASDisplayNode, relativeSourceRect: CGRect, relativeTargetRect: CGRect) {
|
public init(titleView: UIView, textView: UIView, lineView: UIView, imageView: UIView?, relativeSourceRect: CGRect, relativeTargetRect: CGRect) {
|
||||||
self.titleNode = titleNode
|
self.titleView = titleView
|
||||||
self.textNode = textNode
|
self.textView = textView
|
||||||
self.lineNode = lineNode
|
self.lineView = lineView
|
||||||
self.imageNode = imageNode
|
self.imageView = imageView
|
||||||
self.relativeSourceRect = relativeSourceRect
|
self.relativeSourceRect = relativeSourceRect
|
||||||
self.relativeTargetRect = relativeTargetRect
|
self.relativeTargetRect = relativeTargetRect
|
||||||
}
|
}
|
||||||
@ -2181,10 +2181,10 @@ public class ChatMessageStickerItemNode: 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 mappedPanel = ChatMessageReplyInfoNode.TransitionReplyPanel(
|
let mappedPanel = ChatMessageReplyInfoNode.TransitionReplyPanel(
|
||||||
titleNode: sourceReplyPanel.titleNode,
|
titleView: sourceReplyPanel.titleView,
|
||||||
textNode: sourceReplyPanel.textNode,
|
textView: sourceReplyPanel.textView,
|
||||||
lineNode: sourceReplyPanel.lineNode,
|
lineView: sourceReplyPanel.lineView,
|
||||||
imageNode: sourceReplyPanel.imageNode,
|
imageView: sourceReplyPanel.imageView,
|
||||||
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1633,6 +1633,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func animateFrom(sourceView: UIView, scrollOffset: CGFloat, widthDifference: CGFloat, transition: CombinedTransition) {
|
public func animateFrom(sourceView: UIView, scrollOffset: CGFloat, widthDifference: CGFloat, transition: CombinedTransition) {
|
||||||
|
self.containerNode.clipsToBounds = false
|
||||||
self.containerNode.view.addSubview(sourceView)
|
self.containerNode.view.addSubview(sourceView)
|
||||||
|
|
||||||
sourceView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, removeOnCompletion: false, completion: { [weak sourceView] _ in
|
sourceView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, removeOnCompletion: false, completion: { [weak sourceView] _ in
|
||||||
@ -1645,7 +1646,12 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
y: sourceView.frame.minY - (self.textNode.textNode.frame.minY - 3.0) - scrollOffset
|
y: sourceView.frame.minY - (self.textNode.textNode.frame.minY - 3.0) - scrollOffset
|
||||||
)
|
)
|
||||||
|
|
||||||
transition.vertical.animatePositionAdditive(node: self.textNode.textNode, offset: offset)
|
transition.vertical.animatePositionAdditive(layer: self.textNode.textNode.layer, offset: offset, completion: { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.containerNode.clipsToBounds = true
|
||||||
|
})
|
||||||
transition.updatePosition(layer: sourceView.layer, position: CGPoint(x: sourceView.layer.position.x - offset.x, y: sourceView.layer.position.y - offset.y))
|
transition.updatePosition(layer: sourceView.layer, position: CGPoint(x: sourceView.layer.position.x - offset.x, y: sourceView.layer.position.y - offset.y))
|
||||||
|
|
||||||
if let statusNode = self.statusNode {
|
if let statusNode = self.statusNode {
|
||||||
|
|||||||
@ -274,6 +274,9 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
public let recordMoreButton: ChatRecordingViewOnceButtonNode
|
public let recordMoreButton: ChatRecordingViewOnceButtonNode
|
||||||
|
|
||||||
private var accessoryPanel: (component: AnyComponentWithIdentity<ChatInputAccessoryPanelEnvironment>, view: ComponentView<ChatInputAccessoryPanelEnvironment>)?
|
private var accessoryPanel: (component: AnyComponentWithIdentity<ChatInputAccessoryPanelEnvironment>, view: ComponentView<ChatInputAccessoryPanelEnvironment>)?
|
||||||
|
public var accessoryPanelView: ChatInputAccessoryPanelView? {
|
||||||
|
return self.accessoryPanel?.view.view as? ChatInputAccessoryPanelView
|
||||||
|
}
|
||||||
private var contextPanel: (container: UIView, mask: UIImageView, panel: ChatInputContextPanelNode)?
|
private var contextPanel: (container: UIView, mask: UIImageView, panel: ChatInputContextPanelNode)?
|
||||||
private var mediaPreviewPanelNode: ChatRecordingPreviewInputPanelNodeImpl?
|
private var mediaPreviewPanelNode: ChatRecordingPreviewInputPanelNodeImpl?
|
||||||
|
|
||||||
@ -2254,10 +2257,12 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
let alphaTransitionIn: ContainedViewLayoutTransition = transition.isAnimated ? ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut) : .immediate
|
let alphaTransitionIn: ContainedViewLayoutTransition = transition.isAnimated ? ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut) : .immediate
|
||||||
let alphaTransitionOut: ContainedViewLayoutTransition = transition.isAnimated ? ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut) : .immediate
|
let alphaTransitionOut: ContainedViewLayoutTransition = transition.isAnimated ? ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut) : .immediate
|
||||||
|
|
||||||
let accessoryPanelAnimationBlurRadius: CGFloat = 20.0
|
|
||||||
var removedAccessoryPanelView: UIView?
|
var removedAccessoryPanelView: UIView?
|
||||||
|
|
||||||
if let currentAccessoryPanel = self.accessoryPanel, currentAccessoryPanel.component.id != accessoryPanel?.id {
|
if let currentAccessoryPanel = self.accessoryPanel, currentAccessoryPanel.component.id != accessoryPanel?.id {
|
||||||
|
if let panelView = currentAccessoryPanel.view.view as? ChatInputAccessoryPanelView {
|
||||||
|
panelView.storedFrameBeforeDismissed = panelView.convert(panelView.bounds, to: nil)
|
||||||
|
}
|
||||||
self.accessoryPanel = nil
|
self.accessoryPanel = nil
|
||||||
if let accessoryPanelView = currentAccessoryPanel.view.view {
|
if let accessoryPanelView = currentAccessoryPanel.view.view {
|
||||||
removedAccessoryPanelView = accessoryPanelView
|
removedAccessoryPanelView = accessoryPanelView
|
||||||
@ -2299,18 +2304,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
accessoryPanelComponentView.frame = accessoryPanelFrame.offsetBy(dx: 0.0, dy: self.textInputNodeClippingContainer.frame.minY - accessoryPanelFrame.height)
|
accessoryPanelComponentView.frame = accessoryPanelFrame.offsetBy(dx: 0.0, dy: self.textInputNodeClippingContainer.frame.minY - accessoryPanelFrame.height)
|
||||||
accessoryPanelComponentView.alpha = 0.0
|
accessoryPanelComponentView.alpha = 0.0
|
||||||
|
|
||||||
if transition.isAnimated {
|
|
||||||
ComponentTransition(alphaTransitionIn).animateBlur(layer: accessoryPanelComponentView.layer, fromRadius: accessoryPanelAnimationBlurRadius, toRadius: 0.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let accessoryPanelComponentView = accessoryPanelComponentView as? ChatInputAccessoryPanelView {
|
if let accessoryPanelComponentView = accessoryPanelComponentView as? ChatInputAccessoryPanelView {
|
||||||
self.textInputContainerBackgroundView.maskContentView.addSubview(accessoryPanelComponentView.contentTintView)
|
self.textInputContainerBackgroundView.maskContentView.addSubview(accessoryPanelComponentView.contentTintView)
|
||||||
accessoryPanelComponentView.contentTintView.frame = accessoryPanelFrame.offsetBy(dx: 0.0, dy: self.textInputNodeClippingContainer.frame.minY - accessoryPanelFrame.height)
|
accessoryPanelComponentView.contentTintView.frame = accessoryPanelFrame.offsetBy(dx: 0.0, dy: self.textInputNodeClippingContainer.frame.minY - accessoryPanelFrame.height)
|
||||||
accessoryPanelComponentView.contentTintView.alpha = 0.0
|
accessoryPanelComponentView.contentTintView.alpha = 0.0
|
||||||
|
|
||||||
if transition.isAnimated {
|
|
||||||
ComponentTransition(alphaTransitionIn).animateBlur(layer: accessoryPanelComponentView.contentTintView.layer, fromRadius: accessoryPanelAnimationBlurRadius, toRadius: 0.0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
transition.updateFrame(view: accessoryPanelComponentView, frame: accessoryPanelFrame)
|
transition.updateFrame(view: accessoryPanelComponentView, frame: accessoryPanelFrame)
|
||||||
@ -2378,16 +2375,17 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
|
|
||||||
self.textInputContainerBackgroundView.update(size: textInputContainerBackgroundFrame.size, cornerRadius: floor(minimalInputHeight * 0.5), isDark: interfaceState.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), transition: ComponentTransition(transition))
|
self.textInputContainerBackgroundView.update(size: textInputContainerBackgroundFrame.size, cornerRadius: floor(minimalInputHeight * 0.5), isDark: interfaceState.theme.overallDarkAppearance, tintColor: .init(kind: .panel, color: interfaceState.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)), transition: ComponentTransition(transition))
|
||||||
|
|
||||||
|
transition.updateFrame(layer: self.textInputBackgroundNode.layer, frame: textInputContainerBackgroundFrame)
|
||||||
|
transition.updateAlpha(node: self.textInputBackgroundNode, alpha: audioRecordingItemsAlpha)
|
||||||
|
|
||||||
if let removedAccessoryPanelView {
|
if let removedAccessoryPanelView {
|
||||||
if let removedAccessoryPanelView = removedAccessoryPanelView as? ChatInputAccessoryPanelView {
|
if let removedAccessoryPanelView = removedAccessoryPanelView as? ChatInputAccessoryPanelView {
|
||||||
let contentTintView = removedAccessoryPanelView.contentTintView
|
let contentTintView = removedAccessoryPanelView.contentTintView
|
||||||
ComponentTransition(alphaTransitionOut).animateBlur(layer: contentTintView.layer, fromRadius: 0.0, toRadius: accessoryPanelAnimationBlurRadius, removeOnCompletion: false)
|
|
||||||
transition.updateFrame(view: contentTintView, frame: CGRect(origin: CGPoint(x: contentTintView.frame.minX, y: textFieldTopContentOffset - contentTintView.bounds.height), size: contentTintView.bounds.size))
|
transition.updateFrame(view: contentTintView, frame: CGRect(origin: CGPoint(x: contentTintView.frame.minX, y: textFieldTopContentOffset - contentTintView.bounds.height), size: contentTintView.bounds.size))
|
||||||
alphaTransitionOut.updateAlpha(layer: contentTintView.layer, alpha: 0.0, completion: { [weak contentTintView] _ in
|
alphaTransitionOut.updateAlpha(layer: contentTintView.layer, alpha: 0.0, completion: { [weak contentTintView] _ in
|
||||||
contentTintView?.removeFromSuperview()
|
contentTintView?.removeFromSuperview()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ComponentTransition(alphaTransitionOut).animateBlur(layer: removedAccessoryPanelView.layer, fromRadius: 0.0, toRadius: accessoryPanelAnimationBlurRadius, removeOnCompletion: false)
|
|
||||||
transition.updateFrame(view: removedAccessoryPanelView, frame: CGRect(origin: CGPoint(x: removedAccessoryPanelView.frame.minX, y: textFieldTopContentOffset - removedAccessoryPanelView.bounds.height), size: removedAccessoryPanelView.bounds.size))
|
transition.updateFrame(view: removedAccessoryPanelView, frame: CGRect(origin: CGPoint(x: removedAccessoryPanelView.frame.minX, y: textFieldTopContentOffset - removedAccessoryPanelView.bounds.height), size: removedAccessoryPanelView.bounds.size))
|
||||||
alphaTransitionOut.updateAlpha(layer: removedAccessoryPanelView.layer, alpha: 0.0, completion: { [weak removedAccessoryPanelView] _ in
|
alphaTransitionOut.updateAlpha(layer: removedAccessoryPanelView.layer, alpha: 0.0, completion: { [weak removedAccessoryPanelView] _ in
|
||||||
removedAccessoryPanelView?.removeFromSuperview()
|
removedAccessoryPanelView?.removeFromSuperview()
|
||||||
@ -2518,10 +2516,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let textInputBackgroundFrame = CGRect(x: hideOffset.x + leftInset + textFieldInsets.left, y: hideOffset.y + textFieldInsets.top + textFieldTopContentOffset, width: baseWidth - textFieldInsets.left - textFieldInsets.right, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom + self.textInputViewInternalInsets.top + self.textInputViewInternalInsets.bottom)
|
|
||||||
self.currentTextInputBackgroundWidthOffset = textInputBackgroundWidthOffset
|
self.currentTextInputBackgroundWidthOffset = textInputBackgroundWidthOffset
|
||||||
transition.updateFrame(layer: self.textInputBackgroundNode.layer, frame: textInputBackgroundFrame)
|
|
||||||
transition.updateAlpha(node: self.textInputBackgroundNode, alpha: audioRecordingItemsAlpha)
|
|
||||||
|
|
||||||
let textPlaceholderSize: CGSize
|
let textPlaceholderSize: CGSize
|
||||||
let textPlaceholderMaxWidth: CGFloat = max(1.0, nextButtonTopRight.x - 12.0)
|
let textPlaceholderMaxWidth: CGFloat = max(1.0, nextButtonTopRight.x - 12.0)
|
||||||
@ -2563,7 +2558,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
|
|
||||||
let textPlaceholderFrame: CGRect
|
let textPlaceholderFrame: CGRect
|
||||||
if sendingTextDisabled {
|
if sendingTextDisabled {
|
||||||
textPlaceholderFrame = CGRect(origin: CGPoint(x: floor((textInputBackgroundFrame.width - textPlaceholderSize.width) / 2.0), y: self.textInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel + textFieldTopContentOffset), size: textPlaceholderSize)
|
textPlaceholderFrame = CGRect(origin: CGPoint(x: floor((textInputContainerBackgroundFrame.width - textPlaceholderSize.width) / 2.0), y: self.textInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel + textFieldTopContentOffset), size: textPlaceholderSize)
|
||||||
|
|
||||||
let textLockIconNode: ASImageNode
|
let textLockIconNode: ASImageNode
|
||||||
var textLockIconTransition = transition
|
var textLockIconTransition = transition
|
||||||
@ -4672,7 +4667,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
|
|
||||||
public func frameForAttachmentButton() -> CGRect? {
|
public func frameForAttachmentButton() -> CGRect? {
|
||||||
if !self.attachmentButton.alpha.isZero {
|
if !self.attachmentButton.alpha.isZero {
|
||||||
return self.attachmentButton.frame.insetBy(dx: 0.0, dy: 6.0).offsetBy(dx: 2.0, dy: 0.0)
|
return self.attachmentButton.frame.insetBy(dx: 0.0, dy: -4.0).offsetBy(dx: 0.0, dy: 0.0)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -4727,9 +4722,8 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO
|
|
||||||
let backgroundView = UIImageView()
|
let backgroundView = UIImageView()
|
||||||
backgroundView.frame = self.textInputBackgroundNode.frame
|
backgroundView.frame = self.textInputBackgroundNode.view.convert(self.textInputBackgroundNode.bounds, to: self.view)
|
||||||
|
|
||||||
let caretColor = textInputNode.textView.tintColor
|
let caretColor = textInputNode.textView.tintColor
|
||||||
textInputNode.textView.tintColor = .clear
|
textInputNode.textView.tintColor = .clear
|
||||||
@ -4741,7 +4735,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
|
|
||||||
textInputNode.textView.tintColor = caretColor
|
textInputNode.textView.tintColor = caretColor
|
||||||
|
|
||||||
contentView.frame = textInputNode.frame
|
if let textInputNodeSuperview = textInputNode.view.superview {
|
||||||
|
let _ = textInputNodeSuperview
|
||||||
|
contentView.frame = textInputNode.frame.offsetBy(dx: 0.0, dy: self.textInputNodeClippingContainer.frame.minY)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
backgroundView: backgroundView,
|
backgroundView: backgroundView,
|
||||||
|
|||||||
@ -142,6 +142,8 @@ import AVFoundation
|
|||||||
import BalanceNeededScreen
|
import BalanceNeededScreen
|
||||||
import FaceScanScreen
|
import FaceScanScreen
|
||||||
import ChatThemeScreen
|
import ChatThemeScreen
|
||||||
|
import ChatTextInputPanelNode
|
||||||
|
import ChatInputAccessoryPanel
|
||||||
|
|
||||||
public final class ChatControllerOverlayPresentationData {
|
public final class ChatControllerOverlayPresentationData {
|
||||||
public let expandData: (ASDisplayNode?, () -> Void)
|
public let expandData: (ASDisplayNode?, () -> Void)
|
||||||
@ -2178,9 +2180,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
let correlationId = Int64.random(in: 0 ..< Int64.max)
|
let correlationId = Int64.random(in: 0 ..< Int64.max)
|
||||||
|
|
||||||
var replyPanel: ReplyAccessoryPanelNode?
|
var replyPanel: ChatInputAccessoryPanelView?
|
||||||
if let accessoryPanelNode = strongSelf.chatDisplayNode.accessoryPanelNode as? ReplyAccessoryPanelNode {
|
if let inputPanelNode = strongSelf.chatDisplayNode.inputPanelNode as? ChatTextInputPanelNode {
|
||||||
replyPanel = accessoryPanelNode
|
replyPanel = inputPanelNode.accessoryPanelView
|
||||||
}
|
}
|
||||||
|
|
||||||
var shouldAnimateMessageTransition = strongSelf.chatDisplayNode.shouldAnimateMessageTransition
|
var shouldAnimateMessageTransition = strongSelf.chatDisplayNode.shouldAnimateMessageTransition
|
||||||
@ -2188,8 +2190,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
shouldAnimateMessageTransition = true
|
shouldAnimateMessageTransition = true
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.presentPaidMessageAlertIfNeeded(completion: { [weak self] postpone in
|
strongSelf.presentPaidMessageAlertIfNeeded(completion: { [weak strongSelf] postpone in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
|
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
|
||||||
|
|||||||
@ -49,6 +49,7 @@ import ChatSideTopicsPanel
|
|||||||
import GlassBackgroundComponent
|
import GlassBackgroundComponent
|
||||||
import ChatThemeScreen
|
import ChatThemeScreen
|
||||||
import ChatTextInputPanelNode
|
import ChatTextInputPanelNode
|
||||||
|
import ChatInputAccessoryPanel
|
||||||
|
|
||||||
final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem {
|
final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem {
|
||||||
let itemNode: OverlayMediaItemNode
|
let itemNode: OverlayMediaItemNode
|
||||||
@ -4660,11 +4661,10 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
let correlationId = Int64.random(in: 0 ..< Int64.max)
|
let correlationId = Int64.random(in: 0 ..< Int64.max)
|
||||||
messages[messages.count - 1] = messages[messages.count - 1].withUpdatedCorrelationId(correlationId)
|
messages[messages.count - 1] = messages[messages.count - 1].withUpdatedCorrelationId(correlationId)
|
||||||
|
|
||||||
var replyPanel: ReplyAccessoryPanelNode?
|
var replyPanel: ChatInputAccessoryPanelView?
|
||||||
if let accessoryPanelNode = self.accessoryPanelNode as? ReplyAccessoryPanelNode {
|
|
||||||
replyPanel = accessoryPanelNode
|
|
||||||
}
|
|
||||||
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() {
|
||||||
|
replyPanel = inputPanelNode.accessoryPanelView
|
||||||
|
|
||||||
usedCorrelationId = correlationId
|
usedCorrelationId = correlationId
|
||||||
let source: ChatMessageTransitionNodeImpl.Source = .textInput(textInput: ChatMessageTransitionNodeImpl.Source.TextInput(
|
let source: ChatMessageTransitionNodeImpl.Source = .textInput(textInput: ChatMessageTransitionNodeImpl.Source.TextInput(
|
||||||
backgroundView: textInput.backgroundView,
|
backgroundView: textInput.backgroundView,
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import ChatMessageBubbleItemNode
|
|||||||
import ChatEmptyNode
|
import ChatEmptyNode
|
||||||
import ChatMediaInputStickerGridItem
|
import ChatMediaInputStickerGridItem
|
||||||
import AccountContext
|
import AccountContext
|
||||||
|
import ChatInputAccessoryPanel
|
||||||
|
|
||||||
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() {
|
||||||
@ -105,26 +106,41 @@ private final class OverlayTransitionContainerController: ViewController, Standa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func chatMessageTransitionAnimationDuration() -> Double {
|
||||||
|
#if DEBUG && false
|
||||||
|
return 3.0
|
||||||
|
#else
|
||||||
|
return 0.3
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTransitionNode, ChatMessageTransitionProtocol {
|
public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTransitionNode, ChatMessageTransitionProtocol {
|
||||||
static let animationDuration: Double = 0.3
|
static let animationDuration: Double = chatMessageTransitionAnimationDuration()
|
||||||
|
|
||||||
public static let verticalAnimationControlPoints: (Float, Float, Float, Float) = (0.19919472913616398, 0.010644531250000006, 0.27920937042459737, 0.91025390625)
|
public static let verticalAnimationControlPoints: (Float, Float, Float, Float) = (0.19919472913616398, 0.010644531250000006, 0.27920937042459737, 0.91025390625)
|
||||||
public static let verticalAnimationCurve: ContainedViewLayoutTransitionCurve = .custom(verticalAnimationControlPoints.0, verticalAnimationControlPoints.1, verticalAnimationControlPoints.2, verticalAnimationControlPoints.3)
|
public static let verticalAnimationCurve: ContainedViewLayoutTransitionCurve = .custom(verticalAnimationControlPoints.0, verticalAnimationControlPoints.1, verticalAnimationControlPoints.2, verticalAnimationControlPoints.3)
|
||||||
public static let horizontalAnimationCurve: ContainedViewLayoutTransitionCurve = .custom(0.23, 1.0, 0.32, 1.0)
|
public static let horizontalAnimationCurve: ContainedViewLayoutTransitionCurve = .custom(0.23, 1.0, 0.32, 1.0)
|
||||||
|
|
||||||
final class ReplyPanel {
|
final class ReplyPanel {
|
||||||
let titleNode: ASDisplayNode
|
let titleView: UIView
|
||||||
let textNode: ASDisplayNode
|
let textView: UIView
|
||||||
let lineNode: ASDisplayNode
|
let lineView: UIView
|
||||||
let imageNode: ASDisplayNode
|
let imageView: UIView?
|
||||||
let relativeSourceRect: CGRect
|
let relativeSourceRect: CGRect
|
||||||
let relativeTargetRect: CGRect
|
let relativeTargetRect: CGRect
|
||||||
|
|
||||||
init(titleNode: ASDisplayNode, textNode: ASDisplayNode, lineNode: ASDisplayNode, imageNode: ASDisplayNode, relativeSourceRect: CGRect, relativeTargetRect: CGRect) {
|
init(
|
||||||
self.titleNode = titleNode
|
titleView: UIView,
|
||||||
self.textNode = textNode
|
textView: UIView,
|
||||||
self.lineNode = lineNode
|
lineView: UIView,
|
||||||
self.imageNode = imageNode
|
imageView: UIView?,
|
||||||
|
relativeSourceRect: CGRect,
|
||||||
|
relativeTargetRect: CGRect
|
||||||
|
) {
|
||||||
|
self.titleView = titleView
|
||||||
|
self.textView = textView
|
||||||
|
self.lineView = lineView
|
||||||
|
self.imageView = imageView
|
||||||
self.relativeSourceRect = relativeSourceRect
|
self.relativeSourceRect = relativeSourceRect
|
||||||
self.relativeTargetRect = relativeTargetRect
|
self.relativeTargetRect = relativeTargetRect
|
||||||
}
|
}
|
||||||
@ -232,8 +248,8 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case textInput(textInput: TextInput, replyPanel: ReplyAccessoryPanelNode?)
|
case textInput(textInput: TextInput, replyPanel: ChatInputAccessoryPanelView?)
|
||||||
case stickerMediaInput(input: StickerInput, replyPanel: ReplyAccessoryPanelNode?)
|
case stickerMediaInput(input: StickerInput, replyPanel: ChatInputAccessoryPanelView?)
|
||||||
case audioMicInput(AudioMicInput)
|
case audioMicInput(AudioMicInput)
|
||||||
case videoMessage(VideoMessage)
|
case videoMessage(VideoMessage)
|
||||||
case mediaInput(MediaInput)
|
case mediaInput(MediaInput)
|
||||||
@ -403,9 +419,15 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
|
|||||||
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)
|
||||||
|
|
||||||
var sourceReplyPanel: ReplyPanel?
|
var sourceReplyPanel: ReplyPanel?
|
||||||
if let replyPanel = replyPanel, let replyPanelParentView = replyPanel.view.superview {
|
if let replyPanel, let replyPanelTransitionData = replyPanel.transitionData, let replyPanelParentView = replyPanel.superview {
|
||||||
let replyPanelFrame = replyPanel.originalFrameBeforeDismissed ?? replyPanel.frame
|
let replyPanelFrame = replyPanel.frame
|
||||||
var replySourceAbsoluteFrame = replyPanelParentView.convert(replyPanelFrame, to: self.view)
|
var replySourceAbsoluteFrame: CGRect
|
||||||
|
|
||||||
|
if let storedFrameBeforeDismissed = replyPanel.storedFrameBeforeDismissed {
|
||||||
|
replySourceAbsoluteFrame = self.view.convert(storedFrameBeforeDismissed, from: nil)
|
||||||
|
} else {
|
||||||
|
replySourceAbsoluteFrame = replyPanelParentView.convert(replyPanelFrame, to: self.view)
|
||||||
|
}
|
||||||
|
|
||||||
replySourceAbsoluteFrame.origin.x -= sourceAbsoluteRect.minX - self.contextSourceNode.contentRect.minX
|
replySourceAbsoluteFrame.origin.x -= sourceAbsoluteRect.minX - self.contextSourceNode.contentRect.minX
|
||||||
replySourceAbsoluteFrame.origin.y -= sourceAbsoluteRect.minY - self.contextSourceNode.contentRect.minY
|
replySourceAbsoluteFrame.origin.y -= sourceAbsoluteRect.minY - self.contextSourceNode.contentRect.minY
|
||||||
@ -415,7 +437,14 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
|
|||||||
globalTargetFrame.origin.x += sourceAbsoluteRect.minX - targetAbsoluteRect.minX
|
globalTargetFrame.origin.x += sourceAbsoluteRect.minX - targetAbsoluteRect.minX
|
||||||
globalTargetFrame.origin.y += sourceAbsoluteRect.minY - targetAbsoluteRect.minY
|
globalTargetFrame.origin.y += sourceAbsoluteRect.minY - targetAbsoluteRect.minY
|
||||||
|
|
||||||
sourceReplyPanel = ReplyPanel(titleNode: replyPanel.titleNode, textNode: replyPanel.textNode, lineNode: replyPanel.lineNode, imageNode: replyPanel.imageNode, relativeSourceRect: replySourceAbsoluteFrame, relativeTargetRect: globalTargetFrame)
|
sourceReplyPanel = ReplyPanel(
|
||||||
|
titleView: replyPanelTransitionData.titleView,
|
||||||
|
textView: replyPanelTransitionData.textView,
|
||||||
|
lineView: replyPanelTransitionData.lineView,
|
||||||
|
imageView: replyPanelTransitionData.imageView,
|
||||||
|
relativeSourceRect: replySourceAbsoluteFrame,
|
||||||
|
relativeTargetRect: globalTargetFrame
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.itemNode.cancelInsertionAnimations()
|
self.itemNode.cancelInsertionAnimations()
|
||||||
@ -449,13 +478,13 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
|
|||||||
),
|
),
|
||||||
transition: combinedTransition
|
transition: combinedTransition
|
||||||
)
|
)
|
||||||
if let sourceReplyPanel = sourceReplyPanel {
|
if let sourceReplyPanel {
|
||||||
itemNode.animateReplyPanel(
|
itemNode.animateReplyPanel(
|
||||||
sourceReplyPanel: ChatMessageBubbleItemNode.AnimationTransitionReplyPanel(
|
sourceReplyPanel: ChatMessageBubbleItemNode.AnimationTransitionReplyPanel(
|
||||||
titleNode: sourceReplyPanel.titleNode,
|
titleView: sourceReplyPanel.titleView,
|
||||||
textNode: sourceReplyPanel.textNode,
|
textView: sourceReplyPanel.textView,
|
||||||
lineNode: sourceReplyPanel.lineNode,
|
lineView: sourceReplyPanel.lineView,
|
||||||
imageNode: sourceReplyPanel.imageNode,
|
imageView: sourceReplyPanel.imageView,
|
||||||
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
),
|
),
|
||||||
@ -475,10 +504,10 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
|
|||||||
if let sourceReplyPanel = sourceReplyPanel {
|
if let sourceReplyPanel = sourceReplyPanel {
|
||||||
itemNode.animateReplyPanel(
|
itemNode.animateReplyPanel(
|
||||||
sourceReplyPanel: ChatMessageAnimatedStickerItemNode.AnimationTransitionReplyPanel(
|
sourceReplyPanel: ChatMessageAnimatedStickerItemNode.AnimationTransitionReplyPanel(
|
||||||
titleNode: sourceReplyPanel.titleNode,
|
titleView: sourceReplyPanel.titleView,
|
||||||
textNode: sourceReplyPanel.textNode,
|
textView: sourceReplyPanel.textView,
|
||||||
lineNode: sourceReplyPanel.lineNode,
|
lineView: sourceReplyPanel.lineView,
|
||||||
imageNode: sourceReplyPanel.imageNode,
|
imageView: sourceReplyPanel.imageView,
|
||||||
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
),
|
),
|
||||||
@ -498,10 +527,10 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
|
|||||||
if let sourceReplyPanel = sourceReplyPanel {
|
if let sourceReplyPanel = sourceReplyPanel {
|
||||||
itemNode.animateReplyPanel(
|
itemNode.animateReplyPanel(
|
||||||
sourceReplyPanel: ChatMessageStickerItemNode.AnimationTransitionReplyPanel(
|
sourceReplyPanel: ChatMessageStickerItemNode.AnimationTransitionReplyPanel(
|
||||||
titleNode: sourceReplyPanel.titleNode,
|
titleView: sourceReplyPanel.titleView,
|
||||||
textNode: sourceReplyPanel.textNode,
|
textView: sourceReplyPanel.textView,
|
||||||
lineNode: sourceReplyPanel.lineNode,
|
lineView: sourceReplyPanel.lineView,
|
||||||
imageNode: sourceReplyPanel.imageNode,
|
imageView: sourceReplyPanel.imageView,
|
||||||
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
),
|
),
|
||||||
@ -537,12 +566,27 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
|
|||||||
let targetAbsoluteRect = self.contextSourceNode.view.convert(self.contextSourceNode.contentRect, to: self.view)
|
let targetAbsoluteRect = self.contextSourceNode.view.convert(self.contextSourceNode.contentRect, to: self.view)
|
||||||
|
|
||||||
var sourceReplyPanel: ReplyPanel?
|
var sourceReplyPanel: ReplyPanel?
|
||||||
if let replyPanel = replyPanel, let replyPanelParentView = replyPanel.view.superview {
|
if let replyPanel, let replyPanelTransitionData = replyPanel.transitionData, let replyPanelParentView = replyPanel.superview {
|
||||||
var replySourceAbsoluteFrame = replyPanelParentView.convert(replyPanel.originalFrameBeforeDismissed ?? replyPanel.frame, to: self.view)
|
let replyPanelFrame = replyPanel.frame
|
||||||
|
var replySourceAbsoluteFrame: CGRect
|
||||||
|
|
||||||
|
if let storedFrameBeforeDismissed = replyPanel.storedFrameBeforeDismissed {
|
||||||
|
replySourceAbsoluteFrame = self.view.convert(storedFrameBeforeDismissed, from: nil)
|
||||||
|
} else {
|
||||||
|
replySourceAbsoluteFrame = replyPanelParentView.convert(replyPanelFrame, to: self.view)
|
||||||
|
}
|
||||||
|
|
||||||
replySourceAbsoluteFrame.origin.x -= sourceAbsoluteRect.midX - self.contextSourceNode.contentRect.midX
|
replySourceAbsoluteFrame.origin.x -= sourceAbsoluteRect.midX - self.contextSourceNode.contentRect.midX
|
||||||
replySourceAbsoluteFrame.origin.y -= sourceAbsoluteRect.midY - self.contextSourceNode.contentRect.midY
|
replySourceAbsoluteFrame.origin.y -= sourceAbsoluteRect.midY - self.contextSourceNode.contentRect.midY
|
||||||
|
|
||||||
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(
|
||||||
|
titleView: replyPanelTransitionData.titleView,
|
||||||
|
textView: replyPanelTransitionData.textView,
|
||||||
|
lineView: replyPanelTransitionData.lineView,
|
||||||
|
imageView: replyPanelTransitionData.imageView,
|
||||||
|
relativeSourceRect: replySourceAbsoluteFrame,
|
||||||
|
relativeTargetRect: replySourceAbsoluteFrame.offsetBy(dx: 0.0, dy: replySourceAbsoluteFrame.height)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNodeImpl.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNodeImpl.verticalAnimationCurve))
|
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNodeImpl.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNodeImpl.verticalAnimationCurve))
|
||||||
@ -564,10 +608,10 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
|
|||||||
if let sourceReplyPanel = sourceReplyPanel {
|
if let sourceReplyPanel = sourceReplyPanel {
|
||||||
itemNode.animateReplyPanel(
|
itemNode.animateReplyPanel(
|
||||||
sourceReplyPanel: ChatMessageAnimatedStickerItemNode.AnimationTransitionReplyPanel(
|
sourceReplyPanel: ChatMessageAnimatedStickerItemNode.AnimationTransitionReplyPanel(
|
||||||
titleNode: sourceReplyPanel.titleNode,
|
titleView: sourceReplyPanel.titleView,
|
||||||
textNode: sourceReplyPanel.textNode,
|
textView: sourceReplyPanel.textView,
|
||||||
lineNode: sourceReplyPanel.lineNode,
|
lineView: sourceReplyPanel.lineView,
|
||||||
imageNode: sourceReplyPanel.imageNode,
|
imageView: sourceReplyPanel.imageView,
|
||||||
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
),
|
),
|
||||||
@ -588,10 +632,10 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
|
|||||||
if let sourceReplyPanel = sourceReplyPanel {
|
if let sourceReplyPanel = sourceReplyPanel {
|
||||||
itemNode.animateReplyPanel(
|
itemNode.animateReplyPanel(
|
||||||
sourceReplyPanel: ChatMessageStickerItemNode.AnimationTransitionReplyPanel(
|
sourceReplyPanel: ChatMessageStickerItemNode.AnimationTransitionReplyPanel(
|
||||||
titleNode: sourceReplyPanel.titleNode,
|
titleView: sourceReplyPanel.titleView,
|
||||||
textNode: sourceReplyPanel.textNode,
|
textView: sourceReplyPanel.textView,
|
||||||
lineNode: sourceReplyPanel.lineNode,
|
lineView: sourceReplyPanel.lineView,
|
||||||
imageNode: sourceReplyPanel.imageNode,
|
imageView: sourceReplyPanel.imageView,
|
||||||
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
relativeSourceRect: sourceReplyPanel.relativeSourceRect,
|
||||||
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
relativeTargetRect: sourceReplyPanel.relativeTargetRect
|
||||||
),
|
),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user