Reaction animation updates

This commit is contained in:
Ali
2021-12-03 22:19:53 +04:00
parent 41c7863cc9
commit fb4e94d09a
35 changed files with 1299 additions and 331 deletions

View File

@@ -174,6 +174,13 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> ([
}
let firstMessage = item.content.firstMessage
if let reactionsAttribute = mergedMessageReactions(attributes: firstMessage.attributes), !reactionsAttribute.reactions.isEmpty {
if result.last?.1 == ChatMessageWebpageBubbleContentNode.self || result.last?.1 == ChatMessagePollBubbleContentNode.self || result.last?.1 == ChatMessageContactBubbleContentNode.self {
result.append((firstMessage, ChatMessageReactionsFooterContentNode.self, ChatMessageEntryAttributes(), BubbleItemAttributes(isAttachment: true, neighborType: .freeform, neighborSpacing: .default)))
}
}
if !isAction && !Namespaces.Message.allScheduled.contains(firstMessage.id.namespace) {
var hasDiscussion = false
if let channel = firstMessage.peers[firstMessage.id.peerId] as? TelegramChannel, case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) {
@@ -920,7 +927,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
forwardInfoLayout: (ChatPresentationData, PresentationStrings, ChatMessageForwardInfoType, Peer?, String?, String?, CGSize) -> (CGSize, (CGFloat) -> ChatMessageForwardInfoNode),
replyInfoLayout: (ChatPresentationData, PresentationStrings, AccountContext, ChatMessageReplyInfoType, Message, CGSize) -> (CGSize, () -> ChatMessageReplyInfoNode),
actionButtonsLayout: (AccountContext, ChatPresentationThemeData, PresentationChatBubbleCorners, PresentationStrings, ReplyMarkupMessageAttribute, Message, CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (Bool) -> ChatMessageActionButtonsNode)),
mosaicStatusLayout: (ChatMessageDateAndStatusNode.Arguments) -> (CGFloat, (CGFloat) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode)),
mosaicStatusLayout: (ChatMessageDateAndStatusNode.Arguments) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageDateAndStatusNode)),
layoutConstants: ChatMessageItemLayoutConstants,
currentItem: ChatMessageItem?,
currentForwardInfo: (Peer?, String?)?,
@@ -1330,7 +1337,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
prepareContentPosition = .linear(top: topPosition, bottom: refinedBottomPosition)
}
let contentItem = ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: message, read: read, chatLocation: item.chatLocation, presentationData: item.presentationData, associatedData: item.associatedData, attributes: attributes, isItemPinned: isItemPinned, isItemEdited: isItemEdited)
let contentItem = ChatMessageBubbleContentItem(context: item.context, controllerInteraction: item.controllerInteraction, message: message, topMessage: item.content.firstMessage, read: read, chatLocation: item.chatLocation, presentationData: item.presentationData, associatedData: item.associatedData, attributes: attributes, isItemPinned: isItemPinned, isItemEdited: isItemEdited)
var itemSelection: Bool?
switch content {
@@ -1457,7 +1464,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
let lastNodeTopPosition: ChatMessageBubbleRelativePosition = .None(bottomNodeMergeStatus)
var calculatedGroupFramesAndSize: ([(CGRect, MosaicItemPosition)], CGSize)?
var mosaicStatusSizeAndApply: (CGSize, (Bool) -> ChatMessageDateAndStatusNode)?
var mosaicStatusSizeAndApply: (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageDateAndStatusNode)?
if let mosaicRange = mosaicRange {
let maxSize = layoutConstants.image.maxDimensions.fittedToWidthOrSmaller(maximumContentWidth - layoutConstants.image.bubbleInsets.left - layoutConstants.image.bubbleInsets.right)
@@ -2107,7 +2114,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
contentNodeFramesPropertiesAndApply: [(CGRect, ChatMessageBubbleContentProperties, Bool, (ListViewItemUpdateAnimation, Bool) -> Void)],
contentContainerNodeFrames: [(UInt32, CGRect, Bool?, CGFloat)],
mosaicStatusOrigin: CGPoint?,
mosaicStatusSizeAndApply: (CGSize, (Bool) -> ChatMessageDateAndStatusNode)?,
mosaicStatusSizeAndApply: (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageDateAndStatusNode)?,
needsShareButton: Bool
) -> Void {
guard let strongSelf = selfReference.value else {
@@ -2123,10 +2130,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
strongSelf.appliedForwardInfo = (forwardSource, forwardAuthorSignature)
strongSelf.updateAccessibilityData(accessibilityData)
var transition: ContainedViewLayoutTransition = .immediate
var legacyTransition: ContainedViewLayoutTransition = .immediate
var useDisplayLinkAnimations = false
if case let .System(duration) = animation {
transition = .animated(duration: duration, curve: .spring)
if case let .System(duration, _) = animation {
legacyTransition = .animated(duration: duration, curve: .spring)
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
useDisplayLinkAnimations = true
@@ -2150,9 +2157,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
let hasWallpaper = item.presentationData.theme.wallpaper.hasWallpaper
if item.presentationData.theme.theme.forceSync {
transition = .immediate
legacyTransition = .immediate
}
strongSelf.backgroundNode.setType(type: backgroundType, highlighted: strongSelf.highlightedState, graphics: graphics, maskMode: strongSelf.backgroundMaskMode, hasWallpaper: hasWallpaper, transition: transition, backgroundNode: presentationContext.backgroundNode)
strongSelf.backgroundNode.setType(type: backgroundType, highlighted: strongSelf.highlightedState, graphics: graphics, maskMode: strongSelf.backgroundMaskMode, hasWallpaper: hasWallpaper, transition: legacyTransition, backgroundNode: presentationContext.backgroundNode)
strongSelf.backgroundWallpaperNode.setType(type: backgroundType, theme: item.presentationData.theme, essentialGraphics: graphics, maskMode: strongSelf.backgroundMaskMode, backgroundNode: presentationContext.backgroundNode)
strongSelf.shadowNode.setType(type: backgroundType, hasWallpaper: hasWallpaper, graphics: graphics)
@@ -2178,14 +2185,14 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
let deliveryFailedFrame = CGRect(origin: CGPoint(x: backgroundFrame.maxX + deliveryFailedInset - deliveryFailedSize.width, y: backgroundFrame.maxY - deliveryFailedSize.height), size: deliveryFailedSize)
if isAppearing {
deliveryFailedNode.frame = deliveryFailedFrame
transition.animatePositionAdditive(node: deliveryFailedNode, offset: CGPoint(x: deliveryFailedInset, y: 0.0))
legacyTransition.animatePositionAdditive(node: deliveryFailedNode, offset: CGPoint(x: deliveryFailedInset, y: 0.0))
} else {
transition.updateFrame(node: deliveryFailedNode, frame: deliveryFailedFrame)
animation.animator.updateFrame(layer: deliveryFailedNode.layer, frame: deliveryFailedFrame, completion: nil)
}
} else if let deliveryFailedNode = strongSelf.deliveryFailedNode {
strongSelf.deliveryFailedNode = nil
transition.updateAlpha(node: deliveryFailedNode, alpha: 0.0)
transition.updateFrame(node: deliveryFailedNode, frame: deliveryFailedNode.frame.offsetBy(dx: 24.0, dy: 0.0), completion: { [weak deliveryFailedNode] _ in
animation.animator.updateAlpha(layer: deliveryFailedNode.layer, alpha: 0.0, completion: nil)
animation.animator.updateFrame(layer: deliveryFailedNode.layer, frame: deliveryFailedNode.frame.offsetBy(dx: 24.0, dy: 0.0), completion: { [weak deliveryFailedNode] _ in
deliveryFailedNode?.removeFromSupernode()
})
}
@@ -2194,16 +2201,16 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
strongSelf.nameNode = nameNode
nameNode.displaysAsynchronously = !item.presentationData.isPreview && !item.presentationData.theme.theme.forceSync
let previousNameNodeFrame = nameNode.frame
//let previousNameNodeFrame = nameNode.frame
let nameNodeFrame = CGRect(origin: CGPoint(x: contentOrigin.x + layoutConstants.text.bubbleInsets.left, y: layoutConstants.bubble.contentInsets.top + nameNodeOriginY), size: nameNodeSizeApply.0)
nameNode.frame = nameNodeFrame
if nameNode.supernode == nil {
if !nameNode.isNodeLoaded {
nameNode.isUserInteractionEnabled = false
}
strongSelf.clippingNode.addSubnode(nameNode)
nameNode.frame = nameNodeFrame
} else {
transition.animatePositionAdditive(node: nameNode, offset: CGPoint(x: previousNameNodeFrame.maxX - nameNodeFrame.maxX, y: 0.0))
animation.animator.updateFrame(layer: nameNode.layer, frame: nameNodeFrame, completion: nil)
}
if let credibilityIconImage = currentCredibilityIconImage {
@@ -2232,9 +2239,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
strongSelf.clippingNode.addSubnode(adminBadgeNode)
adminBadgeNode.frame = adminBadgeFrame
} else {
let previousAdminBadgeFrame = adminBadgeNode.frame
adminBadgeNode.frame = adminBadgeFrame
transition.animatePositionAdditive(node: adminBadgeNode, offset: CGPoint(x: previousAdminBadgeFrame.maxX - adminBadgeFrame.maxX, y: 0.0))
//let previousAdminBadgeFrame = adminBadgeNode.frame
animation.animator.updateFrame(layer: adminBadgeNode.layer, frame: adminBadgeFrame, completion: nil)
}
} else {
strongSelf.adminBadgeNode?.removeFromSupernode()
@@ -2269,7 +2275,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
let previousForwardInfoNodeFrame = forwardInfoNode.frame
let forwardInfoFrame = CGRect(origin: CGPoint(x: contentOrigin.x + layoutConstants.text.bubbleInsets.left, y: layoutConstants.bubble.contentInsets.top + forwardInfoOriginY), size: CGSize(width: bubbleContentWidth, height: forwardInfoSizeApply.0.height))
if case let .System(duration) = animation {
if case let .System(duration, _) = animation {
if animateFrame {
if useDisplayLinkAnimations {
let animation = ListViewAnimation(from: previousForwardInfoNodeFrame, to: forwardInfoFrame, duration: duration * UIView.animationDurationFactor(), curve: strongSelf.preferredAnimationCurve, beginAt: beginAt, update: { _, frame in
@@ -2309,7 +2315,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
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)
if case let .System(duration) = animation {
if case let .System(duration, _) = animation {
if animateFrame {
replyInfoNode.layer.animateFrame(from: previousReplyInfoNodeFrame, to: replyInfoNode.frame, duration: duration, timingFunction: timingFunction)
}
@@ -2561,7 +2567,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
let contentNodeFrame = relativeFrame.offsetBy(dx: contentOrigin.x, dy: useContentOrigin ? contentOrigin.y : 0.0)
let previousContentNodeFrame = contentNode.frame
if case let .System(duration) = animation {
if case let .System(duration, _) = animation {
var animateFrame = false
var animateAlpha = false
if let addedContentNodes = addedContentNodes {
@@ -2581,8 +2587,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
})
strongSelf.setAnimationForKey("contentNode\(contentNodeIndex)Frame", animation: animation)
} else {
contentNode.frame = contentNodeFrame
contentNode.layer.animateFrame(from: previousContentNodeFrame, to: contentNodeFrame, duration: duration, timingFunction: timingFunction)
animation.animator.updateFrame(layer: contentNode.layer, frame: contentNodeFrame, completion: nil)
}
} else if animateAlpha {
contentNode.frame = contentNodeFrame
@@ -2600,7 +2605,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
if let mosaicStatusOrigin = mosaicStatusOrigin, let (size, apply) = mosaicStatusSizeAndApply {
let mosaicStatusNode = apply(transition.isAnimated)
let mosaicStatusNode = apply(animation)
if mosaicStatusNode !== strongSelf.mosaicStatusNode {
strongSelf.mosaicStatusNode?.removeFromSupernode()
strongSelf.mosaicStatusNode = mosaicStatusNode
@@ -2627,18 +2632,53 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
if case .System = animation, !strongSelf.mainContextSourceNode.isExtractedToContextPreview {
if !strongSelf.backgroundNode.frame.equalTo(backgroundFrame) {
strongSelf.backgroundFrameTransition = (strongSelf.backgroundNode.frame, backgroundFrame)
/*strongSelf.backgroundFrameTransition = (strongSelf.backgroundNode.frame, backgroundFrame)
if let type = strongSelf.backgroundNode.type {
if case .none = type {
} else {
strongSelf.clippingNode.clipsToBounds = true
}
}*/
animation.animator.updateFrame(layer: strongSelf.backgroundNode.layer, frame: backgroundFrame, completion: nil)
animation.animator.updatePosition(layer: strongSelf.clippingNode.layer, position: backgroundFrame.center, completion: nil)
strongSelf.clippingNode.clipsToBounds = true
animation.animator.updateBounds(layer: strongSelf.clippingNode.layer, bounds: CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size), completion: { [weak strongSelf] _ in
let _ = strongSelf
//strongSelf?.clippingNode.clipsToBounds = false
})
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: animation)
animation.animator.updateFrame(layer: strongSelf.backgroundWallpaperNode.layer, frame: backgroundFrame, completion: nil)
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: animation.transition)
if let type = strongSelf.backgroundNode.type {
var incomingOffset: CGFloat = 0.0
switch type {
case .incoming:
incomingOffset = 5.0
default:
break
}
strongSelf.mainContextSourceNode.contentRect = backgroundFrame.offsetBy(dx: incomingOffset, dy: 0.0)
strongSelf.mainContainerNode.targetNodeForActivationProgressContentRect = strongSelf.mainContextSourceNode.contentRect
if !strongSelf.mainContextSourceNode.isExtractedToContextPreview {
if let (rect, size) = strongSelf.absoluteRect {
strongSelf.updateAbsoluteRect(rect, within: size)
}
}
}
strongSelf.messageAccessibilityArea.frame = backgroundFrame
/*if let item = strongSelf.item, let shareButtonNode = strongSelf.shareButtonNode {
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account, disableComments: true)
animation.animator.updateFrame(layer: shareButtonNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.maxX + 8.0, y: backgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize), completion: nil)
}*/
}
if let shareButtonNode = strongSelf.shareButtonNode {
let currentBackgroundFrame = strongSelf.backgroundNode.frame
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account, disableComments: true)
shareButtonNode.frame = CGRect(origin: CGPoint(x: currentBackgroundFrame.maxX + 8.0, y: currentBackgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize)
animation.animator.updateFrame(layer: shareButtonNode.layer, frame: CGRect(origin: CGPoint(x: currentBackgroundFrame.maxX + 8.0, y: currentBackgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize), completion: nil)
}
} else {
if let _ = strongSelf.backgroundFrameTransition {
@@ -2652,14 +2692,14 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
if case .System = animation, strongSelf.mainContextSourceNode.isExtractedToContextPreview {
transition.updateFrame(node: strongSelf.backgroundNode, frame: backgroundFrame)
legacyTransition.updateFrame(node: strongSelf.backgroundNode, frame: backgroundFrame)
transition.updateFrame(node: strongSelf.clippingNode, frame: backgroundFrame)
transition.updateBounds(node: strongSelf.clippingNode, bounds: CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size))
legacyTransition.updateFrame(node: strongSelf.clippingNode, frame: backgroundFrame)
legacyTransition.updateBounds(node: strongSelf.clippingNode, bounds: CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY), size: backgroundFrame.size))
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: transition)
strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, transition: transition)
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: transition)
strongSelf.backgroundNode.updateLayout(size: backgroundFrame.size, transition: legacyTransition)
strongSelf.backgroundWallpaperNode.updateFrame(backgroundFrame, transition: legacyTransition)
strongSelf.shadowNode.updateLayout(backgroundFrame: backgroundFrame, transition: legacyTransition)
} else {
strongSelf.backgroundNode.frame = backgroundFrame
strongSelf.clippingNode.frame = backgroundFrame
@@ -2702,7 +2742,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
strongSelf.insertSubnode(actionButtonsNode, belowSubnode: strongSelf.messageAccessibilityArea)
} else {
if case let .System(duration) = animation {
if case let .System(duration, _) = animation {
actionButtonsNode.layer.animateFrame(from: previousFrame, to: actionButtonsFrame, duration: duration, timingFunction: timingFunction)
}
}
@@ -2780,7 +2820,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
override func animateFrameTransition(_ progress: CGFloat, _ currentValue: CGFloat) {
super.animateFrameTransition(progress, currentValue)
if let backgroundFrameTransition = self.backgroundFrameTransition {
/*if let backgroundFrameTransition = self.backgroundFrameTransition {
let backgroundFrame = CGRect.interpolator()(backgroundFrameTransition.0, backgroundFrameTransition.1, progress) as! CGRect
self.backgroundNode.frame = backgroundFrame
@@ -2819,7 +2859,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
self.clippingNode.clipsToBounds = false
}
}
}*/
}
@objc func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {