From d8de3f48ae4ac8fb7daddc90c4976d1aa4c000ba Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 30 Jul 2019 14:44:47 +0300 Subject: [PATCH 1/7] Fixed Siri message reading --- SiriIntents/IntentHandler.swift | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/SiriIntents/IntentHandler.swift b/SiriIntents/IntentHandler.swift index 4958020e72..b79c9b2d39 100644 --- a/SiriIntents/IntentHandler.swift +++ b/SiriIntents/IntentHandler.swift @@ -326,14 +326,12 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag |> introduceError(IntentHandlingError.self) |> mapToSignal { account -> Signal<[INMessage], IntentHandlingError> in account.shouldBeServiceTaskMaster.set(.single(.now)) - let completedUpdating: Signal = (.single(true) |> then(account.stateManager.isUpdating)) - |> introduceError(IntentHandlingError.self) - |> filter { !$0 } - |> take(1) - |> timeout(3.0, queue: Queue.mainQueue(), alternate: .fail(.generic)) + account.resetStateManagement() - return completedUpdating - |> mapToSignal { value -> Signal<[INMessage], IntentHandlingError> in + return account.stateManager.pollStateUpdateCompletion() + |> introduceError(IntentHandlingError.self) + |> take(1) + |> mapToSignal { _ -> Signal<[INMessage], IntentHandlingError> in return unreadMessages(account: account) |> introduceError(IntentHandlingError.self) } From dabf729195d7dfa786754f08511a2503748921ab Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 30 Jul 2019 15:29:10 +0300 Subject: [PATCH 2/7] Fixed chat mentions button icon on theme auto change --- .../TelegramUI/ChatHistoryNavigationButtonNode.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryNavigationButtonNode.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryNavigationButtonNode.swift index bfd2ef8051..d2e263c84e 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryNavigationButtonNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryNavigationButtonNode.swift @@ -77,7 +77,12 @@ class ChatHistoryNavigationButtonNode: ASControlNode { if self.theme !== theme { self.theme = theme - self.imageNode.image = PresentationResourcesChat.chatHistoryNavigationButtonImage(theme) + switch type { + case .down: + self.imageNode.image = PresentationResourcesChat.chatHistoryNavigationButtonImage(theme) + case .mentions: + self.imageNode.image = PresentationResourcesChat.chatHistoryMentionsButtonImage(theme) + } self.badgeBackgroundNode.image = PresentationResourcesChat.chatHistoryNavigationButtonBadgeImage(theme) if let string = self.badgeTextNode.attributedText?.string { From 7d962cc90fec2e06d81487782e396da8ddb11c55 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 30 Jul 2019 16:52:34 +0300 Subject: [PATCH 3/7] Fixed chat message preview layout on scrolling --- .../ChatHistoryNavigationButtonNode.swift | 4 +++- ...SendMessageActionSheetControllerNode.swift | 20 +++++++++++-------- .../Sources/PresentationThemeSettings.swift | 18 ++++++++--------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryNavigationButtonNode.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryNavigationButtonNode.swift index d2e263c84e..6d27116d42 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryNavigationButtonNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryNavigationButtonNode.swift @@ -37,9 +37,11 @@ class ChatHistoryNavigationButtonNode: ASControlNode { } private var theme: PresentationTheme + private let type: ChatHistoryNavigationButtonType init(theme: PresentationTheme, type: ChatHistoryNavigationButtonType) { self.theme = theme + self.type = type self.imageNode = ASImageNode() self.imageNode.displayWithoutProcessing = true @@ -77,7 +79,7 @@ class ChatHistoryNavigationButtonNode: ASControlNode { if self.theme !== theme { self.theme = theme - switch type { + switch self.type { case .down: self.imageNode.image = PresentationResourcesChat.chatHistoryNavigationButtonImage(theme) case .mentions: diff --git a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift index 43b3567ceb..ac7dee2106 100644 --- a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift @@ -390,14 +390,6 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, intermediateCompletion() }) - Queue.mainQueue().after(0.7) { - completedAlpha = true - completedButton = true - completedBubble = true - completedEffect = true - intermediateCompletion() - } - self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false) self.contentContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in }) @@ -453,6 +445,8 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, let textOffset = self.textInputNode.textView.contentSize.height - self.textInputNode.textView.contentOffset.y - self.textInputNode.textView.frame.height self.fromMessageTextNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: delta * 2.0 + textOffset), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true) self.toMessageTextNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: delta * 2.0 + textOffset), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true) + } else { + completedBubble = true } self.contentContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 160.0, y: 0.0), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true) @@ -460,6 +454,12 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, } } + func scrollViewDidScroll(_ scrollView: UIScrollView) { + if let layout = self.validLayout { + self.containerLayoutUpdated(layout, transition: .immediate) + } + } + func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { self.validLayout = layout @@ -484,10 +484,13 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, let insets = layout.insets(options: [.statusBar, .input]) let inputHeight = layout.inputHeight ?? 0.0 + let contentOffset = self.scrollNode.view.contentOffset.y + var contentOrigin = CGPoint(x: layout.size.width - sideInset - contentSize.width - layout.safeInsets.right, y: layout.size.height - 6.0 - insets.bottom - contentSize.height) if inputHeight > 0.0 { contentOrigin.y += 60.0 } + contentOrigin.y = min(contentOrigin.y + contentOffset, layout.size.height - 6.0 - layout.intrinsicInsets.bottom - contentSize.height) transition.updateFrame(node: self.contentContainerNode, frame: CGRect(origin: contentOrigin, size: contentSize)) var nextY: CGFloat = 0.0 @@ -502,6 +505,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, if inputHeight.isZero { sendButtonFrame.origin.y -= 60.0 } + sendButtonFrame.origin.y = min(sendButtonFrame.origin.y + contentOffset, layout.size.height - layout.intrinsicInsets.bottom - initialSendButtonFrame.height) transition.updateFrame(node: self.sendButtonNode, frame: sendButtonFrame) var messageFrame = self.textFieldFrame diff --git a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift index 2a89a985b0..1d63717c6e 100644 --- a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift @@ -257,15 +257,15 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { } public var color: UIColor { - let color: UIColor - if self.value < 0.5 { - color = self.baseColor.color.interpolateTo(self.baseColor.edgeColors.0, fraction: 0.5 - self.value)! - } else if self.value > 0.5 { - color = self.baseColor.color.interpolateTo(self.baseColor.edgeColors.1, fraction: self.value - 0.5)! - } else { - color = self.baseColor.color - } - return color +// let color: UIColor +// if self.value < 0.5 { +// color = self.baseColor.color.interpolateTo(self.baseColor.edgeColors.0, fraction: 0.5 - self.value)! +// } else if self.value > 0.5 { +// color = self.baseColor.color.interpolateTo(self.baseColor.edgeColors.1, fraction: self.value - 0.5)! +// } else { +// color = self.baseColor.color +// } + return self.baseColor.color } } From 5da86bd619eff082245eb45648d554b3613fac57 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 30 Jul 2019 18:49:04 +0300 Subject: [PATCH 4/7] Added forward placeholder in message sending preview --- ...ChatSendMessageActionSheetController.swift | 10 ++--- ...SendMessageActionSheetControllerNode.swift | 44 ++++++++++++++----- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetController.swift b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetController.swift index 8727b58c20..fe8c69a922 100644 --- a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetController.swift @@ -32,7 +32,7 @@ final class ChatSendMessageActionSheetController: ViewController { self.sendButtonFrame = sendButtonFrame self.textInputNode = textInputNode self.completion = completion - + super.init(navigationBarPresentationData: nil) self.presentationDataDisposable = (context.sharedContext.presentationData @@ -55,12 +55,12 @@ final class ChatSendMessageActionSheetController: ViewController { } override func loadDisplayNode() { - var accessoryPanelNode: AccessoryPanelNode? - if let panel = accessoryPanelForChatPresentationIntefaceState(self.interfaceState, context: self.context, currentPanel: nil, interfaceInteraction: nil), panel is ReplyAccessoryPanelNode || panel is ForwardAccessoryPanelNode { - accessoryPanelNode = panel + var forwardedCount = 0 + if let forwardMessageIds = self.interfaceState.interfaceState.forwardMessageIds { + forwardedCount = forwardMessageIds.count } - self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, sendButtonFrame: self.sendButtonFrame, textInputNode: self.textInputNode, accessoryPanelNode: accessoryPanelNode, send: { [weak self] in + self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, sendButtonFrame: self.sendButtonFrame, textInputNode: self.textInputNode, forwardedCount: forwardedCount, send: { [weak self] in self?.controllerInteraction?.sendCurrentMessage(false) self?.dismiss(cancel: false) }, sendSilently: { [weak self] in diff --git a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift index ac7dee2106..b15375abd9 100644 --- a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift @@ -105,6 +105,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, private let textFieldFrame: CGRect private let textInputNode: EditableTextNode private let accessoryPanelNode: AccessoryPanelNode? + private let forwardedCount: Int? private let send: (() -> Void)? private let cancel: (() -> Void)? @@ -127,12 +128,14 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, private var validLayout: ContainerViewLayout? - init(context: AccountContext, sendButtonFrame: CGRect, textInputNode: EditableTextNode, accessoryPanelNode: AccessoryPanelNode?, send: (() -> Void)?, sendSilently: (() -> Void)?, cancel: (() -> Void)?) { + init(context: AccountContext, sendButtonFrame: CGRect, textInputNode: EditableTextNode, forwardedCount: Int?, send: (() -> Void)?, sendSilently: (() -> Void)?, cancel: (() -> Void)?) { self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.sendButtonFrame = sendButtonFrame self.textFieldFrame = textInputNode.convert(textInputNode.bounds, to: nil) self.textInputNode = textInputNode - self.accessoryPanelNode = accessoryPanelNode + self.accessoryPanelNode = nil + self.forwardedCount = forwardedCount + self.send = send self.cancel = cancel @@ -198,9 +201,13 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.sendButtonNode.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(self.presentationData.theme), for: []) self.sendButtonNode.addTarget(self, action: #selector(sendButtonPressed), forControlEvents: .touchUpInside) - self.fromMessageTextNode.attributedText = textInputNode.attributedText - - if let toAttributedText = textInputNode.attributedText?.mutableCopy() as? NSMutableAttributedString { + if let attributedText = textInputNode.attributedText, !attributedText.string.isEmpty { + self.fromMessageTextNode.attributedText = attributedText + } else { + self.fromMessageTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.ForwardedMessages(Int32(forwardedCount ?? 0)), attributes: [NSAttributedStringKey.foregroundColor: self.presentationData.theme.chat.message.outgoing.primaryTextColor, NSAttributedStringKey.font: Font.regular(self.presentationData.fontSize.baseDisplaySize)]) + } + + if let toAttributedText = self.fromMessageTextNode.attributedText?.mutableCopy() as? NSMutableAttributedString { toAttributedText.addAttribute(NSAttributedStringKey.foregroundColor, value: self.presentationData.theme.chat.message.outgoing.primaryTextColor, range: NSMakeRange(0, (toAttributedText.string as NSString).length)) self.toMessageTextNode.attributedText = toAttributedText } @@ -222,7 +229,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.messageClipNode.addSubnode(self.toMessageTextNode) if let accessoryPanelNode = self.accessoryPanelNode { - self.messageClipNode.addSubnode(accessoryPanelNode) + self.addSubnode(accessoryPanelNode) } self.contentNodes.forEach(self.contentContainerNode.addSubnode) @@ -332,7 +339,11 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.sendButtonNode.layer.animateScale(from: 0.75, to: 1.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionLinear) self.sendButtonNode.layer.animatePosition(from: self.sendButtonFrame.center, to: self.sendButtonNode.position, duration: duration, timingFunction: kCAMediaTimingFunctionSpring) - let initialWidth = self.textFieldFrame.width + 32.0 + var initialWidth = self.textFieldFrame.width + 32.0 + if self.textInputNode.textView.attributedText.string.isEmpty { + initialWidth = ceil(layout.size.width - self.textFieldFrame.origin.x - self.sendButtonFrame.width - layout.safeInsets.left - layout.safeInsets.right + 21.0) + } + let fromFrame = CGRect(origin: CGPoint(), size: CGSize(width: initialWidth, height: self.textFieldFrame.height + 2.0)) let delta = (fromFrame.height - self.messageClipNode.bounds.height) / 2.0 @@ -422,7 +433,11 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.sendButtonNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionLinear, removeOnCompletion: false) } - let initialWidth = self.textFieldFrame.width + 32.0 + var initialWidth = self.textFieldFrame.width + 32.0 + if self.textInputNode.textView.attributedText.string.isEmpty { + initialWidth = ceil(layout.size.width - self.textFieldFrame.origin.x - self.sendButtonFrame.width - layout.safeInsets.left - layout.safeInsets.right + 21.0) + } + let toFrame = CGRect(origin: CGPoint(), size: CGSize(width: initialWidth, height: self.textFieldFrame.height + 1.0)) let delta = (toFrame.height - self.messageClipNode.bounds.height) / 2.0 @@ -516,8 +531,12 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, messageFrame.origin.y += 60.0 } - if self.textInputNode.textView.numberOfLines == 1 { - let textWidth = min(self.textInputNode.textView.sizeThatFits(layout.size).width + 36.0, messageFrame.width) + if self.textInputNode.textView.attributedText.string.isEmpty { + messageFrame.size.width = ceil(layout.size.width - messageFrame.origin.x - sendButtonFrame.width - layout.safeInsets.left - layout.safeInsets.right + 8.0) + } + + if self.textInputNode.textView.numberOfLines == 1 || self.textInputNode.textView.attributedText.string.isEmpty { + let textWidth = min(self.fromMessageTextNode.textView.sizeThatFits(layout.size).width + 36.0, messageFrame.width) messageFrame.origin.x += messageFrame.width - textWidth messageFrame.size.width = textWidth } @@ -544,6 +563,11 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, textFrame.size.height = self.textInputNode.textView.contentSize.height self.fromMessageTextNode.frame = textFrame self.toMessageTextNode.frame = textFrame + + if let accessoryPanelNode = self.accessoryPanelNode { + let size = accessoryPanelNode.calculateSizeThatFits(CGSize(width: messageFrame.width, height: 45.0)) + accessoryPanelNode.frame = CGRect(origin: CGPoint(x: 0.0, y: self.textFieldFrame.minY - size.height - 7.0), size: size) + } } @objc private func dimTapGesture(_ recognizer: UITapGestureRecognizer) { From 1fc8b3a541abe91d236a2b76602ff82e8cd1c164 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 30 Jul 2019 20:18:43 +0300 Subject: [PATCH 5/7] Fixed animated sticker loop disabling --- .../TelegramUI/ChatMediaInputNode.swift | 2 ++ .../ChatMediaInputStickerPackItem.swift | 15 +++++++++++---- .../TelegramUI/ItemListStickerPackItem.swift | 13 +++++++++++-- .../TelegramUI/StickerResources.swift | 18 ++++++++++++------ .../Sources/ExperimentalUISettings.swift | 4 ++-- 5 files changed, 38 insertions(+), 14 deletions(-) diff --git a/submodules/TelegramUI/TelegramUI/ChatMediaInputNode.swift b/submodules/TelegramUI/TelegramUI/ChatMediaInputNode.swift index 5c7db9cd84..fe4f3f6bd6 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMediaInputNode.swift @@ -329,6 +329,7 @@ final class ChatMediaInputNodeInteraction { let dismissPeerSpecificSettings: () -> Void let clearRecentlyUsedStickers: () -> Void + var stickerSettings: ChatInterfaceStickerSettings? var highlightedStickerItemCollectionId: ItemCollectionId? var highlightedItemCollectionId: ItemCollectionId? var previewedStickerPackItem: StickerPreviewPeekItem? @@ -651,6 +652,7 @@ final class ChatMediaInputNode: ChatInputNode { } } } + self.inputNodeInteraction.stickerSettings = self.controllerInteraction.stickerSettings let previousEntries = Atomic<([ChatMediaInputPanelEntry], [ChatMediaInputGridEntry])>(value: ([], [])) diff --git a/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerPackItem.swift b/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerPackItem.swift index 30b5d5f32b..f3472d94f9 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerPackItem.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerPackItem.swift @@ -110,7 +110,8 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode { private var visibilityStatus: Bool = false { didSet { if self.visibilityStatus != oldValue { - self.animatedStickerNode?.visibility = self.visibilityStatus + let loopAnimatedStickers = self.inputNodeInteraction?.stickerSettings?.loopAnimatedStickers ?? false + self.animatedStickerNode?.visibility = self.visibilityStatus && loopAnimatedStickers } } } @@ -175,11 +176,17 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode { let imageSize = representation.dimensions.aspectFitted(boundingImageSize) let imageApply = self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets())) imageApply() - self.imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, representation: representation)) - + self.imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, resource: representation.resource)) self.imageNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - imageSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize) case let .animated(resource): let imageSize = boundingImageSize + let imageApply = self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets())) + imageApply() + self.imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, resource: resource, animated: true)) + self.imageNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - imageSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize) + + let loopAnimatedStickers = self.inputNodeInteraction?.stickerSettings?.loopAnimatedStickers ?? false + self.imageNode.isHidden = loopAnimatedStickers let animatedStickerNode: AnimatedStickerNode if let current = self.animatedStickerNode { @@ -190,8 +197,8 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode { animatedStickerNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0) self.addSubnode(animatedStickerNode) animatedStickerNode.setup(account: account, resource: resource, width: 80, height: 80, mode: .cached) - animatedStickerNode.visibility = self.visibilityStatus } + animatedStickerNode.visibility = self.visibilityStatus && loopAnimatedStickers if let animatedStickerNode = self.animatedStickerNode { animatedStickerNode.frame = CGRect(origin: CGPoint(x: floor((boundingSize.width - imageSize.width) / 2.0) + verticalOffset, y: floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize) } diff --git a/submodules/TelegramUI/TelegramUI/ItemListStickerPackItem.swift b/submodules/TelegramUI/TelegramUI/ItemListStickerPackItem.swift index a7ed3223d8..ed64411a6b 100644 --- a/submodules/TelegramUI/TelegramUI/ItemListStickerPackItem.swift +++ b/submodules/TelegramUI/TelegramUI/ItemListStickerPackItem.swift @@ -371,10 +371,15 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { if fileUpdated { imageApply = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: stillImageSize, boundingSize: stillImageSize, intrinsicInsets: UIEdgeInsets())) - updatedImageSignal = chatMessageStickerPackThumbnail(postbox: item.account.postbox, representation: representation) + updatedImageSignal = chatMessageStickerPackThumbnail(postbox: item.account.postbox, resource: representation.resource) } - case .animated: + case let .animated(resource): imageSize = imageBoundingSize + + if fileUpdated { + imageApply = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: imageBoundingSize, boundingSize: imageBoundingSize, intrinsicInsets: UIEdgeInsets())) + updatedImageSignal = chatMessageStickerPackThumbnail(postbox: item.account.postbox, resource: resource, animated: true) + } } if fileUpdated, let resourceReference = resourceReference { updatedFetchSignal = fetchedMediaResource(mediaBox: item.account.postbox.mediaBox, reference: resourceReference) @@ -552,6 +557,8 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { case .still: transition.updateFrame(node: strongSelf.imageNode, frame: imageFrame) case let .animated(resource): + transition.updateFrame(node: strongSelf.imageNode, frame: imageFrame) + let animationNode: AnimatedStickerNode if let current = strongSelf.animationNode { animationNode = current @@ -562,6 +569,8 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { animationNode.setup(account: item.account, resource: resource, width: 80, height: 80, mode: .cached) } animationNode.visibility = strongSelf.visibility != .none && item.playAnimatedStickers + animationNode.isHidden = !item.playAnimatedStickers + strongSelf.imageNode.isHidden = item.playAnimatedStickers if let animationNode = strongSelf.animationNode { transition.updateFrame(node: animationNode, frame: imageFrame) } diff --git a/submodules/TelegramUI/TelegramUI/StickerResources.swift b/submodules/TelegramUI/TelegramUI/StickerResources.swift index a498108ecd..b6d228e3bf 100644 --- a/submodules/TelegramUI/TelegramUI/StickerResources.swift +++ b/submodules/TelegramUI/TelegramUI/StickerResources.swift @@ -184,9 +184,15 @@ private func chatMessageStickerThumbnailData(postbox: Postbox, file: TelegramMed } } -private func chatMessageStickerPackThumbnailData(postbox: Postbox, representation: TelegramMediaImageRepresentation, synchronousLoad: Bool) -> Signal { - let resource = representation.resource - let maybeFetched = postbox.mediaBox.cachedResourceRepresentation(resource, representation: CachedStickerAJpegRepresentation(size: CGSize(width: 160.0, height: 160.0)), complete: false, fetch: false, attemptSynchronously: synchronousLoad) +private func chatMessageStickerPackThumbnailData(postbox: Postbox, resource: MediaResource, animated: Bool, synchronousLoad: Bool) -> Signal { + let maybeFetched: Signal + let representation: CachedMediaResourceRepresentation + if animated { + representation = CachedAnimatedStickerFirstFrameRepresentation(width: 160, height: 160) + } else { + representation = CachedStickerAJpegRepresentation(size: CGSize(width: 160.0, height: 160.0)) + } + maybeFetched = postbox.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: false, fetch: false, attemptSynchronously: synchronousLoad) return maybeFetched |> take(1) @@ -195,7 +201,7 @@ private func chatMessageStickerPackThumbnailData(postbox: Postbox, representatio let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: maybeData.path), options: []) return .single(loadedData) } else { - let fullSizeData = postbox.mediaBox.cachedResourceRepresentation(resource, representation: CachedStickerAJpegRepresentation(size: CGSize(width: 160.0, height: 160.0)), complete: false) + let fullSizeData = postbox.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: false) |> map { next in return ((next.size == 0 || !next.complete) ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: .mappedIfSafe), next.complete) } @@ -325,8 +331,8 @@ public func chatMessageSticker(account: Account, file: TelegramMediaFile, small: return chatMessageSticker(postbox: account.postbox, file: file, small: small, fetched: fetched, onlyFullSize: onlyFullSize, thumbnail: thumbnail, synchronousLoad: synchronousLoad) } -public func chatMessageStickerPackThumbnail(postbox: Postbox, representation: TelegramMediaImageRepresentation, synchronousLoad: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { - let signal = chatMessageStickerPackThumbnailData(postbox: postbox, representation: representation, synchronousLoad: synchronousLoad) +public func chatMessageStickerPackThumbnail(postbox: Postbox, resource: MediaResource, animated: Bool = false, synchronousLoad: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { + let signal = chatMessageStickerPackThumbnailData(postbox: postbox, resource: resource, animated: animated, synchronousLoad: synchronousLoad) return signal |> map { fullSizeData in diff --git a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift index 48debb81a1..1ca96950e7 100644 --- a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift +++ b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift @@ -10,7 +10,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry { public var playAnimatedEmojiOnce: Bool public static var defaultSettings: ExperimentalUISettings { - return ExperimentalUISettings(keepChatNavigationStack: false, skipReadHistory: false, crashOnLongQueries: false, chatListPhotos: false, playAnimatedEmojiOnce: false) + return ExperimentalUISettings(keepChatNavigationStack: false, skipReadHistory: false, crashOnLongQueries: false, chatListPhotos: false, playAnimatedEmojiOnce: true) } public init(keepChatNavigationStack: Bool, skipReadHistory: Bool, crashOnLongQueries: Bool, chatListPhotos: Bool, playAnimatedEmojiOnce: Bool) { @@ -26,7 +26,7 @@ public struct ExperimentalUISettings: Equatable, PreferencesEntry { self.skipReadHistory = decoder.decodeInt32ForKey("skipReadHistory", orElse: 0) != 0 self.crashOnLongQueries = decoder.decodeInt32ForKey("crashOnLongQueries", orElse: 0) != 0 self.chatListPhotos = decoder.decodeInt32ForKey("chatListPhotos", orElse: 0) != 0 - self.playAnimatedEmojiOnce = decoder.decodeInt32ForKey("playAnimatedEmojiOnce", orElse: 0) != 0 + self.playAnimatedEmojiOnce = decoder.decodeInt32ForKey("playAnimatedEmojiOnce", orElse: 1) != 0 } public func encode(_ encoder: PostboxEncoder) { From b1bb7a630cb07eede9bac595bfed76c938104d51 Mon Sep 17 00:00:00 2001 From: Peter <> Date: Tue, 30 Jul 2019 20:35:30 +0300 Subject: [PATCH 6/7] Support non-square animated stickers --- .../Telegram-iOS-Hockeyapp-Internal.xcscheme | 3 ++ .../Display/Display/GenerateImage.swift | 4 +-- .../Postbox/MessageHistoryMetadataTable.swift | 2 +- submodules/RLottie/Sources/LottieInstance.h | 2 +- submodules/RLottie/Sources/LottieInstance.mm | 4 +-- .../TelegramUI/AnimatedStickerNode.swift | 34 +++++++++++++------ .../TelegramUI/AnimatedStickerUtils.swift | 31 +++++++++++------ .../TelegramUI/AnimationRenderer.swift | 2 +- .../CachedResourceRepresentations.swift | 2 +- .../ChatMediaInputStickerGridItem.swift | 7 ++-- .../ChatMessageAnimatedStickerItemNode.swift | 7 ++-- .../ChatMessageInteractiveMediaNode.swift | 7 ++-- .../ChatPinnedMessageTitlePanelNode.swift | 3 +- ...ListContextResultsChatInputPanelItem.swift | 4 ++- .../HorizontalStickerGridItem.swift | 4 ++- .../MediaInputPaneTrendingItem.swift | 4 ++- .../NotificationContentContext.swift | 6 ++-- .../SoftwareAnimationRenderer.swift | 9 +++-- .../StickerPackPreviewController.swift | 3 +- .../StickerPackPreviewGridItem.swift | 6 ++-- .../StickerPaneSearchStickerItem.swift | 4 ++- .../StickerPreviewPeekContent.swift | 5 ++- submodules/TelegramUI/TelegramUI/YUV.h | 4 +-- submodules/TelegramUI/TelegramUI/YUV.m | 8 ++--- 24 files changed, 110 insertions(+), 55 deletions(-) diff --git a/Telegram-iOS.xcworkspace/xcshareddata/xcschemes/Telegram-iOS-Hockeyapp-Internal.xcscheme b/Telegram-iOS.xcworkspace/xcshareddata/xcschemes/Telegram-iOS-Hockeyapp-Internal.xcscheme index cda2b15e44..2db06cb59b 100644 --- a/Telegram-iOS.xcworkspace/xcshareddata/xcschemes/Telegram-iOS-Hockeyapp-Internal.xcscheme +++ b/Telegram-iOS.xcworkspace/xcshareddata/xcschemes/Telegram-iOS-Hockeyapp-Internal.xcscheme @@ -79,11 +79,14 @@ buildConfiguration = "DebugHockeyapp" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + enableAddressSanitizer = "YES" enableASanStackUseAfterReturn = "YES" + enableUBSanitizer = "YES" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" + stopOnEveryUBSanitizerIssue = "YES" debugServiceExtension = "internal" allowLocationSimulation = "YES" queueDebuggingEnabled = "No"> diff --git a/submodules/Display/Display/GenerateImage.swift b/submodules/Display/Display/GenerateImage.swift index ae6baba564..7c02da4e7c 100644 --- a/submodules/Display/Display/GenerateImage.swift +++ b/submodules/Display/Display/GenerateImage.swift @@ -15,7 +15,7 @@ private let deviceColorSpace: CGColorSpace = { let deviceScale = UIScreen.main.scale -public func generateImagePixel(_ size: CGSize, scale: CGFloat, pixelGenerator: (CGSize, UnsafeMutablePointer) -> Void) -> UIImage? { +public func generateImagePixel(_ size: CGSize, scale: CGFloat, pixelGenerator: (CGSize, UnsafeMutablePointer, Int) -> Void) -> UIImage? { let scaledSize = CGSize(width: size.width * scale, height: size.height * scale) let bytesPerRow = (4 * Int(scaledSize.width) + 15) & (~15) let length = bytesPerRow * Int(scaledSize.height) @@ -27,7 +27,7 @@ public func generateImagePixel(_ size: CGSize, scale: CGFloat, pixelGenerator: ( return nil } - pixelGenerator(scaledSize, bytes) + pixelGenerator(scaledSize, bytes, bytesPerRow) let bitmapInfo = CGBitmapInfo(rawValue: CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue) diff --git a/submodules/Postbox/Postbox/MessageHistoryMetadataTable.swift b/submodules/Postbox/Postbox/MessageHistoryMetadataTable.swift index 8467212a8d..c464fa7fb0 100644 --- a/submodules/Postbox/Postbox/MessageHistoryMetadataTable.swift +++ b/submodules/Postbox/Postbox/MessageHistoryMetadataTable.swift @@ -90,7 +90,7 @@ final class MessageHistoryMetadataTable: Table { private func chatListGroupInitializedKey(_ key: InitializedChatListKey) -> ValueBoxKey { self.sharedChatListGroupHistoryInitializedKey.setInt32(0, value: key.groupId.rawValue) - self.sharedChatListGroupHistoryInitializedKey.setInt8(8, value: MetadataPrefix.ChatListGroupInitialized.rawValue) + self.sharedChatListGroupHistoryInitializedKey.setInt8(4, value: MetadataPrefix.ChatListGroupInitialized.rawValue) return self.sharedChatListGroupHistoryInitializedKey } diff --git a/submodules/RLottie/Sources/LottieInstance.h b/submodules/RLottie/Sources/LottieInstance.h index 5eb3fb3d41..dd57dcddbe 100644 --- a/submodules/RLottie/Sources/LottieInstance.h +++ b/submodules/RLottie/Sources/LottieInstance.h @@ -11,7 +11,7 @@ @property (nonatomic, readonly) CGSize dimensions; - (instancetype _Nullable)initWithData:(NSData * _Nonnull)data cacheKey:(NSString * _Nonnull)cacheKey; -- (void)renderFrameWithIndex:(int32_t)index into:(uint8_t * _Nonnull)buffer width:(int32_t)width height:(int32_t)height; +- (void)renderFrameWithIndex:(int32_t)index into:(uint8_t * _Nonnull)buffer width:(int32_t)width height:(int32_t)height bytesPerRow:(int32_t)bytesPerRow; @end diff --git a/submodules/RLottie/Sources/LottieInstance.mm b/submodules/RLottie/Sources/LottieInstance.mm index e1859ef694..83a10557ff 100644 --- a/submodules/RLottie/Sources/LottieInstance.mm +++ b/submodules/RLottie/Sources/LottieInstance.mm @@ -38,8 +38,8 @@ return self; } -- (void)renderFrameWithIndex:(int32_t)index into:(uint8_t * _Nonnull)buffer width:(int32_t)width height:(int32_t)height { - rlottie::Surface surface((uint32_t *)buffer, width, height, width * 4); +- (void)renderFrameWithIndex:(int32_t)index into:(uint8_t * _Nonnull)buffer width:(int32_t)width height:(int32_t)height bytesPerRow:(int32_t) bytesPerRow{ + rlottie::Surface surface((uint32_t *)buffer, width, height, bytesPerRow); _animation->renderSync(index, surface); } diff --git a/submodules/TelegramUI/TelegramUI/AnimatedStickerNode.swift b/submodules/TelegramUI/TelegramUI/AnimatedStickerNode.swift index 168b692774..48f4cfb86a 100644 --- a/submodules/TelegramUI/TelegramUI/AnimatedStickerNode.swift +++ b/submodules/TelegramUI/TelegramUI/AnimatedStickerNode.swift @@ -82,13 +82,15 @@ private final class AnimatedStickerFrame { let type: AnimationRendererFrameType let width: Int let height: Int + let bytesPerRow: Int let isLastFrame: Bool - init(data: Data, type: AnimationRendererFrameType, width: Int, height: Int, isLastFrame: Bool) { + init(data: Data, type: AnimationRendererFrameType, width: Int, height: Int, bytesPerRow: Int, isLastFrame: Bool) { self.data = data self.type = type self.width = width self.height = height + self.bytesPerRow = bytesPerRow self.isLastFrame = isLastFrame } } @@ -105,6 +107,7 @@ private final class AnimatedStickerCachedFrameSource: AnimatedStickerFrameSource private let data: Data private var scratchBuffer: Data let width: Int + let bytesPerRow: Int let height: Int let frameRate: Int private let initialOffset: Int @@ -120,6 +123,7 @@ private final class AnimatedStickerCachedFrameSource: AnimatedStickerFrameSource var offset = 0 var width = 0 var height = 0 + var bytesPerRow = 0 var frameRate = 0 if !self.data.withUnsafeBytes({ (bytes: UnsafePointer) -> Bool in @@ -129,19 +133,23 @@ private final class AnimatedStickerCachedFrameSource: AnimatedStickerFrameSource offset += 4 var widthValue: Int32 = 0 var heightValue: Int32 = 0 + var bytesPerRowValue: Int32 = 0 memcpy(&widthValue, bytes.advanced(by: offset), 4) offset += 4 memcpy(&heightValue, bytes.advanced(by: offset), 4) offset += 4 + memcpy(&bytesPerRowValue, bytes.advanced(by: offset), 4) + offset += 4 width = Int(widthValue) height = Int(heightValue) + bytesPerRow = Int(bytesPerRowValue) return true }) { return nil } - assert(width % 16 == 0) + self.bytesPerRow = bytesPerRow self.width = width self.height = height @@ -150,8 +158,8 @@ private final class AnimatedStickerCachedFrameSource: AnimatedStickerFrameSource self.initialOffset = offset self.offset = offset - self.decodeBuffer = Data(count: width * 4 * height) - self.frameBuffer = Data(count: width * 4 * height) + self.decodeBuffer = Data(count: self.bytesPerRow * height) + self.frameBuffer = Data(count: self.bytesPerRow * height) let frameBufferLength = self.frameBuffer.count self.frameBuffer.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in memset(bytes, 0, frameBufferLength) @@ -203,7 +211,7 @@ private final class AnimatedStickerCachedFrameSource: AnimatedStickerFrameSource } } - return AnimatedStickerFrame(data: frameData!, type: .yuva, width: self.width, height: self.height, isLastFrame: isLastFrame) + return AnimatedStickerFrame(data: frameData!, type: .yuva, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, isLastFrame: isLastFrame) } } @@ -212,6 +220,7 @@ private final class AnimatedStickerDirectFrameSource: AnimatedStickerFrameSource private let data: Data private let width: Int private let height: Int + private let bytesPerRow: Int private let frameCount: Int let frameRate: Int private var currentFrame: Int @@ -222,6 +231,7 @@ private final class AnimatedStickerDirectFrameSource: AnimatedStickerFrameSource self.data = data self.width = width self.height = height + self.bytesPerRow = (4 * Int(width) + 15) & (~15) self.currentFrame = 0 guard let rawData = TGGUnzipData(data, 8 * 1024 * 1024) else { return nil @@ -232,7 +242,6 @@ private final class AnimatedStickerDirectFrameSource: AnimatedStickerFrameSource self.animation = animation self.frameCount = Int(animation.frameCount) self.frameRate = Int(animation.frameRate) - assert(width % 16 == 0) } deinit { @@ -242,12 +251,12 @@ private final class AnimatedStickerDirectFrameSource: AnimatedStickerFrameSource func takeFrame() -> AnimatedStickerFrame { let frameIndex = self.currentFrame % self.frameCount self.currentFrame += 1 - var frameData = Data(count: self.width * self.height * 4) + var frameData = Data(count: self.bytesPerRow * self.height) frameData.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer) -> Void in - memset(bytes, 0, self.width * self.height * 4) - self.animation.renderFrame(with: Int32(frameIndex), into: bytes, width: Int32(self.width), height: Int32(self.height)) + memset(bytes, 0, self.bytesPerRow * self.height) + self.animation.renderFrame(with: Int32(frameIndex), into: bytes, width: Int32(self.width), height: Int32(self.height), bytesPerRow: Int32(self.bytesPerRow)) } - return AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, isLastFrame: frameIndex == self.frameCount) + return AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, isLastFrame: frameIndex == self.frameCount) } } @@ -354,6 +363,9 @@ final class AnimatedStickerNode: ASDisplayNode { } func setup(account: Account, resource: MediaResource, width: Int, height: Int, playbackMode: AnimatedStickerPlaybackMode = .loop, mode: AnimatedStickerMode) { + if width < 2 || height < 2 { + return + } self.playbackMode = playbackMode switch mode { case .direct: @@ -430,7 +442,7 @@ final class AnimatedStickerNode: ASDisplayNode { guard let strongSelf = self else { return } - strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, data: frame.data, type: frame.type, completion: { + strongSelf.renderer?.render(queue: strongSelf.queue, width: frame.width, height: frame.height, bytesPerRow: frame.bytesPerRow, data: frame.data, type: frame.type, completion: { guard let strongSelf = self else { return } diff --git a/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift b/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift index b5429c89c8..d3d6ad1502 100644 --- a/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift +++ b/submodules/TelegramUI/TelegramUI/AnimatedStickerUtils.swift @@ -83,10 +83,12 @@ func fetchCompressedLottieFirstFrameAJpeg(data: Data, size: CGSize, cacheKey: St } let context = DrawingContext(size: size, scale: 1.0, clear: true) - player.renderFrame(with: 0, into: context.bytes.assumingMemoryBound(to: UInt8.self), width: Int32(size.width), height: Int32(size.height)) + player.renderFrame(with: 0, into: context.bytes.assumingMemoryBound(to: UInt8.self), width: Int32(size.width), height: Int32(size.height), bytesPerRow: Int32(context.bytesPerRow)) - let yuvaLength = Int(size.width) * Int(size.height) * 2 + Int(size.width) * Int(size.height) / 2 - assert(yuvaLength % 8 == 0) + let yuvaPixelsPerAlphaRow = (Int(size.width) + 1) & (~1) + assert(yuvaPixelsPerAlphaRow % 2 == 0) + + let yuvaLength = Int(size.width) * Int(size.height) * 2 + yuvaPixelsPerAlphaRow * Int(size.height) / 2 var yuvaFrameData = malloc(yuvaLength)! memset(yuvaFrameData, 0, yuvaLength) @@ -94,8 +96,8 @@ func fetchCompressedLottieFirstFrameAJpeg(data: Data, size: CGSize, cacheKey: St free(yuvaFrameData) } - encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), context.bytes.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height)) - decodeYUVAToRGBA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), context.bytes.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height)) + encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), context.bytes.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(context.bytesPerRow)) + decodeYUVAToRGBA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), context.bytes.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(context.bytesPerRow)) if let colorImage = context.generateImage() { let colorData = NSMutableData() @@ -189,23 +191,29 @@ func experimentalConvertCompressedLottieToCombinedMp4(data: Data, size: CGSize, let scale = size.width / 512.0 + let bytesPerRow = (4 * Int(size.width) + 15) & (~15) + var currentFrame: Int32 = 0 var fps: Int32 = player.frameRate let _ = fileContext.write(&fps, count: 4) var widthValue: Int32 = Int32(size.width) var heightValue: Int32 = Int32(size.height) + var bytesPerRowValue: Int32 = Int32(bytesPerRow) let _ = fileContext.write(&widthValue, count: 4) let _ = fileContext.write(&heightValue, count: 4) + let _ = fileContext.write(&bytesPerRowValue, count: 4) - let frameLength = Int(size.width) * Int(size.height) * 4 + let frameLength = bytesPerRow * Int(size.height) assert(frameLength % 16 == 0) let currentFrameData = malloc(frameLength)! memset(currentFrameData, 0, frameLength) - let yuvaLength = Int(size.width) * Int(size.height) * 2 + Int(size.width) * Int(size.height) / 2 - assert(yuvaLength % 8 == 0) + let yuvaPixelsPerAlphaRow = (Int(size.width) + 1) & (~1) + assert(yuvaPixelsPerAlphaRow % 2 == 0) + + let yuvaLength = Int(size.width) * Int(size.height) * 2 + yuvaPixelsPerAlphaRow * Int(size.height) / 2 var yuvaFrameData = malloc(yuvaLength)! memset(yuvaFrameData, 0, yuvaLength) @@ -234,12 +242,12 @@ func experimentalConvertCompressedLottieToCombinedMp4(data: Data, size: CGSize, let drawStartTime = CACurrentMediaTime() memset(currentFrameData, 0, frameLength) - player.renderFrame(with: Int32(currentFrame), into: currentFrameData.assumingMemoryBound(to: UInt8.self), width: Int32(size.width), height: Int32(size.height)) + player.renderFrame(with: Int32(currentFrame), into: currentFrameData.assumingMemoryBound(to: UInt8.self), width: Int32(size.width), height: Int32(size.height), bytesPerRow: Int32(bytesPerRow)) drawingTime += CACurrentMediaTime() - drawStartTime let appendStartTime = CACurrentMediaTime() - encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), currentFrameData.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height)) + encodeRGBAToYUVA(yuvaFrameData.assumingMemoryBound(to: UInt8.self), currentFrameData.assumingMemoryBound(to: UInt8.self), Int32(size.width), Int32(size.height), Int32(bytesPerRow)) appendingTime += CACurrentMediaTime() - appendStartTime @@ -250,6 +258,9 @@ func experimentalConvertCompressedLottieToCombinedMp4(data: Data, size: CGSize, lhs.pointee = rhs.pointee ^ lhs.pointee lhs = lhs.advanced(by: 1) rhs = rhs.advanced(by: 1) + } + for i in (yuvaLength / 8) * 8 ..< yuvaLength { + } deltaTime += CACurrentMediaTime() - deltaStartTime diff --git a/submodules/TelegramUI/TelegramUI/AnimationRenderer.swift b/submodules/TelegramUI/TelegramUI/AnimationRenderer.swift index 7f728dd7f7..1c171dac83 100644 --- a/submodules/TelegramUI/TelegramUI/AnimationRenderer.swift +++ b/submodules/TelegramUI/TelegramUI/AnimationRenderer.swift @@ -8,5 +8,5 @@ enum AnimationRendererFrameType { } protocol AnimationRenderer { - func render(queue: Queue, width: Int, height: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void) + func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void) } diff --git a/submodules/TelegramUI/TelegramUI/CachedResourceRepresentations.swift b/submodules/TelegramUI/TelegramUI/CachedResourceRepresentations.swift index bd03f1b2bd..cdd435ad6a 100644 --- a/submodules/TelegramUI/TelegramUI/CachedResourceRepresentations.swift +++ b/submodules/TelegramUI/TelegramUI/CachedResourceRepresentations.swift @@ -271,7 +271,7 @@ final class CachedAnimatedStickerRepresentation: CachedMediaResourceRepresentati let height: Int32 var uniqueId: String { - return "animated-sticker-\(self.width)x\(self.height)-v5" + return "animated-sticker-\(self.width)x\(self.height)-v6" } init(width: Int32, height: Int32) { diff --git a/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift index e17b80f464..32fb9fdb8c 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMediaInputStickerGridItem.swift @@ -224,7 +224,8 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { } self.addSubnode(animationNode) } - self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.account.postbox, file: item.stickerItem.file, small: false, size: CGSize(width: 160.0, height: 160.0))) + let dimensions = item.stickerItem.file.dimensions ?? CGSize(width: 512.0, height: 512.0) + self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.account.postbox, file: item.stickerItem.file, small: false, size: dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0)))) self.updateVisibility() self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.account, fileReference: stickerPackFileReference(item.stickerItem.file), resource: item.stickerItem.file.resource).start()) } else { @@ -293,7 +294,9 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { self.animationNode?.visibility = isPlaying if let item = self.item, isPlaying, !self.didSetUpAnimationNode { self.didSetUpAnimationNode = true - self.animationNode?.setup(account: item.account, resource: item.stickerItem.file.resource, width: 160, height: 160, mode: .cached) + let dimensions = item.stickerItem.file.dimensions ?? CGSize(width: 512.0, height: 512.0) + let fittedDimensions = dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0)) + self.animationNode?.setup(account: item.account, resource: item.stickerItem.file.resource, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .cached) } } } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift index 5b2fc88f74..37c42a991c 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift @@ -127,7 +127,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if let telegramFile = media as? TelegramMediaFile { if self.telegramFile?.id != telegramFile.id { self.telegramFile = telegramFile - self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.context.account.postbox, file: telegramFile, small: false, size: CGSize(width: 384.0, height: 384.0), thumbnail: false)) + let dimensions = telegramFile.dimensions ?? CGSize(width: 512.0, height: 512.0) + self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.context.account.postbox, file: telegramFile, small: false, size: dimensions.aspectFitted(CGSize(width: 384.0, height: 384.0)), thumbnail: false)) self.updateVisibility() self.disposable.set(freeMediaFileInteractiveFetched(account: item.context.account, fileReference: .message(message: MessageReference(item.message), media: telegramFile)).start()) } @@ -172,7 +173,9 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if !item.controllerInteraction.stickerSettings.loopAnimatedStickers { playbackMode = .once } - self.animationNode.setup(account: item.context.account, resource: telegramFile.resource, width: 384, height: 384, playbackMode: playbackMode, mode: .cached) + let dimensions = telegramFile.dimensions ?? CGSize(width: 512.0, height: 512.0) + let fittedSize = dimensions.aspectFitted(CGSize(width: 384.0, height: 384.0)) + self.animationNode.setup(account: item.context.account, resource: telegramFile.resource, width: Int(fittedSize.width), height: Int(fittedSize.height), playbackMode: playbackMode, mode: .cached) } else if let emojiResource = self.emojiResource { var playbackMode: AnimatedStickerPlaybackMode = .loop if item.context.sharedContext.immediateExperimentalUISettings.playAnimatedEmojiOnce { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift index c0f9be3518..fa6096a608 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveMediaNode.swift @@ -458,8 +458,9 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { } } else { if file.isAnimatedSticker { + let dimensions = file.dimensions ?? CGSize(width: 512.0, height: 512.0) updateImageSignal = { synchronousLoad in - return chatMessageAnimatedSticker(postbox: context.account.postbox, file: file, small: false, size: CGSize(width: 400.0, height: 400.0)) + return chatMessageAnimatedSticker(postbox: context.account.postbox, file: file, small: false, size: dimensions.aspectFitted(CGSize(width: 400.0, height: 400.0))) } } else if file.isSticker { updateImageSignal = { synchronousLoad in @@ -685,7 +686,9 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode { strongSelf.imageNode.isHidden = true } strongSelf.animatedStickerNode = animatedStickerNode - animatedStickerNode.setup(account: context.account, resource: updatedAnimatedStickerFile.resource, width: 384, height: 384, mode: .cached) + let dimensions = updatedAnimatedStickerFile.dimensions ?? CGSize(width: 512.0, height: 512.0) + let fittedDimensions = dimensions.aspectFitted(CGSize(width: 384.0, height: 384.0)) + animatedStickerNode.setup(account: context.account, resource: updatedAnimatedStickerFile.resource, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .cached) strongSelf.insertSubnode(animatedStickerNode, aboveSubnode: strongSelf.imageNode) animatedStickerNode.visibility = strongSelf.visibility } diff --git a/submodules/TelegramUI/TelegramUI/ChatPinnedMessageTitlePanelNode.swift b/submodules/TelegramUI/TelegramUI/ChatPinnedMessageTitlePanelNode.swift index fdaa8981bf..d620db3a8e 100644 --- a/submodules/TelegramUI/TelegramUI/ChatPinnedMessageTitlePanelNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatPinnedMessageTitlePanelNode.swift @@ -217,7 +217,8 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { updateImageSignal = chatMessagePhotoThumbnail(account: context.account, photoReference: imageReference) } else if let fileReference = updatedMediaReference.concrete(TelegramMediaFile.self) { if fileReference.media.isAnimatedSticker { - updateImageSignal = chatMessageAnimatedSticker(postbox: context.account.postbox, file: fileReference.media, small: false, size: CGSize(width: 160.0, height: 160.0)) + let dimensions = fileReference.media.dimensions ?? CGSize(width: 512.0, height: 512.0) + updateImageSignal = chatMessageAnimatedSticker(postbox: context.account.postbox, file: fileReference.media, small: false, size: dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0))) updatedFetchMediaSignal = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: fileReference.resourceReference(fileReference.media.resource)) } else if fileReference.media.isVideo { updateImageSignal = chatMessageVideoThumbnail(account: context.account, fileReference: fileReference) diff --git a/submodules/TelegramUI/TelegramUI/HorizontalListContextResultsChatInputPanelItem.swift b/submodules/TelegramUI/TelegramUI/HorizontalListContextResultsChatInputPanelItem.swift index 285440a7d5..54b531a1b2 100644 --- a/submodules/TelegramUI/TelegramUI/HorizontalListContextResultsChatInputPanelItem.swift +++ b/submodules/TelegramUI/TelegramUI/HorizontalListContextResultsChatInputPanelItem.swift @@ -380,7 +380,9 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode animationNode.started = { [weak self] in self?.imageNode.alpha = 0.0 } - animationNode.setup(account: item.account, resource: animatedStickerFile.resource, width: 160, height: 160, mode: .cached) + let dimensions = animatedStickerFile.dimensions ?? CGSize(width: 512.0, height: 512.0) + let fittedDimensions = dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0)) + animationNode.setup(account: item.account, resource: animatedStickerFile.resource, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .cached) } } diff --git a/submodules/TelegramUI/TelegramUI/HorizontalStickerGridItem.swift b/submodules/TelegramUI/TelegramUI/HorizontalStickerGridItem.swift index 1649b2b680..f081f0bf7b 100755 --- a/submodules/TelegramUI/TelegramUI/HorizontalStickerGridItem.swift +++ b/submodules/TelegramUI/TelegramUI/HorizontalStickerGridItem.swift @@ -106,7 +106,9 @@ final class HorizontalStickerGridItemNode: GridItemNode { animationNode.started = { [weak self] in self?.imageNode.alpha = 0.0 } - animationNode.setup(account: account, resource: item.file.resource, width: 160, height: 160, mode: .cached) + let dimensions = item.file.dimensions ?? CGSize(width: 512.0, height: 512.0) + let fittedDimensions = dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0)) + animationNode.setup(account: account, resource: item.file.resource, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .cached) self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, fileReference: stickerPackFileReference(item.file), resource: item.file.resource).start()) } else { diff --git a/submodules/TelegramUI/TelegramUI/MediaInputPaneTrendingItem.swift b/submodules/TelegramUI/TelegramUI/MediaInputPaneTrendingItem.swift index 571d79455c..278ba25185 100644 --- a/submodules/TelegramUI/TelegramUI/MediaInputPaneTrendingItem.swift +++ b/submodules/TelegramUI/TelegramUI/MediaInputPaneTrendingItem.swift @@ -113,7 +113,9 @@ final class TrendingTopItemNode: ASDisplayNode { animationNode.started = { [weak self] in self?.imageNode.alpha = 0.0 } - animationNode.setup(account: account, resource: item.file.resource, width: 160, height: 160, mode: .cached) + let dimensions = item.file.dimensions ?? CGSize(width: 512.0, height: 512.0) + let fittedDimensions = dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0)) + animationNode.setup(account: account, resource: item.file.resource, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .cached) self.loadDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, fileReference: stickerPackFileReference(item.file), resource: item.file.resource).start()) } else { self.imageNode.setSignal(chatMessageSticker(account: account, file: item.file, small: true, synchronousLoad: synchronousLoads), attemptSynchronously: synchronousLoads) diff --git a/submodules/TelegramUI/TelegramUI/NotificationContentContext.swift b/submodules/TelegramUI/TelegramUI/NotificationContentContext.swift index 016090accb..aec6d9471d 100644 --- a/submodules/TelegramUI/TelegramUI/NotificationContentContext.swift +++ b/submodules/TelegramUI/TelegramUI/NotificationContentContext.swift @@ -279,8 +279,10 @@ public final class NotificationViewControllerImpl { } view?.addSubnode(animatedStickerNode) } - strongSelf.imageNode.setSignal(chatMessageAnimatedSticker(postbox: accountAndImage.0.postbox, file: fileReference.media, small: false, size: CGSize(width: 512.0, height: 512.0))) - animatedStickerNode.setup(account: accountAndImage.0, resource: fileReference.media.resource, width: 512, height: 512, mode: .direct) + let dimensions = fileReference.media.dimensions ?? CGSize(width: 512.0, height: 512.0) + let fittedDimensions = dimensions.aspectFitted(CGSize(width: 512.0, height: 512.0)) + strongSelf.imageNode.setSignal(chatMessageAnimatedSticker(postbox: accountAndImage.0.postbox, file: fileReference.media, small: false, size: fittedDimensions)) + animatedStickerNode.setup(account: accountAndImage.0, resource: fileReference.media.resource, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .direct) animatedStickerNode.visibility = true accountAndImage.0.network.shouldExplicitelyKeepWorkerConnections.set(.single(true)) diff --git a/submodules/TelegramUI/TelegramUI/SoftwareAnimationRenderer.swift b/submodules/TelegramUI/TelegramUI/SoftwareAnimationRenderer.swift index 85dfc322d3..f13c50adea 100644 --- a/submodules/TelegramUI/TelegramUI/SoftwareAnimationRenderer.swift +++ b/submodules/TelegramUI/TelegramUI/SoftwareAnimationRenderer.swift @@ -6,13 +6,16 @@ import SwiftSignalKit import TelegramUIPrivateModule final class SoftwareAnimationRenderer: ASDisplayNode, AnimationRenderer { - func render(queue: Queue, width: Int, height: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void) { + func render(queue: Queue, width: Int, height: Int, bytesPerRow: Int, data: Data, type: AnimationRendererFrameType, completion: @escaping () -> Void) { queue.async { [weak self] in - let image = generateImagePixel(CGSize(width: CGFloat(width), height: CGFloat(height)), scale: 1.0, pixelGenerator: { _, pixelData in + let calculatedBytesPerRow = (4 * Int(width) + 15) & (~15) + assert(bytesPerRow == calculatedBytesPerRow) + + let image = generateImagePixel(CGSize(width: CGFloat(width), height: CGFloat(height)), scale: 1.0, pixelGenerator: { _, pixelData, bytesPerRow in switch type { case .yuva: data.withUnsafeBytes { (bytes: UnsafePointer) -> Void in - decodeYUVAToRGBA(bytes, pixelData, Int32(width), Int32(height)) + decodeYUVAToRGBA(bytes, pixelData, Int32(width), Int32(height), Int32(bytesPerRow)) } case .argb: data.withUnsafeBytes { (bytes: UnsafePointer) -> Void in diff --git a/submodules/TelegramUI/TelegramUI/StickerPackPreviewController.swift b/submodules/TelegramUI/TelegramUI/StickerPackPreviewController.swift index c7bb483771..b2715d323c 100644 --- a/submodules/TelegramUI/TelegramUI/StickerPackPreviewController.swift +++ b/submodules/TelegramUI/TelegramUI/StickerPackPreviewController.swift @@ -165,7 +165,8 @@ final class StickerPackPreviewController: ViewController { let signal = Signal { subscriber in let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, reference: FileMediaReference.standalone(media: item.file).resourceReference(item.file.resource)).start() let data = account.postbox.mediaBox.resourceData(item.file.resource).start() - let fetchedRepresentation = chatMessageAnimatedStickerDatas(postbox: account.postbox, file: item.file, small: false, size: CGSize(width: 160.0, height: 160.0), fetched: true, onlyFullSize: false, synchronousLoad: false).start(next: { next in + let dimensions = item.file.dimensions ?? CGSize(width: 512.0, height: 512.0) + let fetchedRepresentation = chatMessageAnimatedStickerDatas(postbox: account.postbox, file: item.file, small: false, size: dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0)), fetched: true, onlyFullSize: false, synchronousLoad: false).start(next: { next in let hasContent = next._0 != nil || next._1 != nil subscriber.putNext(hasContent) if hasContent { diff --git a/submodules/TelegramUI/TelegramUI/StickerPackPreviewGridItem.swift b/submodules/TelegramUI/TelegramUI/StickerPackPreviewGridItem.swift index 06b0bdc2b1..693c1cbd18 100644 --- a/submodules/TelegramUI/TelegramUI/StickerPackPreviewGridItem.swift +++ b/submodules/TelegramUI/TelegramUI/StickerPackPreviewGridItem.swift @@ -93,7 +93,8 @@ final class StickerPackPreviewGridItemNode: GridItemNode { if self.currentState == nil || self.currentState!.0 !== account || self.currentState!.1 != stickerItem { if let dimensions = stickerItem.file.dimensions { if stickerItem.file.isAnimatedSticker { - self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: account.postbox, file: stickerItem.file, small: false, size: CGSize(width: 160.0, height: 160.0))) + let dimensions = stickerItem.file.dimensions ?? CGSize(width: 512.0, height: 512.0) + self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: account.postbox, file: stickerItem.file, small: false, size: dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0)))) if self.animationNode == nil { let animationNode = AnimatedStickerNode() @@ -103,7 +104,8 @@ final class StickerPackPreviewGridItemNode: GridItemNode { self?.imageNode.isHidden = true } } - self.animationNode?.setup(account: account, resource: stickerItem.file.resource, width: 160, height: 160, mode: .cached) + let fittedDimensions = dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0)) + self.animationNode?.setup(account: account, resource: stickerItem.file.resource, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .cached) self.animationNode?.visibility = self.isVisibleInGrid && self.interaction?.playAnimatedStickers ?? true self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, fileReference: stickerPackFileReference(stickerItem.file), resource: stickerItem.file.resource).start()) } else { diff --git a/submodules/TelegramUI/TelegramUI/StickerPaneSearchStickerItem.swift b/submodules/TelegramUI/TelegramUI/StickerPaneSearchStickerItem.swift index 92945922a9..82abfd0722 100644 --- a/submodules/TelegramUI/TelegramUI/StickerPaneSearchStickerItem.swift +++ b/submodules/TelegramUI/TelegramUI/StickerPaneSearchStickerItem.swift @@ -159,7 +159,9 @@ final class StickerPaneSearchStickerItemNode: GridItemNode { self.animationNode = animationNode self.addSubnode(animationNode) } - self.animationNode?.setup(account: account, resource: stickerItem.file.resource, width: 160, height: 160, mode: .cached) + let dimensions = stickerItem.file.dimensions ?? CGSize(width: 512.0, height: 512.0) + let fittedDimensions = dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0)) + self.animationNode?.setup(account: account, resource: stickerItem.file.resource, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .cached) self.animationNode?.visibility = self.isVisibleInGrid self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, fileReference: stickerPackFileReference(stickerItem.file), resource: stickerItem.file.resource).start()) } else { diff --git a/submodules/TelegramUI/TelegramUI/StickerPreviewPeekContent.swift b/submodules/TelegramUI/TelegramUI/StickerPreviewPeekContent.swift index 43bd9ca954..736885ee4a 100644 --- a/submodules/TelegramUI/TelegramUI/StickerPreviewPeekContent.swift +++ b/submodules/TelegramUI/TelegramUI/StickerPreviewPeekContent.swift @@ -86,7 +86,10 @@ private final class StickerPreviewPeekContentNode: ASDisplayNode, PeekController let animationNode = AnimatedStickerNode() self.animationNode = animationNode - self.animationNode?.setup(account: account, resource: item.file.resource, width: 400, height: 400, mode: .direct) + let dimensions = item.file.dimensions ?? CGSize(width: 512.0, height: 512.0) + let fittedDimensions = dimensions.aspectFitted(CGSize(width: 400.0, height: 400.0)) + + self.animationNode?.setup(account: account, resource: item.file.resource, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .direct) self.animationNode?.visibility = true self.animationNode?.addSubnode(self.textNode) } else { diff --git a/submodules/TelegramUI/TelegramUI/YUV.h b/submodules/TelegramUI/TelegramUI/YUV.h index 9208d75f39..ab00691a46 100644 --- a/submodules/TelegramUI/TelegramUI/YUV.h +++ b/submodules/TelegramUI/TelegramUI/YUV.h @@ -1,4 +1,4 @@ #import -void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height); -void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height); +void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow); +void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height, int bytesPerRow); diff --git a/submodules/TelegramUI/TelegramUI/YUV.m b/submodules/TelegramUI/TelegramUI/YUV.m index a53dd0c585..78381d714e 100644 --- a/submodules/TelegramUI/TelegramUI/YUV.m +++ b/submodules/TelegramUI/TelegramUI/YUV.m @@ -1,7 +1,7 @@ #import "YUV.h" #import -void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height) { +void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow) { static vImage_ARGBToYpCbCr info; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -15,7 +15,7 @@ void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height) src.data = (void *)argb; src.width = width; src.height = height; - src.rowBytes = width * 4; + src.rowBytes = bytesPerRow; uint8_t permuteMap[4] = {3, 2, 1, 0}; error = vImagePermuteChannels_ARGB8888(&src, &src, permuteMap, kvImageDoNotTile); @@ -48,7 +48,7 @@ void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height) } } -void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height) { +void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height, int bytesPerRow) { static vImage_YpCbCrToARGB info; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -74,7 +74,7 @@ void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height) dest.data = (void *)argb; dest.width = width; dest.height = height; - dest.rowBytes = width * 4; + dest.rowBytes = bytesPerRow; error = vImageConvert_420Yp8_CbCr8ToARGB8888(&srcYp, &srcCbCr, &dest, &info, NULL, 0xff, kvImageDoNotTile); From 67e13e5947606a7e02b264d3d6fea99395a21595 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 30 Jul 2019 20:42:50 +0300 Subject: [PATCH 7/7] Fixed forward message placeholder in send message preview --- .../TelegramUI/TelegramUI/ChatController.swift | 5 +++++ ...hatSendMessageActionSheetControllerNode.swift | 16 +++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index 5d487e8f9a..8cd5957d1b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -240,6 +240,8 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget, private weak var slowmodeTooltipController: ChatSlowmodeHintController? + private weak var sendMessageActionsController: ChatSendMessageActionSheetController? + private var screenCaptureEventsDisposable: Disposable? private let chatAdditionalDataDisposable = MetaDisposable() @@ -3655,6 +3657,7 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget, strongSelf.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .all) } }) + strongSelf.sendMessageActionsController = controller strongSelf.presentInGlobalOverlay(controller, with: nil) } }, statuses: ChatPanelInterfaceInteractionStatuses(editingMessage: self.editingMessage.get(), startingBot: self.startingBot.get(), unblockingPeer: self.unblockingPeer.get(), searching: self.searching.get(), loadingMessage: self.loadingMessage.get())) @@ -4026,6 +4029,8 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget, controller.dismissWithCommitAction() } }) + + self.sendMessageActionsController?.dismiss() } private func saveInterfaceState(includeScrollState: Bool = true) { diff --git a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift index b15375abd9..66452f17b2 100644 --- a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift @@ -203,13 +203,15 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, if let attributedText = textInputNode.attributedText, !attributedText.string.isEmpty { self.fromMessageTextNode.attributedText = attributedText + + if let toAttributedText = self.fromMessageTextNode.attributedText?.mutableCopy() as? NSMutableAttributedString { + toAttributedText.addAttribute(NSAttributedStringKey.foregroundColor, value: self.presentationData.theme.chat.message.outgoing.primaryTextColor, range: NSMakeRange(0, (toAttributedText.string as NSString).length)) + self.toMessageTextNode.attributedText = toAttributedText + } } else { - self.fromMessageTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.ForwardedMessages(Int32(forwardedCount ?? 0)), attributes: [NSAttributedStringKey.foregroundColor: self.presentationData.theme.chat.message.outgoing.primaryTextColor, NSAttributedStringKey.font: Font.regular(self.presentationData.fontSize.baseDisplaySize)]) - } - - if let toAttributedText = self.fromMessageTextNode.attributedText?.mutableCopy() as? NSMutableAttributedString { - toAttributedText.addAttribute(NSAttributedStringKey.foregroundColor, value: self.presentationData.theme.chat.message.outgoing.primaryTextColor, range: NSMakeRange(0, (toAttributedText.string as NSString).length)) - self.toMessageTextNode.attributedText = toAttributedText + self.fromMessageTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.Conversation_InputTextPlaceholder, attributes: [NSAttributedStringKey.foregroundColor: self.presentationData.theme.chat.inputPanel.inputPlaceholderColor, NSAttributedStringKey.font: Font.regular(self.presentationData.fontSize.baseDisplaySize)]) + + self.toMessageTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.ForwardedMessages(Int32(forwardedCount ?? 0)), attributes: [NSAttributedStringKey.foregroundColor: self.presentationData.theme.chat.message.outgoing.primaryTextColor, NSAttributedStringKey.font: Font.regular(self.presentationData.fontSize.baseDisplaySize)]) } self.messageBackgroundNode.contentMode = .scaleToFill @@ -536,7 +538,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, } if self.textInputNode.textView.numberOfLines == 1 || self.textInputNode.textView.attributedText.string.isEmpty { - let textWidth = min(self.fromMessageTextNode.textView.sizeThatFits(layout.size).width + 36.0, messageFrame.width) + let textWidth = min(self.toMessageTextNode.textView.sizeThatFits(layout.size).width + 36.0, messageFrame.width) messageFrame.origin.x += messageFrame.width - textWidth messageFrame.size.width = textWidth }