mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Various fixes
This commit is contained in:
parent
0bf8b373e3
commit
e090872d2f
@ -148,12 +148,12 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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 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 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 {
|
||||
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 (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
|
||||
contentInstantVideoSizeAndApply = (videoLayout, apply)
|
||||
} else if file.isVideo {
|
||||
|
@ -28,6 +28,7 @@ struct ChatMessageBubbleContentProperties {
|
||||
let forceAlignment: ChatMessageBubbleContentAlignment
|
||||
let shareButtonOffset: CGPoint?
|
||||
let hidesHeaders: Bool
|
||||
let avatarOffset: CGFloat?
|
||||
|
||||
init(
|
||||
hidesSimpleAuthorHeader: Bool,
|
||||
@ -36,7 +37,8 @@ struct ChatMessageBubbleContentProperties {
|
||||
forceFullCorners: Bool,
|
||||
forceAlignment: ChatMessageBubbleContentAlignment,
|
||||
shareButtonOffset: CGPoint? = nil,
|
||||
hidesHeaders: Bool = false
|
||||
hidesHeaders: Bool = false,
|
||||
avatarOffset: CGFloat? = nil
|
||||
) {
|
||||
self.hidesSimpleAuthorHeader = hidesSimpleAuthorHeader
|
||||
self.headerSpacing = headerSpacing
|
||||
@ -45,6 +47,7 @@ struct ChatMessageBubbleContentProperties {
|
||||
self.forceAlignment = forceAlignment
|
||||
self.shareButtonOffset = shareButtonOffset
|
||||
self.hidesHeaders = hidesHeaders
|
||||
self.avatarOffset = avatarOffset
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +175,7 @@ class ChatMessageBubbleContentNode: ASDisplayNode {
|
||||
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()
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
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 {
|
||||
if let message = contentNode.item?.message {
|
||||
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,
|
||||
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),
|
||||
adminBadgeLayout: (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode),
|
||||
forwardInfoLayout: (ChatPresentationData, PresentationStrings, ChatMessageForwardInfoType, Peer?, String?, String?, CGSize) -> (CGSize, (CGFloat) -> ChatMessageForwardInfoNode),
|
||||
@ -1135,7 +1135,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
var displayAuthorInfo: Bool
|
||||
var ignoreNameHiding = false
|
||||
|
||||
let avatarInset: CGFloat
|
||||
var avatarInset: CGFloat
|
||||
var hasAvatar = 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)]?
|
||||
for contentNodeItemValue in contentNodeMessagesAndClasses {
|
||||
let contentNodeItem = contentNodeItemValue as (message: Message, type: AnyClass, attributes: ChatMessageEntryAttributes, bubbleAttributes: BubbleItemAttributes)
|
||||
|
||||
var found = false
|
||||
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 {
|
||||
contentPropertiesAndPrepareLayouts.append((contentNodeItem.message, currentNodeItem.supportsMosaic, contentNodeItem.attributes, contentNodeItem.bubbleAttributes, currentNodeItem.currentLayout))
|
||||
@ -1529,6 +1529,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
|
||||
var hidesHeaders = false
|
||||
var shareButtonOffset: CGPoint?
|
||||
var avatarOffset: CGFloat?
|
||||
var index = 0
|
||||
for (message, _, attributes, bubbleAttributes, prepareLayout) in contentPropertiesAndPrepareLayouts {
|
||||
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)
|
||||
|
||||
if let offset = properties.shareButtonOffset {
|
||||
@ -1590,6 +1591,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
if properties.hidesHeaders {
|
||||
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))
|
||||
|
||||
@ -2385,6 +2392,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
mosaicStatusSizeAndApply: mosaicStatusSizeAndApply,
|
||||
needsShareButton: needsShareButton,
|
||||
shareButtonOffset: shareButtonOffset,
|
||||
avatarOffset: avatarOffset,
|
||||
hidesHeaders: hidesHeaders
|
||||
)
|
||||
})
|
||||
@ -2431,6 +2439,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
mosaicStatusSizeAndApply: (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageDateAndStatusNode)?,
|
||||
needsShareButton: Bool,
|
||||
shareButtonOffset: CGPoint?,
|
||||
avatarOffset: CGFloat?,
|
||||
hidesHeaders: Bool
|
||||
) -> Void {
|
||||
guard let strongSelf = selfReference.value else {
|
||||
@ -2489,6 +2498,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
|
||||
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())
|
||||
if isFailed {
|
||||
let deliveryFailedNode: ChatMessageDeliveryFailedNode
|
||||
@ -2691,6 +2704,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
animateFrame = false
|
||||
|
||||
replyInfoNode.visibility = strongSelf.visibility != .none
|
||||
|
||||
if animation.isAnimated {
|
||||
replyInfoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
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)
|
||||
@ -2700,8 +2717,17 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
}
|
||||
}
|
||||
} else {
|
||||
strongSelf.replyInfoNode?.removeFromSupernode()
|
||||
strongSelf.replyInfoNode = nil
|
||||
if animation.isAnimated {
|
||||
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
|
||||
|
@ -62,11 +62,11 @@ class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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 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)
|
||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||
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 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 displaySeparator: Bool
|
||||
|
@ -75,7 +75,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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 makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
||||
@ -84,7 +84,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
let previousContact = self.contact
|
||||
let previousContactInfo = self.contactInfo
|
||||
|
||||
return { item, layoutConstants, _, _, constrainedSize in
|
||||
return { item, layoutConstants, _, _, constrainedSize, _ in
|
||||
var selectedContact: TelegramMediaContact?
|
||||
for media in item.message.media {
|
||||
if let media = media as? TelegramMediaContact {
|
||||
|
@ -27,10 +27,10 @@ final class ChatMessageEventLogPreviousDescriptionContentNode: ChatMessageBubble
|
||||
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()
|
||||
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||
var messageEntities: [MessageTextEntity]?
|
||||
|
||||
for attribute in item.message.attributes {
|
||||
|
@ -27,10 +27,10 @@ final class ChatMessageEventLogPreviousLinkContentNode: ChatMessageBubbleContent
|
||||
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()
|
||||
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||
var messageEntities: [MessageTextEntity]?
|
||||
|
||||
for attribute in item.message.attributes {
|
||||
|
@ -27,10 +27,10 @@ final class ChatMessageEventLogPreviousMessageContentNode: ChatMessageBubbleCont
|
||||
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()
|
||||
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||
var messageEntities: [MessageTextEntity]?
|
||||
|
||||
for attribute in item.message.attributes {
|
||||
|
@ -91,10 +91,10 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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()
|
||||
|
||||
return { item, layoutConstants, preparePosition, selection, constrainedSize in
|
||||
return { item, layoutConstants, preparePosition, selection, constrainedSize, _ in
|
||||
var selectedFile: TelegramMediaFile?
|
||||
for media in item.message.media {
|
||||
if let telegramFile = media as? TelegramMediaFile {
|
||||
|
@ -41,10 +41,10 @@ final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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()
|
||||
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||
var game: TelegramMediaGame?
|
||||
var messageEntities: [MessageTextEntity]?
|
||||
|
||||
|
@ -137,7 +137,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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 makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
let makeSubtitleLayout = TextNode.asyncLayout(self.subtitleNode)
|
||||
@ -145,7 +145,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
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)
|
||||
|
||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||
|
@ -29,16 +29,29 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
if case .visible = oldValue {
|
||||
wasVisible = true
|
||||
}
|
||||
var isVisible = false
|
||||
if case .visible = self.visibility {
|
||||
isVisible = true
|
||||
}
|
||||
let isVisible = self.isContentVisible
|
||||
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() {
|
||||
self.interactiveFileNode = ChatMessageInteractiveFileNode()
|
||||
self.interactiveVideoNode = ChatMessageInteractiveInstantVideoNode()
|
||||
@ -134,7 +147,7 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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 interactiveFileLayout = self.interactiveFileNode.asyncLayout()
|
||||
|
||||
@ -142,7 +155,7 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
let audioTranscriptionState = self.audioTranscriptionState
|
||||
let didSetupFileNode = self.item != nil
|
||||
|
||||
return { item, layoutConstants, preparePosition, selection, constrainedSize in
|
||||
return { item, layoutConstants, preparePosition, selection, constrainedSize, avatarInset in
|
||||
var selectedFile: TelegramMediaFile?
|
||||
for media in item.message.media {
|
||||
if let telegramFile = media as? TelegramMediaFile {
|
||||
@ -199,8 +212,6 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
isReplyThread = true
|
||||
}
|
||||
|
||||
let avatarInset: CGFloat = 0.0
|
||||
|
||||
var isExpanded = false
|
||||
if case .expanded = audioTranscriptionState {
|
||||
isExpanded = true
|
||||
@ -210,23 +221,21 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
let normalDisplaySize = layoutConstants.instantVideo.dimensions
|
||||
var displaySize = normalDisplaySize
|
||||
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 {
|
||||
isPlaying = true
|
||||
if !isExpanded {
|
||||
displaySize = maximumDisplaySize
|
||||
}
|
||||
// effectiveAvatarInset = 0.0
|
||||
}
|
||||
|
||||
let leftInset: 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 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
|
||||
|
||||
@ -328,8 +337,10 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
|
||||
var videoAnimation = animation
|
||||
var fileAnimation = animation
|
||||
if currentExpanded != isExpanded {
|
||||
videoAnimation = .None
|
||||
fileAnimation = .None
|
||||
}
|
||||
|
||||
animation.animator.updateFrame(layer: strongSelf.interactiveVideoNode.layer, frame: videoFrame, completion: nil)
|
||||
@ -337,7 +348,7 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
if let fileSize = finalFileSize {
|
||||
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 {
|
||||
|
@ -389,7 +389,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
||||
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)
|
||||
|
||||
@ -1264,7 +1264,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
||||
effectiveAvatarInset *= (1.0 - scaleProgress)
|
||||
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 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>?
|
||||
private var transcriptionPendingIndicator: ComponentHostView<Empty>?
|
||||
let textNode: TextNode
|
||||
private let textClippingNode: ASDisplayNode
|
||||
let textClippingNode: ASDisplayNode
|
||||
private var textSelectionNode: TextSelectionNode?
|
||||
|
||||
var updateIsTextSelectionActive: ((Bool) -> Void)?
|
||||
|
@ -17,6 +17,8 @@ import ComponentFlow
|
||||
import AudioTranscriptionButtonComponent
|
||||
import UndoUI
|
||||
import TelegramNotices
|
||||
import Markdown
|
||||
import TextFormat
|
||||
|
||||
struct ChatMessageInstantVideoItemLayoutResult {
|
||||
let contentSize: CGSize
|
||||
@ -30,6 +32,9 @@ enum ChatMessageInstantVideoItemLayoutData {
|
||||
}
|
||||
|
||||
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 {
|
||||
case free
|
||||
@ -48,9 +53,9 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
var customIsHidden: Bool = false {
|
||||
var canAttachContent: Bool = false {
|
||||
didSet {
|
||||
if self.customIsHidden != oldValue {
|
||||
if self.canAttachContent != oldValue {
|
||||
Queue.mainQueue().justDispatch {
|
||||
self.videoNode?.canAttachContent = self.shouldAcquireVideoContext
|
||||
}
|
||||
@ -73,6 +78,8 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
private var item: ChatMessageBubbleContentItem?
|
||||
private var automaticDownload: Bool?
|
||||
var media: TelegramMediaFile?
|
||||
var appliedForwardInfo: (Peer?, String?)?
|
||||
|
||||
private var secretProgressIcon: UIImage?
|
||||
|
||||
private let fetchDisposable = MetaDisposable()
|
||||
@ -84,6 +91,11 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
private let infoBackgroundNode: ASImageNode
|
||||
private let muteIconNode: ASImageNode
|
||||
|
||||
var viaBotNode: TextNode?
|
||||
var replyInfoNode: ChatMessageReplyInfoNode?
|
||||
var replyBackgroundNode: NavigationBackgroundNode?
|
||||
var forwardInfoNode: ChatMessageForwardInfoNode?
|
||||
|
||||
private var status: FileMediaResourceStatus?
|
||||
private var playerStatus: MediaPlayerStatus? {
|
||||
didSet {
|
||||
@ -97,7 +109,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
private let fetchedThumbnailDisposable = MetaDisposable()
|
||||
|
||||
private var shouldAcquireVideoContext: Bool {
|
||||
if self.visibility && self.trackingIsInHierarchy && !self.customIsHidden {
|
||||
if self.visibility && self.trackingIsInHierarchy && !self.canAttachContent {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -195,10 +207,11 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
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 currentItem = self.item
|
||||
let currentForwardInfo = self.appliedForwardInfo
|
||||
let previousAutomaticDownload = self.automaticDownload
|
||||
|
||||
let makeDateAndStatusLayout = self.dateAndStatusNode.asyncLayout()
|
||||
@ -206,14 +219,22 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
let audioTranscriptionState = self.audioTranscriptionState
|
||||
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 updatedInfoBackgroundImage: UIImage?
|
||||
var updatedMuteIconImage: UIImage?
|
||||
|
||||
var viaBotApply: (TextNodeLayout, () -> TextNode)?
|
||||
var replyInfoApply: (CGSize, (Bool) -> ChatMessageReplyInfoNode)?
|
||||
var updatedReplyBackgroundNode: NavigationBackgroundNode?
|
||||
|
||||
var updatedInstantVideoBackgroundImage: UIImage?
|
||||
let instantVideoBackgroundImage: UIImage?
|
||||
|
||||
switch statusDisplayType {
|
||||
case .free:
|
||||
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
|
||||
for attribute in item.message.attributes {
|
||||
if let attribute = attribute as? ConsumableContentMessageAttribute {
|
||||
@ -412,10 +542,21 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
|
||||
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
|
||||
if let strongSelf = self {
|
||||
strongSelf.item = item
|
||||
strongSelf.videoFrame = displayVideoFrame
|
||||
strongSelf.appliedForwardInfo = (forwardSource, forwardAuthorSignature)
|
||||
strongSelf.secretProgressIcon = secretProgressIcon
|
||||
strongSelf.automaticDownload = automaticDownload
|
||||
|
||||
@ -737,6 +878,112 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
} else {
|
||||
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 {
|
||||
switch gesture {
|
||||
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) {
|
||||
self.transcribe()
|
||||
return
|
||||
@ -1007,9 +1287,6 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
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) {
|
||||
return audioTranscriptionButton
|
||||
}
|
||||
@ -1021,6 +1298,12 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
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) {
|
||||
return self.view
|
||||
}
|
||||
@ -1028,6 +1311,9 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
if let videoNode = self.videoNode, videoNode.frame.contains(point) {
|
||||
return self.view
|
||||
}
|
||||
if !self.bounds.contains(point) {
|
||||
return nil
|
||||
}
|
||||
return super.hitTest(point, with: event)
|
||||
}
|
||||
|
||||
@ -1072,16 +1358,16 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
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()
|
||||
return { item, width, displaySize, maximumDisplaySize, scaleProgress, statusType, automaticDownload in
|
||||
return { item, width, displaySize, maximumDisplaySize, scaleProgress, statusType, automaticDownload, avatarInset in
|
||||
var createdNode: ChatMessageInteractiveInstantVideoNode?
|
||||
let sizeAndApplyLayout: (ChatMessageInstantVideoItemLayoutResult, (ChatMessageInstantVideoItemLayoutData, ListViewItemUpdateAnimation) -> Void)
|
||||
if let makeLayout = makeLayout {
|
||||
sizeAndApplyLayout = makeLayout(item, width, displaySize, maximumDisplaySize, scaleProgress, statusType, automaticDownload)
|
||||
sizeAndApplyLayout = makeLayout(item, width, displaySize, maximumDisplaySize, scaleProgress, statusType, automaticDownload, avatarInset)
|
||||
} else {
|
||||
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
|
||||
}
|
||||
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)
|
||||
animator.animatePosition(layer: videoNode.layer, from: videoNode.position, to: targetFrame.center, completion: { _ in
|
||||
self.isHidden = true
|
||||
self.customIsHidden = true
|
||||
self.canAttachContent = true
|
||||
})
|
||||
let targetScale = targetNode.frame.width / videoNode.bounds.width
|
||||
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)
|
||||
|
||||
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)
|
||||
node.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||
animator.animatePosition(layer: node.textClippingNode.layer, from: node.textClippingNode.position.offsetBy(dx: 0.0, dy: verticalDelta), to: node.textClippingNode.position, completion: nil)
|
||||
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 {
|
||||
@ -1335,6 +1634,19 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
|
||||
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) {
|
||||
@ -1374,8 +1686,21 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
sourceNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
||||
|
||||
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)
|
||||
node.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration)
|
||||
animator.animatePosition(layer: node.textClippingNode.layer, from: node.textClippingNode.position, to: node.textClippingNode.position.offsetBy(dx: 0.0, dy: verticalDelta), completion: nil)
|
||||
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 {
|
||||
@ -1413,6 +1738,19 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
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")
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||
var invoice: TelegramMediaInvoice?
|
||||
for media in item.message.media {
|
||||
if let media = media as? TelegramMediaInvoice {
|
||||
|
@ -87,7 +87,7 @@ private func mediaMergeableStyle(_ media: Media) -> ChatMessageMerge {
|
||||
return .semanticallyMerged
|
||||
case let .Video(_, _, flags):
|
||||
if flags.contains(.instantRoundVideo) {
|
||||
return .semanticallyMerged
|
||||
return .none
|
||||
}
|
||||
default:
|
||||
break
|
||||
|
@ -64,7 +64,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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 makePinLayout = self.pinNode.asyncLayout()
|
||||
let statusLayout = self.dateAndStatusNode.asyncLayout()
|
||||
@ -73,7 +73,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
let previousMedia = self.media
|
||||
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||
var selectedMedia: TelegramMediaMap?
|
||||
var activeLiveBroadcastingTimeout: Int32?
|
||||
for media in item.message.media {
|
||||
|
@ -71,10 +71,10 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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()
|
||||
|
||||
return { item, layoutConstants, preparePosition, selection, constrainedSize in
|
||||
return { item, layoutConstants, preparePosition, selection, constrainedSize, _ in
|
||||
var selectedMedia: Media?
|
||||
var automaticDownload: InteractiveMediaNodeAutodownloadMode = .none
|
||||
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 makeTypeLayout = TextNode.asyncLayout(self.typeNode)
|
||||
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)
|
||||
|
||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||
|
@ -511,10 +511,10 @@ final class ChatMessageReactionsFooterContentNode: ChatMessageBubbleContentNode
|
||||
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
|
||||
|
||||
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 displaySeparator: Bool
|
||||
|
@ -29,11 +29,11 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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 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)
|
||||
|
||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||
|
@ -120,14 +120,14 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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 spoilerTextLayout = TextNodeWithEntities.asyncLayout(self.spoilerTextNode)
|
||||
let statusLayout = self.statusNode.asyncLayout()
|
||||
|
||||
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)
|
||||
|
||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||
|
@ -27,10 +27,10 @@ final class ChatMessageUnsupportedBubbleContentNode: ChatMessageBubbleContentNod
|
||||
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)
|
||||
|
||||
return { item, layoutConstants, _, _, constrainedSize in
|
||||
return { item, layoutConstants, _, _, constrainedSize, _ in
|
||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
|
||||
|
||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||
|
@ -112,10 +112,10 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
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()
|
||||
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize in
|
||||
return { item, layoutConstants, preparePosition, _, constrainedSize, _ in
|
||||
var webPage: TelegramMediaWebpage?
|
||||
var webPageContent: TelegramMediaWebpageLoadedContent?
|
||||
for media in item.message.media {
|
||||
|
Loading…
x
Reference in New Issue
Block a user