mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 11:23:48 +00:00
Various fixes
This commit is contained in:
parent
0bf8b373e3
commit
e090872d2f
@ -148,12 +148,12 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
return mediaHidden
|
return mediaHidden
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let makeLabelLayout = TextNodeWithEntities.asyncLayout(self.labelNode)
|
let makeLabelLayout = TextNodeWithEntities.asyncLayout(self.labelNode)
|
||||||
|
|
||||||
let cachedMaskBackgroundImage = self.cachedMaskBackgroundImage
|
let cachedMaskBackgroundImage = self.cachedMaskBackgroundImage
|
||||||
|
|
||||||
return { item, layoutConstants, _, _, _ in
|
return { item, layoutConstants, _, _, _, _ in
|
||||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: true, headerSpacing: 0.0, hidesBackground: .always, forceFullCorners: false, forceAlignment: .center)
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: true, headerSpacing: 0.0, hidesBackground: .always, forceFullCorners: false, forceAlignment: .center)
|
||||||
|
|
||||||
let backgroundImage = PresentationResourcesChat.chatActionPhotoBackgroundImage(item.presentationData.theme.theme, wallpaper: !item.presentationData.theme.wallpaper.isEmpty)
|
let backgroundImage = PresentationResourcesChat.chatActionPhotoBackgroundImage(item.presentationData.theme.theme, wallpaper: !item.presentationData.theme.wallpaper.isEmpty)
|
||||||
|
@ -531,7 +531,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
} else if file.isInstantVideo {
|
} else if file.isInstantVideo {
|
||||||
let displaySize = CGSize(width: 212.0, height: 212.0)
|
let displaySize = CGSize(width: 212.0, height: 212.0)
|
||||||
let automaticDownload = shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: file)
|
let automaticDownload = shouldDownloadMediaAutomatically(settings: automaticDownloadSettings, peerType: associatedData.automaticDownloadPeerType, networkType: associatedData.automaticDownloadNetworkType, authorPeerId: message.author?.id, contactsPeerIds: associatedData.contactsPeerIds, media: file)
|
||||||
let (videoLayout, apply) = contentInstantVideoLayout(ChatMessageBubbleContentItem(context: context, controllerInteraction: controllerInteraction, message: message, topMessage: message, read: messageRead, chatLocation: chatLocation, presentationData: presentationData, associatedData: associatedData, attributes: attributes, isItemPinned: message.tags.contains(.pinned) && !isReplyThread, isItemEdited: false), constrainedSize.width - horizontalInsets.left - horizontalInsets.right, displaySize, displaySize, 0.0, .bubble, automaticDownload)
|
let (videoLayout, apply) = contentInstantVideoLayout(ChatMessageBubbleContentItem(context: context, controllerInteraction: controllerInteraction, message: message, topMessage: message, read: messageRead, chatLocation: chatLocation, presentationData: presentationData, associatedData: associatedData, attributes: attributes, isItemPinned: message.tags.contains(.pinned) && !isReplyThread, isItemEdited: false), constrainedSize.width - horizontalInsets.left - horizontalInsets.right, displaySize, displaySize, 0.0, .bubble, automaticDownload, 0.0)
|
||||||
initialWidth = videoLayout.contentSize.width + videoLayout.overflowLeft + videoLayout.overflowRight
|
initialWidth = videoLayout.contentSize.width + videoLayout.overflowLeft + videoLayout.overflowRight
|
||||||
contentInstantVideoSizeAndApply = (videoLayout, apply)
|
contentInstantVideoSizeAndApply = (videoLayout, apply)
|
||||||
} else if file.isVideo {
|
} else if file.isVideo {
|
||||||
|
@ -28,6 +28,7 @@ struct ChatMessageBubbleContentProperties {
|
|||||||
let forceAlignment: ChatMessageBubbleContentAlignment
|
let forceAlignment: ChatMessageBubbleContentAlignment
|
||||||
let shareButtonOffset: CGPoint?
|
let shareButtonOffset: CGPoint?
|
||||||
let hidesHeaders: Bool
|
let hidesHeaders: Bool
|
||||||
|
let avatarOffset: CGFloat?
|
||||||
|
|
||||||
init(
|
init(
|
||||||
hidesSimpleAuthorHeader: Bool,
|
hidesSimpleAuthorHeader: Bool,
|
||||||
@ -36,7 +37,8 @@ struct ChatMessageBubbleContentProperties {
|
|||||||
forceFullCorners: Bool,
|
forceFullCorners: Bool,
|
||||||
forceAlignment: ChatMessageBubbleContentAlignment,
|
forceAlignment: ChatMessageBubbleContentAlignment,
|
||||||
shareButtonOffset: CGPoint? = nil,
|
shareButtonOffset: CGPoint? = nil,
|
||||||
hidesHeaders: Bool = false
|
hidesHeaders: Bool = false,
|
||||||
|
avatarOffset: CGFloat? = nil
|
||||||
) {
|
) {
|
||||||
self.hidesSimpleAuthorHeader = hidesSimpleAuthorHeader
|
self.hidesSimpleAuthorHeader = hidesSimpleAuthorHeader
|
||||||
self.headerSpacing = headerSpacing
|
self.headerSpacing = headerSpacing
|
||||||
@ -45,6 +47,7 @@ struct ChatMessageBubbleContentProperties {
|
|||||||
self.forceAlignment = forceAlignment
|
self.forceAlignment = forceAlignment
|
||||||
self.shareButtonOffset = shareButtonOffset
|
self.shareButtonOffset = shareButtonOffset
|
||||||
self.hidesHeaders = hidesHeaders
|
self.hidesHeaders = hidesHeaders
|
||||||
|
self.avatarOffset = avatarOffset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +175,7 @@ class ChatMessageBubbleContentNode: ASDisplayNode {
|
|||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
preconditionFailure()
|
preconditionFailure()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1039,7 +1039,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, ListViewItemApply, Bool) -> Void) {
|
override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, ListViewItemApply, Bool) -> Void) {
|
||||||
var currentContentClassesPropertiesAndLayouts: [(Message, AnyClass, Bool, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))))] = []
|
var currentContentClassesPropertiesAndLayouts: [(Message, AnyClass, Bool, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))))] = []
|
||||||
for contentNode in self.contentNodes {
|
for contentNode in self.contentNodes {
|
||||||
if let message = contentNode.item?.message {
|
if let message = contentNode.item?.message {
|
||||||
currentContentClassesPropertiesAndLayouts.append((message, type(of: contentNode) as AnyClass, contentNode.supportsMosaic, contentNode.asyncLayoutContent()))
|
currentContentClassesPropertiesAndLayouts.append((message, type(of: contentNode) as AnyClass, contentNode.supportsMosaic, contentNode.asyncLayoutContent()))
|
||||||
@ -1086,7 +1086,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static func beginLayout(selfReference: Weak<ChatMessageBubbleItemNode>, _ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool,
|
private static func beginLayout(selfReference: Weak<ChatMessageBubbleItemNode>, _ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool,
|
||||||
currentContentClassesPropertiesAndLayouts: [(Message, AnyClass, Bool, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))))],
|
currentContentClassesPropertiesAndLayouts: [(Message, AnyClass, Bool, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))))],
|
||||||
authorNameLayout: (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode),
|
authorNameLayout: (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode),
|
||||||
adminBadgeLayout: (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode),
|
adminBadgeLayout: (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode),
|
||||||
forwardInfoLayout: (ChatPresentationData, PresentationStrings, ChatMessageForwardInfoType, Peer?, String?, String?, CGSize) -> (CGSize, (CGFloat) -> ChatMessageForwardInfoNode),
|
forwardInfoLayout: (ChatPresentationData, PresentationStrings, ChatMessageForwardInfoType, Peer?, String?, String?, CGSize) -> (CGSize, (CGFloat) -> ChatMessageForwardInfoNode),
|
||||||
@ -1135,7 +1135,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
var displayAuthorInfo: Bool
|
var displayAuthorInfo: Bool
|
||||||
var ignoreNameHiding = false
|
var ignoreNameHiding = false
|
||||||
|
|
||||||
let avatarInset: CGFloat
|
var avatarInset: CGFloat
|
||||||
var hasAvatar = false
|
var hasAvatar = false
|
||||||
|
|
||||||
var allowFullWidth = false
|
var allowFullWidth = false
|
||||||
@ -1348,14 +1348,14 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentPropertiesAndPrepareLayouts: [(Message, Bool, ChatMessageEntryAttributes, BubbleItemAttributes, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))))] = []
|
var contentPropertiesAndPrepareLayouts: [(Message, Bool, ChatMessageEntryAttributes, BubbleItemAttributes, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))))] = []
|
||||||
var addedContentNodes: [(Message, Bool, ChatMessageBubbleContentNode)]?
|
var addedContentNodes: [(Message, Bool, ChatMessageBubbleContentNode)]?
|
||||||
for contentNodeItemValue in contentNodeMessagesAndClasses {
|
for contentNodeItemValue in contentNodeMessagesAndClasses {
|
||||||
let contentNodeItem = contentNodeItemValue as (message: Message, type: AnyClass, attributes: ChatMessageEntryAttributes, bubbleAttributes: BubbleItemAttributes)
|
let contentNodeItem = contentNodeItemValue as (message: Message, type: AnyClass, attributes: ChatMessageEntryAttributes, bubbleAttributes: BubbleItemAttributes)
|
||||||
|
|
||||||
var found = false
|
var found = false
|
||||||
for currentNodeItemValue in currentContentClassesPropertiesAndLayouts {
|
for currentNodeItemValue in currentContentClassesPropertiesAndLayouts {
|
||||||
let currentNodeItem = currentNodeItemValue as (message: Message, type: AnyClass, supportsMosaic: Bool, currentLayout: (ChatMessageBubbleContentItem, ChatMessageItemLayoutConstants, ChatMessageBubblePreparePosition, Bool?, CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))))
|
let currentNodeItem = currentNodeItemValue as (message: Message, type: AnyClass, supportsMosaic: Bool, currentLayout: (ChatMessageBubbleContentItem, ChatMessageItemLayoutConstants, ChatMessageBubblePreparePosition, Bool?, CGSize, CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))))
|
||||||
|
|
||||||
if currentNodeItem.type == contentNodeItem.type && currentNodeItem.message.stableId == contentNodeItem.message.stableId {
|
if currentNodeItem.type == contentNodeItem.type && currentNodeItem.message.stableId == contentNodeItem.message.stableId {
|
||||||
contentPropertiesAndPrepareLayouts.append((contentNodeItem.message, currentNodeItem.supportsMosaic, contentNodeItem.attributes, contentNodeItem.bubbleAttributes, currentNodeItem.currentLayout))
|
contentPropertiesAndPrepareLayouts.append((contentNodeItem.message, currentNodeItem.supportsMosaic, contentNodeItem.attributes, contentNodeItem.bubbleAttributes, currentNodeItem.currentLayout))
|
||||||
@ -1529,6 +1529,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
|
|
||||||
var hidesHeaders = false
|
var hidesHeaders = false
|
||||||
var shareButtonOffset: CGPoint?
|
var shareButtonOffset: CGPoint?
|
||||||
|
var avatarOffset: CGFloat?
|
||||||
var index = 0
|
var index = 0
|
||||||
for (message, _, attributes, bubbleAttributes, prepareLayout) in contentPropertiesAndPrepareLayouts {
|
for (message, _, attributes, bubbleAttributes, prepareLayout) in contentPropertiesAndPrepareLayouts {
|
||||||
let topPosition: ChatMessageBubbleRelativePosition
|
let topPosition: ChatMessageBubbleRelativePosition
|
||||||
@ -1581,7 +1582,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (properties, unboundSize, maxNodeWidth, nodeLayout) = prepareLayout(contentItem, layoutConstants, prepareContentPosition, itemSelection, CGSize(width: maximumContentWidth, height: CGFloat.greatestFiniteMagnitude))
|
let (properties, unboundSize, maxNodeWidth, nodeLayout) = prepareLayout(contentItem, layoutConstants, prepareContentPosition, itemSelection, CGSize(width: maximumContentWidth, height: CGFloat.greatestFiniteMagnitude), avatarInset)
|
||||||
maximumNodeWidth = min(maximumNodeWidth, maxNodeWidth)
|
maximumNodeWidth = min(maximumNodeWidth, maxNodeWidth)
|
||||||
|
|
||||||
if let offset = properties.shareButtonOffset {
|
if let offset = properties.shareButtonOffset {
|
||||||
@ -1590,6 +1591,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
if properties.hidesHeaders {
|
if properties.hidesHeaders {
|
||||||
hidesHeaders = true
|
hidesHeaders = true
|
||||||
}
|
}
|
||||||
|
if let offset = properties.avatarOffset {
|
||||||
|
avatarOffset = offset
|
||||||
|
if !offset.isZero {
|
||||||
|
avatarInset = 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
contentPropertiesAndLayouts.append((unboundSize, properties, prepareContentPosition, bubbleAttributes, nodeLayout, needSeparateContainers && !bubbleAttributes.isAttachment ? message.stableId : nil, itemSelection))
|
contentPropertiesAndLayouts.append((unboundSize, properties, prepareContentPosition, bubbleAttributes, nodeLayout, needSeparateContainers && !bubbleAttributes.isAttachment ? message.stableId : nil, itemSelection))
|
||||||
|
|
||||||
@ -2385,6 +2392,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
mosaicStatusSizeAndApply: mosaicStatusSizeAndApply,
|
mosaicStatusSizeAndApply: mosaicStatusSizeAndApply,
|
||||||
needsShareButton: needsShareButton,
|
needsShareButton: needsShareButton,
|
||||||
shareButtonOffset: shareButtonOffset,
|
shareButtonOffset: shareButtonOffset,
|
||||||
|
avatarOffset: avatarOffset,
|
||||||
hidesHeaders: hidesHeaders
|
hidesHeaders: hidesHeaders
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -2431,6 +2439,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
mosaicStatusSizeAndApply: (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageDateAndStatusNode)?,
|
mosaicStatusSizeAndApply: (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageDateAndStatusNode)?,
|
||||||
needsShareButton: Bool,
|
needsShareButton: Bool,
|
||||||
shareButtonOffset: CGPoint?,
|
shareButtonOffset: CGPoint?,
|
||||||
|
avatarOffset: CGFloat?,
|
||||||
hidesHeaders: Bool
|
hidesHeaders: Bool
|
||||||
) -> Void {
|
) -> Void {
|
||||||
guard let strongSelf = selfReference.value else {
|
guard let strongSelf = selfReference.value else {
|
||||||
@ -2489,6 +2498,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
|
|
||||||
strongSelf.backgroundNode.backgroundFrame = backgroundFrame
|
strongSelf.backgroundNode.backgroundFrame = backgroundFrame
|
||||||
|
|
||||||
|
if let avatarOffset = avatarOffset {
|
||||||
|
strongSelf.updateAttachedAvatarNodeOffset(offset: avatarOffset, transition: .animated(duration: 0.3, curve: .spring))
|
||||||
|
}
|
||||||
|
|
||||||
let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp())
|
let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp())
|
||||||
if isFailed {
|
if isFailed {
|
||||||
let deliveryFailedNode: ChatMessageDeliveryFailedNode
|
let deliveryFailedNode: ChatMessageDeliveryFailedNode
|
||||||
@ -2691,6 +2704,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
animateFrame = false
|
animateFrame = false
|
||||||
|
|
||||||
replyInfoNode.visibility = strongSelf.visibility != .none
|
replyInfoNode.visibility = strongSelf.visibility != .none
|
||||||
|
|
||||||
|
if animation.isAnimated {
|
||||||
|
replyInfoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let previousReplyInfoNodeFrame = replyInfoNode.frame
|
let previousReplyInfoNodeFrame = replyInfoNode.frame
|
||||||
replyInfoNode.frame = CGRect(origin: CGPoint(x: contentOrigin.x + layoutConstants.text.bubbleInsets.left, y: layoutConstants.bubble.contentInsets.top + replyInfoOriginY), size: replyInfoSizeApply.0)
|
replyInfoNode.frame = CGRect(origin: CGPoint(x: contentOrigin.x + layoutConstants.text.bubbleInsets.left, y: layoutConstants.bubble.contentInsets.top + replyInfoOriginY), size: replyInfoSizeApply.0)
|
||||||
@ -2700,8 +2717,17 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strongSelf.replyInfoNode?.removeFromSupernode()
|
if animation.isAnimated {
|
||||||
strongSelf.replyInfoNode = nil
|
if let replyInfoNode = strongSelf.replyInfoNode {
|
||||||
|
strongSelf.replyInfoNode = nil
|
||||||
|
replyInfoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, removeOnCompletion: false, completion: { [weak replyInfoNode] _ in
|
||||||
|
replyInfoNode?.removeFromSupernode()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strongSelf.replyInfoNode?.removeFromSupernode()
|
||||||
|
strongSelf.replyInfoNode = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var incomingOffset: CGFloat = 0.0
|
var incomingOffset: CGFloat = 0.0
|
||||||
|
@ -62,11 +62,11 @@ class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||||
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
||||||
|
|
||||||
return { item, layoutConstants, _, _, _ in
|
return { item, layoutConstants, _, _, _, _ in
|
||||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
||||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||||
let incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
let incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
||||||
|
@ -96,11 +96,11 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let makeCountLayout = self.countNode.asyncLayout()
|
let makeCountLayout = self.countNode.asyncLayout()
|
||||||
let makeAlternativeCountLayout = self.alternativeCountNode.asyncLayout()
|
let makeAlternativeCountLayout = self.alternativeCountNode.asyncLayout()
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
||||||
|
|
||||||
let displaySeparator: Bool
|
let displaySeparator: Bool
|
||||||
|
@ -75,7 +75,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
self.view.addGestureRecognizer(tapRecognizer)
|
self.view.addGestureRecognizer(tapRecognizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let statusLayout = self.dateAndStatusNode.asyncLayout()
|
let statusLayout = self.dateAndStatusNode.asyncLayout()
|
||||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||||
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
||||||
@ -84,7 +84,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
let previousContact = self.contact
|
let previousContact = self.contact
|
||||||
let previousContactInfo = self.contactInfo
|
let previousContactInfo = self.contactInfo
|
||||||
|
|
||||||
return { item, layoutConstants, _, _, constrainedSize in
|
return { item, layoutConstants, _, _, constrainedSize, _ in
|
||||||
var selectedContact: TelegramMediaContact?
|
var selectedContact: TelegramMediaContact?
|
||||||
for media in item.message.media {
|
for media in item.message.media {
|
||||||
if let media = media as? TelegramMediaContact {
|
if let media = media as? TelegramMediaContact {
|
||||||
|
@ -27,10 +27,10 @@ final class ChatMessageEventLogPreviousDescriptionContentNode: ChatMessageBubble
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let contentNodeLayout = self.contentNode.asyncLayout()
|
let contentNodeLayout = self.contentNode.asyncLayout()
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||||
var messageEntities: [MessageTextEntity]?
|
var messageEntities: [MessageTextEntity]?
|
||||||
|
|
||||||
for attribute in item.message.attributes {
|
for attribute in item.message.attributes {
|
||||||
|
@ -27,10 +27,10 @@ final class ChatMessageEventLogPreviousLinkContentNode: ChatMessageBubbleContent
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let contentNodeLayout = self.contentNode.asyncLayout()
|
let contentNodeLayout = self.contentNode.asyncLayout()
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||||
var messageEntities: [MessageTextEntity]?
|
var messageEntities: [MessageTextEntity]?
|
||||||
|
|
||||||
for attribute in item.message.attributes {
|
for attribute in item.message.attributes {
|
||||||
|
@ -27,10 +27,10 @@ final class ChatMessageEventLogPreviousMessageContentNode: ChatMessageBubbleCont
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let contentNodeLayout = self.contentNode.asyncLayout()
|
let contentNodeLayout = self.contentNode.asyncLayout()
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||||
var messageEntities: [MessageTextEntity]?
|
var messageEntities: [MessageTextEntity]?
|
||||||
|
|
||||||
for attribute in item.message.attributes {
|
for attribute in item.message.attributes {
|
||||||
|
@ -91,10 +91,10 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let interactiveFileLayout = self.interactiveFileNode.asyncLayout()
|
let interactiveFileLayout = self.interactiveFileNode.asyncLayout()
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, selection, constrainedSize in
|
return { item, layoutConstants, preparePosition, selection, constrainedSize, _ in
|
||||||
var selectedFile: TelegramMediaFile?
|
var selectedFile: TelegramMediaFile?
|
||||||
for media in item.message.media {
|
for media in item.message.media {
|
||||||
if let telegramFile = media as? TelegramMediaFile {
|
if let telegramFile = media as? TelegramMediaFile {
|
||||||
|
@ -41,10 +41,10 @@ final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let contentNodeLayout = self.contentNode.asyncLayout()
|
let contentNodeLayout = self.contentNode.asyncLayout()
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||||
var game: TelegramMediaGame?
|
var game: TelegramMediaGame?
|
||||||
var messageEntities: [MessageTextEntity]?
|
var messageEntities: [MessageTextEntity]?
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
let _ = item.controllerInteraction.openMessage(item.message, .default)
|
let _ = item.controllerInteraction.openMessage(item.message, .default)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
||||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||||
let makeSubtitleLayout = TextNode.asyncLayout(self.subtitleNode)
|
let makeSubtitleLayout = TextNode.asyncLayout(self.subtitleNode)
|
||||||
@ -145,7 +145,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
|
|
||||||
let cachedMaskBackgroundImage = self.cachedMaskBackgroundImage
|
let cachedMaskBackgroundImage = self.cachedMaskBackgroundImage
|
||||||
|
|
||||||
return { item, layoutConstants, _, _, _ in
|
return { item, layoutConstants, _, _, _, _ in
|
||||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: true, headerSpacing: 0.0, hidesBackground: .always, forceFullCorners: false, forceAlignment: .center)
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: true, headerSpacing: 0.0, hidesBackground: .always, forceFullCorners: false, forceAlignment: .center)
|
||||||
|
|
||||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||||
|
@ -29,16 +29,29 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
if case .visible = oldValue {
|
if case .visible = oldValue {
|
||||||
wasVisible = true
|
wasVisible = true
|
||||||
}
|
}
|
||||||
var isVisible = false
|
let isVisible = self.isContentVisible
|
||||||
if case .visible = self.visibility {
|
|
||||||
isVisible = true
|
|
||||||
}
|
|
||||||
if wasVisible != isVisible {
|
if wasVisible != isVisible {
|
||||||
self.interactiveVideoNode.visibility = isVisible
|
if !isVisible {
|
||||||
|
Queue.mainQueue().after(0.05) {
|
||||||
|
if isVisible == self.isContentVisible {
|
||||||
|
self.interactiveVideoNode.visibility = isVisible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.interactiveVideoNode.visibility = isVisible
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var isContentVisible: Bool {
|
||||||
|
var isVisible = false
|
||||||
|
if case .visible = self.visibility {
|
||||||
|
isVisible = true
|
||||||
|
}
|
||||||
|
return isVisible
|
||||||
|
}
|
||||||
|
|
||||||
required init() {
|
required init() {
|
||||||
self.interactiveFileNode = ChatMessageInteractiveFileNode()
|
self.interactiveFileNode = ChatMessageInteractiveFileNode()
|
||||||
self.interactiveVideoNode = ChatMessageInteractiveInstantVideoNode()
|
self.interactiveVideoNode = ChatMessageInteractiveInstantVideoNode()
|
||||||
@ -134,7 +147,7 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let interactiveVideoLayout = self.interactiveVideoNode.asyncLayout()
|
let interactiveVideoLayout = self.interactiveVideoNode.asyncLayout()
|
||||||
let interactiveFileLayout = self.interactiveFileNode.asyncLayout()
|
let interactiveFileLayout = self.interactiveFileNode.asyncLayout()
|
||||||
|
|
||||||
@ -142,7 +155,7 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
let audioTranscriptionState = self.audioTranscriptionState
|
let audioTranscriptionState = self.audioTranscriptionState
|
||||||
let didSetupFileNode = self.item != nil
|
let didSetupFileNode = self.item != nil
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, selection, constrainedSize in
|
return { item, layoutConstants, preparePosition, selection, constrainedSize, avatarInset in
|
||||||
var selectedFile: TelegramMediaFile?
|
var selectedFile: TelegramMediaFile?
|
||||||
for media in item.message.media {
|
for media in item.message.media {
|
||||||
if let telegramFile = media as? TelegramMediaFile {
|
if let telegramFile = media as? TelegramMediaFile {
|
||||||
@ -198,9 +211,7 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
if case .replyThread = item.chatLocation {
|
if case .replyThread = item.chatLocation {
|
||||||
isReplyThread = true
|
isReplyThread = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let avatarInset: CGFloat = 0.0
|
|
||||||
|
|
||||||
var isExpanded = false
|
var isExpanded = false
|
||||||
if case .expanded = audioTranscriptionState {
|
if case .expanded = audioTranscriptionState {
|
||||||
isExpanded = true
|
isExpanded = true
|
||||||
@ -210,23 +221,21 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
let normalDisplaySize = layoutConstants.instantVideo.dimensions
|
let normalDisplaySize = layoutConstants.instantVideo.dimensions
|
||||||
var displaySize = normalDisplaySize
|
var displaySize = normalDisplaySize
|
||||||
let maximumDisplaySize = CGSize(width: min(404, constrainedSize.width - 2.0), height: min(404, constrainedSize.width - 2.0))
|
let maximumDisplaySize = CGSize(width: min(404, constrainedSize.width - 2.0), height: min(404, constrainedSize.width - 2.0))
|
||||||
// var effectiveAvatarInset = avatarInset
|
|
||||||
if item.associatedData.currentlyPlayingMessageId == item.message.index {
|
if item.associatedData.currentlyPlayingMessageId == item.message.index {
|
||||||
isPlaying = true
|
isPlaying = true
|
||||||
if !isExpanded {
|
if !isExpanded {
|
||||||
displaySize = maximumDisplaySize
|
displaySize = maximumDisplaySize
|
||||||
}
|
}
|
||||||
// effectiveAvatarInset = 0.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let leftInset: CGFloat = 0.0
|
let leftInset: CGFloat = 0.0
|
||||||
let rightInset: CGFloat = 0.0
|
let rightInset: CGFloat = 0.0
|
||||||
|
|
||||||
let (videoLayout, videoApply) = interactiveVideoLayout(ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: item.message, topMessage: item.message, read: item.read, chatLocation: item.chatLocation, presentationData: item.presentationData, associatedData: item.associatedData, attributes: item.attributes, isItemPinned: item.message.tags.contains(.pinned) && !isReplyThread, isItemEdited: false), constrainedSize.width - leftInset - rightInset - avatarInset, displaySize, maximumDisplaySize, isPlaying ? 1.0 : 0.0, .free, automaticDownload)
|
let (videoLayout, videoApply) = interactiveVideoLayout(ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: item.message, topMessage: item.message, read: item.read, chatLocation: item.chatLocation, presentationData: item.presentationData, associatedData: item.associatedData, attributes: item.attributes, isItemPinned: item.message.tags.contains(.pinned) && !isReplyThread, isItemEdited: false), constrainedSize.width - leftInset - rightInset - avatarInset, displaySize, maximumDisplaySize, isPlaying ? 1.0 : 0.0, .free, automaticDownload, avatarInset)
|
||||||
|
|
||||||
let videoFrame = CGRect(origin: CGPoint(x: 1.0, y: 1.0), size: videoLayout.contentSize)
|
let videoFrame = CGRect(origin: CGPoint(x: 1.0, y: 1.0), size: videoLayout.contentSize)
|
||||||
|
|
||||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none, shareButtonOffset: isExpanded ? .zero : CGPoint(x: -16.0, y: -24.0), hidesHeaders: !isExpanded)
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none, shareButtonOffset: isExpanded ? .zero : CGPoint(x: -16.0, y: -24.0), hidesHeaders: !isExpanded, avatarOffset: !isExpanded && isPlaying ? -100.0 : 0.0)
|
||||||
|
|
||||||
let width = videoFrame.width + 2.0
|
let width = videoFrame.width + 2.0
|
||||||
|
|
||||||
@ -328,8 +337,10 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var videoAnimation = animation
|
var videoAnimation = animation
|
||||||
|
var fileAnimation = animation
|
||||||
if currentExpanded != isExpanded {
|
if currentExpanded != isExpanded {
|
||||||
videoAnimation = .None
|
videoAnimation = .None
|
||||||
|
fileAnimation = .None
|
||||||
}
|
}
|
||||||
|
|
||||||
animation.animator.updateFrame(layer: strongSelf.interactiveVideoNode.layer, frame: videoFrame, completion: nil)
|
animation.animator.updateFrame(layer: strongSelf.interactiveVideoNode.layer, frame: videoFrame, completion: nil)
|
||||||
@ -337,7 +348,7 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
|
|
||||||
if let fileSize = finalFileSize {
|
if let fileSize = finalFileSize {
|
||||||
strongSelf.interactiveFileNode.frame = CGRect(origin: CGPoint(x: layoutConstants.file.bubbleInsets.left, y: layoutConstants.file.bubbleInsets.top), size: fileSize)
|
strongSelf.interactiveFileNode.frame = CGRect(origin: CGPoint(x: layoutConstants.file.bubbleInsets.left, y: layoutConstants.file.bubbleInsets.top), size: fileSize)
|
||||||
finalFileApply?(synchronousLoads, .None, applyInfo)
|
finalFileApply?(synchronousLoads, fileAnimation, applyInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentExpanded != isExpanded {
|
if currentExpanded != isExpanded {
|
||||||
|
@ -389,7 +389,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||||||
isReplyThread = true
|
isReplyThread = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let (videoLayout, videoApply) = makeVideoLayout(ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: item.message, topMessage: item.content.firstMessage, read: item.read, chatLocation: item.chatLocation, presentationData: item.presentationData, associatedData: item.associatedData, attributes: item.content.firstMessageAttributes, isItemPinned: item.message.tags.contains(.pinned) && !isReplyThread, isItemEdited: false), params.width - params.leftInset - params.rightInset - avatarInset, displaySize, maximumDisplaySize, isPlaying ? 1.0 : 0.0, .free, automaticDownload)
|
let (videoLayout, videoApply) = makeVideoLayout(ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: item.message, topMessage: item.content.firstMessage, read: item.read, chatLocation: item.chatLocation, presentationData: item.presentationData, associatedData: item.associatedData, attributes: item.content.firstMessageAttributes, isItemPinned: item.message.tags.contains(.pinned) && !isReplyThread, isItemEdited: false), params.width - params.leftInset - params.rightInset - avatarInset, displaySize, maximumDisplaySize, isPlaying ? 1.0 : 0.0, .free, automaticDownload, 0.0)
|
||||||
|
|
||||||
let videoFrame = CGRect(origin: CGPoint(x: (incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + effectiveAvatarInset + layoutConstants.bubble.contentInsets.left) : (params.width - params.rightInset - videoLayout.contentSize.width - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - deliveryFailedInset)), y: 0.0), size: videoLayout.contentSize)
|
let videoFrame = CGRect(origin: CGPoint(x: (incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + effectiveAvatarInset + layoutConstants.bubble.contentInsets.left) : (params.width - params.rightInset - videoLayout.contentSize.width - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - deliveryFailedInset)), y: 0.0), size: videoLayout.contentSize)
|
||||||
|
|
||||||
@ -1264,7 +1264,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||||||
effectiveAvatarInset *= (1.0 - scaleProgress)
|
effectiveAvatarInset *= (1.0 - scaleProgress)
|
||||||
displaySize = CGSize(width: initialSize.width + (targetSize.width - initialSize.width) * animationProgress, height: initialSize.height + (targetSize.height - initialSize.height) * animationProgress)
|
displaySize = CGSize(width: initialSize.width + (targetSize.width - initialSize.width) * animationProgress, height: initialSize.height + (targetSize.height - initialSize.height) * animationProgress)
|
||||||
|
|
||||||
let (videoLayout, videoApply) = makeVideoLayout(ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: item.message, topMessage: item.message, read: item.read, chatLocation: item.chatLocation, presentationData: item.presentationData, associatedData: item.associatedData, attributes: item.content.firstMessageAttributes, isItemPinned: item.message.tags.contains(.pinned) && !isReplyThread, isItemEdited: false), params.width - params.leftInset - params.rightInset - avatarInset, displaySize, maximumDisplaySize, scaleProgress, .free, self.appliedAutomaticDownload)
|
let (videoLayout, videoApply) = makeVideoLayout(ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: item.message, topMessage: item.message, read: item.read, chatLocation: item.chatLocation, presentationData: item.presentationData, associatedData: item.associatedData, attributes: item.content.firstMessageAttributes, isItemPinned: item.message.tags.contains(.pinned) && !isReplyThread, isItemEdited: false), params.width - params.leftInset - params.rightInset - avatarInset, displaySize, maximumDisplaySize, scaleProgress, .free, self.appliedAutomaticDownload, 0.0)
|
||||||
|
|
||||||
let availableContentWidth = params.width - params.leftInset - params.rightInset - layoutConstants.bubble.edgeInset * 2.0 - avatarInset - layoutConstants.bubble.contentInsets.left
|
let availableContentWidth = params.width - params.leftInset - params.rightInset - layoutConstants.bubble.edgeInset * 2.0 - avatarInset - layoutConstants.bubble.contentInsets.left
|
||||||
let videoFrame = CGRect(origin: CGPoint(x: (incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + effectiveAvatarInset + layoutConstants.bubble.contentInsets.left) : (params.width - params.rightInset - videoLayout.contentSize.width - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - deliveryFailedInset)), y: 0.0), size: videoLayout.contentSize)
|
let videoFrame = CGRect(origin: CGPoint(x: (incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + effectiveAvatarInset + layoutConstants.bubble.contentInsets.left) : (params.width - params.rightInset - videoLayout.contentSize.width - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - deliveryFailedInset)), y: 0.0), size: videoLayout.contentSize)
|
||||||
|
@ -143,7 +143,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
|||||||
var audioTranscriptionButton: ComponentHostView<Empty>?
|
var audioTranscriptionButton: ComponentHostView<Empty>?
|
||||||
private var transcriptionPendingIndicator: ComponentHostView<Empty>?
|
private var transcriptionPendingIndicator: ComponentHostView<Empty>?
|
||||||
let textNode: TextNode
|
let textNode: TextNode
|
||||||
private let textClippingNode: ASDisplayNode
|
let textClippingNode: ASDisplayNode
|
||||||
private var textSelectionNode: TextSelectionNode?
|
private var textSelectionNode: TextSelectionNode?
|
||||||
|
|
||||||
var updateIsTextSelectionActive: ((Bool) -> Void)?
|
var updateIsTextSelectionActive: ((Bool) -> Void)?
|
||||||
|
@ -17,6 +17,8 @@ import ComponentFlow
|
|||||||
import AudioTranscriptionButtonComponent
|
import AudioTranscriptionButtonComponent
|
||||||
import UndoUI
|
import UndoUI
|
||||||
import TelegramNotices
|
import TelegramNotices
|
||||||
|
import Markdown
|
||||||
|
import TextFormat
|
||||||
|
|
||||||
struct ChatMessageInstantVideoItemLayoutResult {
|
struct ChatMessageInstantVideoItemLayoutResult {
|
||||||
let contentSize: CGSize
|
let contentSize: CGSize
|
||||||
@ -30,6 +32,9 @@ enum ChatMessageInstantVideoItemLayoutData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private let textFont = Font.regular(11.0)
|
private let textFont = Font.regular(11.0)
|
||||||
|
private let nameFont = Font.medium(14.0)
|
||||||
|
private let inlineBotPrefixFont = Font.regular(14.0)
|
||||||
|
private let inlineBotNameFont = nameFont
|
||||||
|
|
||||||
enum ChatMessageInteractiveInstantVideoNodeStatusType {
|
enum ChatMessageInteractiveInstantVideoNodeStatusType {
|
||||||
case free
|
case free
|
||||||
@ -48,9 +53,9 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var customIsHidden: Bool = false {
|
var canAttachContent: Bool = false {
|
||||||
didSet {
|
didSet {
|
||||||
if self.customIsHidden != oldValue {
|
if self.canAttachContent != oldValue {
|
||||||
Queue.mainQueue().justDispatch {
|
Queue.mainQueue().justDispatch {
|
||||||
self.videoNode?.canAttachContent = self.shouldAcquireVideoContext
|
self.videoNode?.canAttachContent = self.shouldAcquireVideoContext
|
||||||
}
|
}
|
||||||
@ -73,6 +78,8 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
private var item: ChatMessageBubbleContentItem?
|
private var item: ChatMessageBubbleContentItem?
|
||||||
private var automaticDownload: Bool?
|
private var automaticDownload: Bool?
|
||||||
var media: TelegramMediaFile?
|
var media: TelegramMediaFile?
|
||||||
|
var appliedForwardInfo: (Peer?, String?)?
|
||||||
|
|
||||||
private var secretProgressIcon: UIImage?
|
private var secretProgressIcon: UIImage?
|
||||||
|
|
||||||
private let fetchDisposable = MetaDisposable()
|
private let fetchDisposable = MetaDisposable()
|
||||||
@ -84,6 +91,11 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
private let infoBackgroundNode: ASImageNode
|
private let infoBackgroundNode: ASImageNode
|
||||||
private let muteIconNode: ASImageNode
|
private let muteIconNode: ASImageNode
|
||||||
|
|
||||||
|
var viaBotNode: TextNode?
|
||||||
|
var replyInfoNode: ChatMessageReplyInfoNode?
|
||||||
|
var replyBackgroundNode: NavigationBackgroundNode?
|
||||||
|
var forwardInfoNode: ChatMessageForwardInfoNode?
|
||||||
|
|
||||||
private var status: FileMediaResourceStatus?
|
private var status: FileMediaResourceStatus?
|
||||||
private var playerStatus: MediaPlayerStatus? {
|
private var playerStatus: MediaPlayerStatus? {
|
||||||
didSet {
|
didSet {
|
||||||
@ -97,7 +109,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
private let fetchedThumbnailDisposable = MetaDisposable()
|
private let fetchedThumbnailDisposable = MetaDisposable()
|
||||||
|
|
||||||
private var shouldAcquireVideoContext: Bool {
|
private var shouldAcquireVideoContext: Bool {
|
||||||
if self.visibility && self.trackingIsInHierarchy && !self.customIsHidden {
|
if self.visibility && self.trackingIsInHierarchy && !self.canAttachContent {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -195,10 +207,11 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
self.layer.addSublayer(hierarchyTrackingLayer)
|
self.layer.addSublayer(hierarchyTrackingLayer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func asyncLayout() -> (_ item: ChatMessageBubbleContentItem, _ width: CGFloat, _ displaySize: CGSize, _ maximumDisplaySize: CGSize, _ scaleProgress: CGFloat, _ statusType: ChatMessageInteractiveInstantVideoNodeStatusType, _ automaticDownload: Bool) -> (ChatMessageInstantVideoItemLayoutResult, (ChatMessageInstantVideoItemLayoutData, ListViewItemUpdateAnimation) -> Void) {
|
func asyncLayout() -> (_ item: ChatMessageBubbleContentItem, _ width: CGFloat, _ displaySize: CGSize, _ maximumDisplaySize: CGSize, _ scaleProgress: CGFloat, _ statusType: ChatMessageInteractiveInstantVideoNodeStatusType, _ automaticDownload: Bool, _ avatarInset: CGFloat) -> (ChatMessageInstantVideoItemLayoutResult, (ChatMessageInstantVideoItemLayoutData, ListViewItemUpdateAnimation) -> Void) {
|
||||||
let previousFile = self.media
|
let previousFile = self.media
|
||||||
|
|
||||||
let currentItem = self.item
|
let currentItem = self.item
|
||||||
|
let currentForwardInfo = self.appliedForwardInfo
|
||||||
let previousAutomaticDownload = self.automaticDownload
|
let previousAutomaticDownload = self.automaticDownload
|
||||||
|
|
||||||
let makeDateAndStatusLayout = self.dateAndStatusNode.asyncLayout()
|
let makeDateAndStatusLayout = self.dateAndStatusNode.asyncLayout()
|
||||||
@ -206,14 +219,22 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
let audioTranscriptionState = self.audioTranscriptionState
|
let audioTranscriptionState = self.audioTranscriptionState
|
||||||
let audioTranscriptionText = self.audioTranscriptionText
|
let audioTranscriptionText = self.audioTranscriptionText
|
||||||
|
|
||||||
return { item, width, displaySize, maximumDisplaySize, scaleProgress, statusDisplayType, automaticDownload in
|
let viaBotLayout = TextNode.asyncLayout(self.viaBotNode)
|
||||||
|
let makeReplyInfoLayout = ChatMessageReplyInfoNode.asyncLayout(self.replyInfoNode)
|
||||||
|
let makeForwardInfoLayout = ChatMessageForwardInfoNode.asyncLayout(self.forwardInfoNode)
|
||||||
|
let currentReplyBackgroundNode = self.replyBackgroundNode
|
||||||
|
|
||||||
|
return { item, width, displaySize, maximumDisplaySize, scaleProgress, statusDisplayType, automaticDownload, avatarInset in
|
||||||
var secretVideoPlaceholderBackgroundImage: UIImage?
|
var secretVideoPlaceholderBackgroundImage: UIImage?
|
||||||
var updatedInfoBackgroundImage: UIImage?
|
var updatedInfoBackgroundImage: UIImage?
|
||||||
var updatedMuteIconImage: UIImage?
|
var updatedMuteIconImage: UIImage?
|
||||||
|
|
||||||
|
var viaBotApply: (TextNodeLayout, () -> TextNode)?
|
||||||
|
var replyInfoApply: (CGSize, (Bool) -> ChatMessageReplyInfoNode)?
|
||||||
|
var updatedReplyBackgroundNode: NavigationBackgroundNode?
|
||||||
|
|
||||||
var updatedInstantVideoBackgroundImage: UIImage?
|
var updatedInstantVideoBackgroundImage: UIImage?
|
||||||
let instantVideoBackgroundImage: UIImage?
|
let instantVideoBackgroundImage: UIImage?
|
||||||
|
|
||||||
switch statusDisplayType {
|
switch statusDisplayType {
|
||||||
case .free:
|
case .free:
|
||||||
instantVideoBackgroundImage = nil
|
instantVideoBackgroundImage = nil
|
||||||
@ -260,6 +281,115 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ignoreForward = false
|
||||||
|
var ignoreSource = false
|
||||||
|
|
||||||
|
if let forwardInfo = item.message.forwardInfo {
|
||||||
|
if !item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) {
|
||||||
|
for attribute in item.message.attributes {
|
||||||
|
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
||||||
|
if attribute.messageId.peerId == forwardInfo.author?.id {
|
||||||
|
ignoreForward = true
|
||||||
|
} else {
|
||||||
|
ignoreSource = true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ignoreForward = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let bubbleEdgeInset: CGFloat = 4.0
|
||||||
|
let bubbleContentInsetsLeft: CGFloat = 6.0
|
||||||
|
let availableWidth = max(60.0, width - 210.0 - bubbleEdgeInset * 2.0 - bubbleContentInsetsLeft - 20.0)
|
||||||
|
let availableContentWidth = width - bubbleEdgeInset * 2.0 - bubbleContentInsetsLeft - 20.0
|
||||||
|
|
||||||
|
for attribute in item.message.attributes {
|
||||||
|
if let attribute = attribute as? InlineBotMessageAttribute {
|
||||||
|
var inlineBotNameString: String?
|
||||||
|
if let peerId = attribute.peerId, let bot = item.message.peers[peerId] as? TelegramUser {
|
||||||
|
inlineBotNameString = bot.addressName
|
||||||
|
} else {
|
||||||
|
inlineBotNameString = attribute.title
|
||||||
|
}
|
||||||
|
|
||||||
|
if let inlineBotNameString = inlineBotNameString {
|
||||||
|
let inlineBotNameColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper).primaryText
|
||||||
|
|
||||||
|
let bodyAttributes = MarkdownAttributeSet(font: nameFont, textColor: inlineBotNameColor)
|
||||||
|
let boldAttributes = MarkdownAttributeSet(font: inlineBotPrefixFont, textColor: inlineBotNameColor)
|
||||||
|
let botString = addAttributesToStringWithRanges(item.presentationData.strings.Conversation_MessageViaUser("@\(inlineBotNameString)")._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
|
||||||
|
|
||||||
|
viaBotApply = viaBotLayout(TextNodeLayoutArguments(attributedString: botString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0, availableWidth), height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
|
ignoreForward = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let replyAttribute = attribute as? ReplyMessageAttribute, let replyMessage = item.message.associatedMessages[replyAttribute.messageId] {
|
||||||
|
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId {
|
||||||
|
} else {
|
||||||
|
replyInfoApply = makeReplyInfoLayout(ChatMessageReplyInfoNode.Arguments(
|
||||||
|
presentationData: item.presentationData,
|
||||||
|
strings: item.presentationData.strings,
|
||||||
|
context: item.context,
|
||||||
|
type: .standalone,
|
||||||
|
message: replyMessage,
|
||||||
|
parentMessage: item.message,
|
||||||
|
constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude),
|
||||||
|
animationCache: item.controllerInteraction.presentationContext.animationCache,
|
||||||
|
animationRenderer: item.controllerInteraction.presentationContext.animationRenderer
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ignoreSource, !item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) {
|
||||||
|
for attribute in item.message.attributes {
|
||||||
|
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
||||||
|
if let sourcePeer = item.message.peers[attribute.messageId.peerId] {
|
||||||
|
let inlineBotNameColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper).primaryText
|
||||||
|
|
||||||
|
let nameString = NSAttributedString(string: EnginePeer(sourcePeer).displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder), font: inlineBotPrefixFont, textColor: inlineBotNameColor)
|
||||||
|
|
||||||
|
viaBotApply = viaBotLayout(TextNodeLayoutArguments(attributedString: nameString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0, availableWidth), height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var forwardSource: Peer?
|
||||||
|
var forwardAuthorSignature: String?
|
||||||
|
|
||||||
|
var forwardInfoSizeApply: (CGSize, (CGFloat) -> ChatMessageForwardInfoNode)?
|
||||||
|
|
||||||
|
if !ignoreForward, let forwardInfo = item.message.forwardInfo {
|
||||||
|
let forwardPsaType = forwardInfo.psaType
|
||||||
|
|
||||||
|
if let source = forwardInfo.source {
|
||||||
|
forwardSource = source
|
||||||
|
if let authorSignature = forwardInfo.authorSignature {
|
||||||
|
forwardAuthorSignature = authorSignature
|
||||||
|
} else if let forwardInfoAuthor = forwardInfo.author, forwardInfoAuthor.id != source.id {
|
||||||
|
forwardAuthorSignature = EnginePeer(forwardInfoAuthor).displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
|
||||||
|
} else {
|
||||||
|
forwardAuthorSignature = nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let currentForwardInfo = currentForwardInfo, forwardInfo.author == nil && currentForwardInfo.0 != nil {
|
||||||
|
forwardSource = nil
|
||||||
|
forwardAuthorSignature = currentForwardInfo.0.flatMap(EnginePeer.init)?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
|
||||||
|
} else {
|
||||||
|
forwardSource = forwardInfo.author
|
||||||
|
forwardAuthorSignature = forwardInfo.authorSignature
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let availableWidth = max(60.0, availableContentWidth - 210.0 + 6.0)
|
||||||
|
forwardInfoSizeApply = makeForwardInfoLayout(item.presentationData, item.presentationData.strings, .standalone, forwardSource, forwardAuthorSignature, forwardPsaType, CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude))
|
||||||
|
}
|
||||||
|
|
||||||
var notConsumed = false
|
var notConsumed = false
|
||||||
for attribute in item.message.attributes {
|
for attribute in item.message.attributes {
|
||||||
if let attribute = attribute as? ConsumableContentMessageAttribute {
|
if let attribute = attribute as? ConsumableContentMessageAttribute {
|
||||||
@ -412,10 +542,21 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
|
|
||||||
let effectiveAudioTranscriptionState = updatedAudioTranscriptionState ?? audioTranscriptionState
|
let effectiveAudioTranscriptionState = updatedAudioTranscriptionState ?? audioTranscriptionState
|
||||||
|
|
||||||
|
if replyInfoApply != nil || viaBotApply != nil || forwardInfoSizeApply != nil {
|
||||||
|
if let currentReplyBackgroundNode = currentReplyBackgroundNode {
|
||||||
|
updatedReplyBackgroundNode = currentReplyBackgroundNode
|
||||||
|
} else {
|
||||||
|
updatedReplyBackgroundNode = NavigationBackgroundNode(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper))
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedReplyBackgroundNode?.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate)
|
||||||
|
}
|
||||||
|
|
||||||
return (result, { [weak self] layoutData, animation in
|
return (result, { [weak self] layoutData, animation in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.item = item
|
strongSelf.item = item
|
||||||
strongSelf.videoFrame = displayVideoFrame
|
strongSelf.videoFrame = displayVideoFrame
|
||||||
|
strongSelf.appliedForwardInfo = (forwardSource, forwardAuthorSignature)
|
||||||
strongSelf.secretProgressIcon = secretProgressIcon
|
strongSelf.secretProgressIcon = secretProgressIcon
|
||||||
strongSelf.automaticDownload = automaticDownload
|
strongSelf.automaticDownload = automaticDownload
|
||||||
|
|
||||||
@ -737,6 +878,112 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
strongSelf.dateAndStatusNode.pressed = nil
|
strongSelf.dateAndStatusNode.pressed = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let updatedReplyBackgroundNode = updatedReplyBackgroundNode {
|
||||||
|
if strongSelf.replyBackgroundNode == nil {
|
||||||
|
strongSelf.replyBackgroundNode = updatedReplyBackgroundNode
|
||||||
|
strongSelf.addSubnode(updatedReplyBackgroundNode)
|
||||||
|
}
|
||||||
|
} else if let replyBackgroundNode = strongSelf.replyBackgroundNode {
|
||||||
|
replyBackgroundNode.removeFromSupernode()
|
||||||
|
strongSelf.replyBackgroundNode = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var messageInfoSize = CGSize()
|
||||||
|
if let (viaBotLayout, _) = viaBotApply, forwardInfoSizeApply == nil {
|
||||||
|
messageInfoSize = CGSize(width: viaBotLayout.size.width + 1.0, height: 0.0)
|
||||||
|
}
|
||||||
|
if let (forwardInfoSize, _) = forwardInfoSizeApply {
|
||||||
|
messageInfoSize = CGSize(width: max(messageInfoSize.width, forwardInfoSize.width + 2.0), height: 0.0)
|
||||||
|
}
|
||||||
|
if let (replyInfoSize, _) = replyInfoApply {
|
||||||
|
messageInfoSize = CGSize(width: max(messageInfoSize.width, replyInfoSize.width), height: 0.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var width = width
|
||||||
|
if !scaleProgress.isZero {
|
||||||
|
width += avatarInset
|
||||||
|
}
|
||||||
|
if let (viaBotLayout, viaBotApply) = viaBotApply, forwardInfoSizeApply == nil {
|
||||||
|
let viaBotNode = viaBotApply()
|
||||||
|
if strongSelf.viaBotNode == nil {
|
||||||
|
strongSelf.viaBotNode = viaBotNode
|
||||||
|
strongSelf.addSubnode(viaBotNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
let viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? 11.0 : (width - messageInfoSize.width - bubbleEdgeInset - 9.0 + 10.0)), y: 8.0), size: viaBotLayout.size)
|
||||||
|
animation.animator.updateFrame(layer: viaBotNode.layer, frame: viaBotFrame, completion: nil)
|
||||||
|
|
||||||
|
messageInfoSize = CGSize(width: messageInfoSize.width, height: viaBotLayout.size.height)
|
||||||
|
} else if let viaBotNode = strongSelf.viaBotNode {
|
||||||
|
viaBotNode.removeFromSupernode()
|
||||||
|
strongSelf.viaBotNode = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (forwardInfoSize, forwardInfoApply) = forwardInfoSizeApply {
|
||||||
|
let forwardInfoNode = forwardInfoApply(forwardInfoSize.width)
|
||||||
|
if strongSelf.forwardInfoNode == nil {
|
||||||
|
strongSelf.forwardInfoNode = forwardInfoNode
|
||||||
|
strongSelf.addSubnode(forwardInfoNode)
|
||||||
|
|
||||||
|
if animation.isAnimated {
|
||||||
|
forwardInfoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let forwardInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? 12.0 : (width - messageInfoSize.width - bubbleEdgeInset - 8.0 + 10.0)), y: 8.0 + messageInfoSize.height), size: forwardInfoSize)
|
||||||
|
animation.animator.updateFrame(layer: forwardInfoNode.layer, frame: forwardInfoFrame, completion: nil)
|
||||||
|
|
||||||
|
messageInfoSize = CGSize(width: messageInfoSize.width, height: messageInfoSize.height + forwardInfoSize.height - 1.0)
|
||||||
|
} else if let forwardInfoNode = strongSelf.forwardInfoNode {
|
||||||
|
if animation.isAnimated {
|
||||||
|
if let forwardInfoNode = strongSelf.forwardInfoNode {
|
||||||
|
strongSelf.forwardInfoNode = nil
|
||||||
|
forwardInfoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, removeOnCompletion: false, completion: { [weak forwardInfoNode] _ in
|
||||||
|
forwardInfoNode?.removeFromSupernode()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
forwardInfoNode.removeFromSupernode()
|
||||||
|
strongSelf.forwardInfoNode = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
||||||
|
let replyInfoNode = replyInfoApply(false)
|
||||||
|
if strongSelf.replyInfoNode == nil {
|
||||||
|
strongSelf.replyInfoNode = replyInfoNode
|
||||||
|
strongSelf.addSubnode(replyInfoNode)
|
||||||
|
}
|
||||||
|
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (bubbleEdgeInset + 11.0) : (width - messageInfoSize.width - bubbleEdgeInset - 9.0 + 10.0)), y: 8.0 + messageInfoSize.height), size: replyInfoSize)
|
||||||
|
animation.animator.updateFrame(layer: replyInfoNode.layer, frame: replyInfoFrame, completion: nil)
|
||||||
|
|
||||||
|
messageInfoSize = CGSize(width: max(messageInfoSize.width, replyInfoSize.width), height: messageInfoSize.height + replyInfoSize.height)
|
||||||
|
} else if let replyInfoNode = strongSelf.replyInfoNode {
|
||||||
|
replyInfoNode.removeFromSupernode()
|
||||||
|
strongSelf.replyInfoNode = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let replyBackgroundNode = strongSelf.replyBackgroundNode {
|
||||||
|
let replyBackgroundFrame = CGRect(origin: CGPoint(x: (!incoming ? (bubbleEdgeInset + 10.0) : (width - messageInfoSize.width - bubbleEdgeInset)) - 4.0, y: 6.0), size: CGSize(width: messageInfoSize.width + 8.0, height: messageInfoSize.height + 5.0))
|
||||||
|
animation.animator.updateFrame(layer: replyBackgroundNode.layer, frame: replyBackgroundFrame, completion: nil)
|
||||||
|
|
||||||
|
let cornerRadius = replyBackgroundNode.frame.height <= 22.0 ? replyBackgroundNode.frame.height / 2.0 : 8.0
|
||||||
|
replyBackgroundNode.update(size: replyBackgroundNode.bounds.size, cornerRadius: cornerRadius, transition: .immediate)
|
||||||
|
}
|
||||||
|
|
||||||
|
let transition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
|
||||||
|
if let viaBotNode = strongSelf.viaBotNode {
|
||||||
|
transition.updateAlpha(node: viaBotNode, alpha: strongSelf.isPlaying ? 0.0 : 1.0)
|
||||||
|
}
|
||||||
|
if let replyBackgroundNode = strongSelf.replyBackgroundNode {
|
||||||
|
transition.updateAlpha(node: replyBackgroundNode, alpha: strongSelf.isPlaying ? 0.0 : 1.0)
|
||||||
|
}
|
||||||
|
if let forwardInfoNode = strongSelf.forwardInfoNode {
|
||||||
|
transition.updateAlpha(node: forwardInfoNode, alpha: strongSelf.isPlaying ? 0.0 : 1.0)
|
||||||
|
}
|
||||||
|
if let replyInfoNode = strongSelf.replyInfoNode {
|
||||||
|
transition.updateAlpha(node: replyInfoNode, alpha: strongSelf.isPlaying ? 0.0 : 1.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -962,6 +1209,39 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
|
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
|
||||||
switch gesture {
|
switch gesture {
|
||||||
case .tap:
|
case .tap:
|
||||||
|
if let replyInfoNode = self.replyInfoNode, replyInfoNode.frame.contains(location) {
|
||||||
|
if let item = self.item {
|
||||||
|
for attribute in item.message.attributes {
|
||||||
|
if let attribute = attribute as? ReplyMessageAttribute {
|
||||||
|
item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let forwardInfoNode = self.forwardInfoNode, forwardInfoNode.frame.contains(location) {
|
||||||
|
if let item = self.item, let forwardInfo = item.message.forwardInfo {
|
||||||
|
if let sourceMessageId = forwardInfo.sourceMessageId {
|
||||||
|
if !item.message.id.peerId.isReplies, let channel = forwardInfo.author as? TelegramChannel, channel.addressName == nil {
|
||||||
|
if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) {
|
||||||
|
} else if case .member = channel.participationStatus {
|
||||||
|
} else {
|
||||||
|
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_PrivateChannelTooltip, forwardInfoNode, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId)
|
||||||
|
return
|
||||||
|
} else if let peer = forwardInfo.source ?? forwardInfo.author {
|
||||||
|
item.controllerInteraction.openPeer(EnginePeer(peer), peer is TelegramUser ? .info : .chat(textInputState: nil, subject: nil, peekData: nil), nil, false)
|
||||||
|
return
|
||||||
|
} else if let _ = forwardInfo.authorSignature {
|
||||||
|
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, forwardInfoNode, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if let audioTranscriptionButton = self.audioTranscriptionButton, !audioTranscriptionButton.isHidden, audioTranscriptionButton.frame.contains(location) {
|
if let audioTranscriptionButton = self.audioTranscriptionButton, !audioTranscriptionButton.isHidden, audioTranscriptionButton.frame.contains(location) {
|
||||||
self.transcribe()
|
self.transcribe()
|
||||||
return
|
return
|
||||||
@ -1007,9 +1287,6 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
if !self.bounds.contains(point) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if let audioTranscriptionButton = self.audioTranscriptionButton, !audioTranscriptionButton.isHidden, audioTranscriptionButton.frame.contains(point) {
|
if let audioTranscriptionButton = self.audioTranscriptionButton, !audioTranscriptionButton.isHidden, audioTranscriptionButton.frame.contains(point) {
|
||||||
return audioTranscriptionButton
|
return audioTranscriptionButton
|
||||||
}
|
}
|
||||||
@ -1021,6 +1298,12 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
return playbackNode.view
|
return playbackNode.view
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let forwardInfoNode = self.forwardInfoNode, forwardInfoNode.frame.contains(point), !forwardInfoNode.alpha.isZero {
|
||||||
|
return self.view
|
||||||
|
}
|
||||||
|
if let replyInfoNode = self.replyInfoNode, replyInfoNode.frame.contains(point), !replyInfoNode.alpha.isZero {
|
||||||
|
return self.view
|
||||||
|
}
|
||||||
if let statusNode = self.statusNode, statusNode.supernode != nil, !statusNode.isHidden, statusNode.frame.contains(point) {
|
if let statusNode = self.statusNode, statusNode.supernode != nil, !statusNode.isHidden, statusNode.frame.contains(point) {
|
||||||
return self.view
|
return self.view
|
||||||
}
|
}
|
||||||
@ -1028,6 +1311,9 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
if let videoNode = self.videoNode, videoNode.frame.contains(point) {
|
if let videoNode = self.videoNode, videoNode.frame.contains(point) {
|
||||||
return self.view
|
return self.view
|
||||||
}
|
}
|
||||||
|
if !self.bounds.contains(point) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return super.hitTest(point, with: event)
|
return super.hitTest(point, with: event)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1072,16 +1358,16 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
static func asyncLayout(_ node: ChatMessageInteractiveInstantVideoNode?) -> (_ item: ChatMessageBubbleContentItem, _ width: CGFloat, _ displaySize: CGSize, _ maximumDisplaySize: CGSize, _ scaleProgress: CGFloat, _ statusType: ChatMessageInteractiveInstantVideoNodeStatusType, _ automaticDownload: Bool) -> (ChatMessageInstantVideoItemLayoutResult, (ChatMessageInstantVideoItemLayoutData, ListViewItemUpdateAnimation) -> ChatMessageInteractiveInstantVideoNode) {
|
static func asyncLayout(_ node: ChatMessageInteractiveInstantVideoNode?) -> (_ item: ChatMessageBubbleContentItem, _ width: CGFloat, _ displaySize: CGSize, _ maximumDisplaySize: CGSize, _ scaleProgress: CGFloat, _ statusType: ChatMessageInteractiveInstantVideoNodeStatusType, _ automaticDownload: Bool, _ avatarInset: CGFloat) -> (ChatMessageInstantVideoItemLayoutResult, (ChatMessageInstantVideoItemLayoutData, ListViewItemUpdateAnimation) -> ChatMessageInteractiveInstantVideoNode) {
|
||||||
let makeLayout = node?.asyncLayout()
|
let makeLayout = node?.asyncLayout()
|
||||||
return { item, width, displaySize, maximumDisplaySize, scaleProgress, statusType, automaticDownload in
|
return { item, width, displaySize, maximumDisplaySize, scaleProgress, statusType, automaticDownload, avatarInset in
|
||||||
var createdNode: ChatMessageInteractiveInstantVideoNode?
|
var createdNode: ChatMessageInteractiveInstantVideoNode?
|
||||||
let sizeAndApplyLayout: (ChatMessageInstantVideoItemLayoutResult, (ChatMessageInstantVideoItemLayoutData, ListViewItemUpdateAnimation) -> Void)
|
let sizeAndApplyLayout: (ChatMessageInstantVideoItemLayoutResult, (ChatMessageInstantVideoItemLayoutData, ListViewItemUpdateAnimation) -> Void)
|
||||||
if let makeLayout = makeLayout {
|
if let makeLayout = makeLayout {
|
||||||
sizeAndApplyLayout = makeLayout(item, width, displaySize, maximumDisplaySize, scaleProgress, statusType, automaticDownload)
|
sizeAndApplyLayout = makeLayout(item, width, displaySize, maximumDisplaySize, scaleProgress, statusType, automaticDownload, avatarInset)
|
||||||
} else {
|
} else {
|
||||||
let node = ChatMessageInteractiveInstantVideoNode()
|
let node = ChatMessageInteractiveInstantVideoNode()
|
||||||
sizeAndApplyLayout = node.asyncLayout()(item, width, displaySize, maximumDisplaySize, scaleProgress, statusType, automaticDownload)
|
sizeAndApplyLayout = node.asyncLayout()(item, width, displaySize, maximumDisplaySize, scaleProgress, statusType, automaticDownload, avatarInset)
|
||||||
createdNode = node
|
createdNode = node
|
||||||
}
|
}
|
||||||
return (sizeAndApplyLayout.0, { [weak node] layoutData, transition in
|
return (sizeAndApplyLayout.0, { [weak node] layoutData, transition in
|
||||||
@ -1275,7 +1561,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
let targetFrame = targetNode.view.convert(targetNode.bounds, to: self.view)
|
let targetFrame = targetNode.view.convert(targetNode.bounds, to: self.view)
|
||||||
animator.animatePosition(layer: videoNode.layer, from: videoNode.position, to: targetFrame.center, completion: { _ in
|
animator.animatePosition(layer: videoNode.layer, from: videoNode.position, to: targetFrame.center, completion: { _ in
|
||||||
self.isHidden = true
|
self.isHidden = true
|
||||||
self.customIsHidden = true
|
self.canAttachContent = true
|
||||||
})
|
})
|
||||||
let targetScale = targetNode.frame.width / videoNode.bounds.width
|
let targetScale = targetNode.frame.width / videoNode.bounds.width
|
||||||
animator.animateScale(layer: videoNode.layer, from: self.imageScale, to: targetScale, completion: nil)
|
animator.animateScale(layer: videoNode.layer, from: self.imageScale, to: targetScale, completion: nil)
|
||||||
@ -1297,8 +1583,21 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
targetNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
targetNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||||
|
|
||||||
let verticalDelta = (videoNode.position.y - targetFrame.center.y) * 2.0
|
let verticalDelta = (videoNode.position.y - targetFrame.center.y) * 2.0
|
||||||
animator.animatePosition(layer: node.textNode.layer, from: node.textNode.position.offsetBy(dx: 0.0, dy: verticalDelta), to: node.textNode.position, completion: nil)
|
animator.animatePosition(layer: node.textClippingNode.layer, from: node.textClippingNode.position.offsetBy(dx: 0.0, dy: verticalDelta), to: node.textClippingNode.position, completion: nil)
|
||||||
node.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
node.textClippingNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||||
|
|
||||||
|
if let maskImage = generateGradientImage(size: CGSize(width: 8.0, height: 10.0), colors: [UIColor.black, UIColor.black, UIColor.clear], locations: [0.0, 0.1, 1.0], direction: .vertical) {
|
||||||
|
let textClippingFrame = node.textClippingNode.frame
|
||||||
|
|
||||||
|
let maskView = UIImageView(image: maskImage.stretchableImage(withLeftCapWidth: 0, topCapHeight: 1))
|
||||||
|
node.textClippingNode.view.mask = maskView
|
||||||
|
|
||||||
|
maskView.frame = CGRect(origin: CGPoint(), size: CGSize(width: textClippingFrame.width, height: maskImage.size.height))
|
||||||
|
animator.updateFrame(layer: maskView.layer, frame: CGRect(origin: CGPoint(), size: textClippingFrame.size), completion: { [weak maskView, weak node] _ in
|
||||||
|
maskView?.removeFromSuperview()
|
||||||
|
node?.textClippingNode.view.mask = nil
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let audioTranscriptionButton = self.audioTranscriptionButton, let targetAudioTranscriptionButton = node.audioTranscriptionButton {
|
if let audioTranscriptionButton = self.audioTranscriptionButton, let targetAudioTranscriptionButton = node.audioTranscriptionButton {
|
||||||
@ -1335,6 +1634,19 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
|
|
||||||
node.fetchingTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration - 0.05, delay: 0.05)
|
node.fetchingTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration - 0.05, delay: 0.05)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let viaBotNode = self.viaBotNode {
|
||||||
|
viaBotNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
||||||
|
}
|
||||||
|
if let replyBackgroundNode = self.replyBackgroundNode {
|
||||||
|
replyBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
||||||
|
}
|
||||||
|
if let forwardInfoNode = self.forwardInfoNode {
|
||||||
|
forwardInfoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
||||||
|
}
|
||||||
|
if let replyInfoNode = self.replyInfoNode {
|
||||||
|
replyInfoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateFrom(_ node: ChatMessageInteractiveFileNode, animator: ControlledTransitionAnimator) {
|
func animateFrom(_ node: ChatMessageInteractiveFileNode, animator: ControlledTransitionAnimator) {
|
||||||
@ -1374,8 +1686,21 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
sourceNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
sourceNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
||||||
|
|
||||||
let verticalDelta = (videoNode.position.y - sourceFrame.center.y) * 2.0
|
let verticalDelta = (videoNode.position.y - sourceFrame.center.y) * 2.0
|
||||||
animator.animatePosition(layer: node.textNode.layer, from: node.textNode.position, to: node.textNode.position.offsetBy(dx: 0.0, dy: verticalDelta), completion: nil)
|
animator.animatePosition(layer: node.textClippingNode.layer, from: node.textClippingNode.position, to: node.textClippingNode.position.offsetBy(dx: 0.0, dy: verticalDelta), completion: nil)
|
||||||
node.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
node.textClippingNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
||||||
|
|
||||||
|
if let maskImage = generateGradientImage(size: CGSize(width: 8.0, height: 10.0), colors: [UIColor.black, UIColor.black, UIColor.clear], locations: [0.0, 0.1, 1.0], direction: .vertical) {
|
||||||
|
let textClippingFrame = node.textClippingNode.frame
|
||||||
|
|
||||||
|
let maskView = UIImageView(image: maskImage.stretchableImage(withLeftCapWidth: 0, topCapHeight: 1))
|
||||||
|
node.textClippingNode.view.mask = maskView
|
||||||
|
|
||||||
|
maskView.frame = CGRect(origin: CGPoint(), size: textClippingFrame.size)
|
||||||
|
animator.updateFrame(layer: maskView.layer, frame: CGRect(origin: CGPoint(), size: CGSize(width: textClippingFrame.width, height: maskImage.size.height)), completion: { [weak maskView, weak node] _ in
|
||||||
|
maskView?.removeFromSuperview()
|
||||||
|
node?.textClippingNode.view.mask = nil
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let audioTranscriptionButton = self.audioTranscriptionButton, let sourceAudioTranscriptionButton = node.audioTranscriptionButton {
|
if let audioTranscriptionButton = self.audioTranscriptionButton, let sourceAudioTranscriptionButton = node.audioTranscriptionButton {
|
||||||
@ -1413,6 +1738,19 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
node.fetchingTextNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
node.fetchingTextNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.customIsHidden = false
|
if let viaBotNode = self.viaBotNode {
|
||||||
|
viaBotNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||||
|
}
|
||||||
|
if let replyBackgroundNode = self.replyBackgroundNode {
|
||||||
|
replyBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||||
|
}
|
||||||
|
if let forwardInfoNode = self.forwardInfoNode {
|
||||||
|
forwardInfoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||||
|
}
|
||||||
|
if let replyInfoNode = self.replyInfoNode {
|
||||||
|
replyInfoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.canAttachContent = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,10 @@ final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let contentNodeLayout = self.contentNode.asyncLayout()
|
let contentNodeLayout = self.contentNode.asyncLayout()
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||||
var invoice: TelegramMediaInvoice?
|
var invoice: TelegramMediaInvoice?
|
||||||
for media in item.message.media {
|
for media in item.message.media {
|
||||||
if let media = media as? TelegramMediaInvoice {
|
if let media = media as? TelegramMediaInvoice {
|
||||||
|
@ -87,7 +87,7 @@ private func mediaMergeableStyle(_ media: Media) -> ChatMessageMerge {
|
|||||||
return .semanticallyMerged
|
return .semanticallyMerged
|
||||||
case let .Video(_, _, flags):
|
case let .Video(_, _, flags):
|
||||||
if flags.contains(.instantRoundVideo) {
|
if flags.contains(.instantRoundVideo) {
|
||||||
return .semanticallyMerged
|
return .none
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
@ -64,7 +64,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
self.view.addGestureRecognizer(tapRecognizer)
|
self.view.addGestureRecognizer(tapRecognizer)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let makeImageLayout = self.imageNode.asyncLayout()
|
let makeImageLayout = self.imageNode.asyncLayout()
|
||||||
let makePinLayout = self.pinNode.asyncLayout()
|
let makePinLayout = self.pinNode.asyncLayout()
|
||||||
let statusLayout = self.dateAndStatusNode.asyncLayout()
|
let statusLayout = self.dateAndStatusNode.asyncLayout()
|
||||||
@ -73,7 +73,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
|
|
||||||
let previousMedia = self.media
|
let previousMedia = self.media
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||||
var selectedMedia: TelegramMediaMap?
|
var selectedMedia: TelegramMediaMap?
|
||||||
var activeLiveBroadcastingTimeout: Int32?
|
var activeLiveBroadcastingTimeout: Int32?
|
||||||
for media in item.message.media {
|
for media in item.message.media {
|
||||||
|
@ -71,10 +71,10 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let interactiveImageLayout = self.interactiveImageNode.asyncLayout()
|
let interactiveImageLayout = self.interactiveImageNode.asyncLayout()
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, selection, constrainedSize in
|
return { item, layoutConstants, preparePosition, selection, constrainedSize, _ in
|
||||||
var selectedMedia: Media?
|
var selectedMedia: Media?
|
||||||
var automaticDownload: InteractiveMediaNodeAutodownloadMode = .none
|
var automaticDownload: InteractiveMediaNodeAutodownloadMode = .none
|
||||||
var automaticPlayback: Bool = false
|
var automaticPlayback: Bool = false
|
||||||
|
@ -1005,7 +1005,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
||||||
let makeTypeLayout = TextNode.asyncLayout(self.typeNode)
|
let makeTypeLayout = TextNode.asyncLayout(self.typeNode)
|
||||||
let makeVotersLayout = TextNode.asyncLayout(self.votersNode)
|
let makeVotersLayout = TextNode.asyncLayout(self.votersNode)
|
||||||
@ -1030,7 +1030,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { item, layoutConstants, _, _, _ in
|
return { item, layoutConstants, _, _, _, _ in
|
||||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
||||||
|
|
||||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||||
|
@ -511,10 +511,10 @@ final class ChatMessageReactionsFooterContentNode: ChatMessageBubbleContentNode
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let buttonsNode = self.buttonsNode
|
let buttonsNode = self.buttonsNode
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
||||||
|
|
||||||
//let displaySeparator: Bool
|
//let displaySeparator: Bool
|
||||||
|
@ -29,11 +29,11 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let textLayout = TextNode.asyncLayout(self.textNode)
|
let textLayout = TextNode.asyncLayout(self.textNode)
|
||||||
let statusLayout = self.statusNode.asyncLayout()
|
let statusLayout = self.statusNode.asyncLayout()
|
||||||
|
|
||||||
return { item, layoutConstants, _, _, _ in
|
return { item, layoutConstants, _, _, _, _ in
|
||||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
||||||
|
|
||||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||||
|
@ -120,14 +120,14 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let textLayout = TextNodeWithEntities.asyncLayout(self.textNode)
|
let textLayout = TextNodeWithEntities.asyncLayout(self.textNode)
|
||||||
let spoilerTextLayout = TextNodeWithEntities.asyncLayout(self.spoilerTextNode)
|
let spoilerTextLayout = TextNodeWithEntities.asyncLayout(self.spoilerTextNode)
|
||||||
let statusLayout = self.statusNode.asyncLayout()
|
let statusLayout = self.statusNode.asyncLayout()
|
||||||
|
|
||||||
let currentCachedChatMessageText = self.cachedChatMessageText
|
let currentCachedChatMessageText = self.cachedChatMessageText
|
||||||
|
|
||||||
return { item, layoutConstants, _, _, _ in
|
return { item, layoutConstants, _, _, _, _ in
|
||||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
||||||
|
|
||||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||||
|
@ -27,10 +27,10 @@ final class ChatMessageUnsupportedBubbleContentNode: ChatMessageBubbleContentNod
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let makeButtonLayout = ChatMessageAttachedContentButtonNode.asyncLayout(self.buttonNode)
|
let makeButtonLayout = ChatMessageAttachedContentButtonNode.asyncLayout(self.buttonNode)
|
||||||
|
|
||||||
return { item, layoutConstants, _, _, constrainedSize in
|
return { item, layoutConstants, _, _, constrainedSize, _ in
|
||||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
||||||
|
|
||||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||||
|
@ -112,10 +112,10 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let contentNodeLayout = self.contentNode.asyncLayout()
|
let contentNodeLayout = self.contentNode.asyncLayout()
|
||||||
|
|
||||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||||
var webPage: TelegramMediaWebpage?
|
var webPage: TelegramMediaWebpage?
|
||||||
var webPageContent: TelegramMediaWebpageLoadedContent?
|
var webPageContent: TelegramMediaWebpageLoadedContent?
|
||||||
for media in item.message.media {
|
for media in item.message.media {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user