diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index 8bf54d388e..0b4f6299b0 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -369,7 +369,7 @@ public struct ChatTextInputStateText: Codable, Equatable { } else if key == ChatTextInputAttributes.textUrl, let value = value as? ChatTextInputTextUrlAttribute { parsedAttributes.append(ChatTextInputStateTextAttribute(type: .textUrl(value.url), range: range.location ..< (range.location + range.length))) } else if key == ChatTextInputAttributes.customEmoji, let value = value as? ChatTextInputTextCustomEmojiAttribute { - parsedAttributes.append(ChatTextInputStateTextAttribute(type: .customEmoji(stickerPack: value.stickerPack, fileId: value.fileId), range: range.location ..< (range.location + range.length))) + parsedAttributes.append(ChatTextInputStateTextAttribute(type: .customEmoji(stickerPack: nil, fileId: value.fileId), range: range.location ..< (range.location + range.length))) } } }) @@ -406,8 +406,8 @@ public struct ChatTextInputStateText: Codable, Equatable { result.addAttribute(ChatTextInputAttributes.textMention, value: ChatTextInputTextMentionAttribute(peerId: id), range: NSRange(location: attribute.range.lowerBound, length: attribute.range.count)) case let .textUrl(url): result.addAttribute(ChatTextInputAttributes.textUrl, value: ChatTextInputTextUrlAttribute(url: url), range: NSRange(location: attribute.range.lowerBound, length: attribute.range.count)) - case let .customEmoji(stickerPack, fileId): - result.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: nil), range: NSRange(location: attribute.range.lowerBound, length: attribute.range.count)) + case let .customEmoji(_, fileId): + result.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: nil), range: NSRange(location: attribute.range.lowerBound, length: attribute.range.count)) } } return result diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index ca9f74c8b7..4209bd062c 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -603,7 +603,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _, _ in + }, sendSticker: { _, _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 77b40bd16a..e5ed2daf83 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -1214,7 +1214,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } } } diff --git a/submodules/ChatListUI/Sources/ChatListTitleView.swift b/submodules/ChatListUI/Sources/ChatListTitleView.swift index acaae6bc52..786946a4d4 100644 --- a/submodules/ChatListUI/Sources/ChatListTitleView.swift +++ b/submodules/ChatListUI/Sources/ChatListTitleView.swift @@ -384,7 +384,7 @@ final class ChatListTitleView: UIView, NavigationBarTitleView, NavigationBarTitl containerSize: CGSize(width: 22.0, height: 22.0) ) titleCredibilityIconTransition.setFrame(view: titleCredibilityIconView, frame: CGRect(origin: CGPoint(x: titleFrame.maxX + 2.0, y: floorToScreenPixels(titleFrame.midY - titleIconSize.height / 2.0)), size: titleIconSize)) - titleCredibilityIconView.isHidden = self.title.activity + titleCredibilityIconView.alpha = self.title.activity ? 0.0 : 1.0 } else { if let titleCredibilityIconView = self.titleCredibilityIconView { self.titleCredibilityIconView = nil diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift index 5e38c1994b..cee082e2a9 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift @@ -99,7 +99,7 @@ public final class ChatPanelInterfaceInteraction { public let displayVideoUnmuteTip: (CGPoint?) -> Void public let switchMediaRecordingMode: () -> Void public let setupMessageAutoremoveTimeout: () -> Void - public let sendSticker: (FileMediaReference, Bool, UIView, CGRect, CALayer?) -> Bool + public let sendSticker: (FileMediaReference, Bool, UIView, CGRect, CALayer?, [ItemCollectionId]) -> Bool public let unblockPeer: () -> Void public let pinMessage: (MessageId, ContextControllerProtocol?) -> Void public let unpinMessage: (MessageId, Bool, ContextControllerProtocol?) -> Void @@ -195,7 +195,7 @@ public final class ChatPanelInterfaceInteraction { displayVideoUnmuteTip: @escaping (CGPoint?) -> Void, switchMediaRecordingMode: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void, - sendSticker: @escaping (FileMediaReference, Bool, UIView, CGRect, CALayer?) -> Bool, + sendSticker: @escaping (FileMediaReference, Bool, UIView, CGRect, CALayer?, [ItemCollectionId]) -> Bool, unblockPeer: @escaping () -> Void, pinMessage: @escaping (MessageId, ContextControllerProtocol?) -> Void, unpinMessage: @escaping (MessageId, Bool, ContextControllerProtocol?) -> Void, @@ -392,7 +392,7 @@ public final class ChatPanelInterfaceInteraction { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _, _ in + }, sendSticker: { _, _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in diff --git a/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift b/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift index ada8d1090c..0e490d89aa 100644 --- a/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift +++ b/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift @@ -141,7 +141,7 @@ public final class ReactionIconView: PortalSourceView { context: context, attemptSynchronousLoad: false, emoji: ChatTextInputTextCustomEmojiAttribute( - stickerPack: nil, + interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file ), diff --git a/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift b/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift index fb551e9a8d..30e2b99e87 100644 --- a/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift +++ b/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift @@ -195,7 +195,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent let reactionLayer = InlineStickerItemLayer( context: context, attemptSynchronousLoad: false, - emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: file.fileId.id, file: file), + emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file), file: file, cache: self.animationCache, renderer: self.animationRenderer, @@ -437,7 +437,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent let reactionLayer = InlineStickerItemLayer( context: context, attemptSynchronousLoad: false, - emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: file.fileId.id, file: file), + emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file), file: file, cache: self.animationCache, renderer: self.animationRenderer, diff --git a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift index 82ffb5da7d..6f90dd4983 100644 --- a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift +++ b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift @@ -518,7 +518,7 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { if let file = self.file { let range = (attributedText.string as NSString).range(of: "#") if range.location != NSNotFound { - attributedText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: file.fileId.id, file: file), range: range) + attributedText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file), range: range) } } diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index 851dbc92e8..da35eaf19e 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -291,7 +291,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -371,7 +371,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: logData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(logData.count), attributes: [.FileName(fileName: "Log-iOS-Short.txt")]) - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -457,7 +457,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -541,7 +541,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -625,7 +625,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -678,7 +678,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { let messages = logs.map { (name, path) -> EnqueueMessage in let id = Int64.random(in: Int64.min ... Int64.max) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: name)]) - return .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + return .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) } let _ = enqueueMessages(account: context.account, peerId: peerId, messages: messages).start() } @@ -786,7 +786,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/zip", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-All.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -1388,7 +1388,7 @@ public func triggerDebugSendLogsUI(context: AccountContext, additionalInfo: Stri context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } diff --git a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift index 92e86ddaee..a2c372118e 100644 --- a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift +++ b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift @@ -340,7 +340,7 @@ public final class SecretMediaPreviewController: ViewController { |> deliverOnMainQueue).start(next: { [weak self] _ in if let strongSelf = self, strongSelf.traceVisibility() { if strongSelf.messageId.peerId.namespace == Namespaces.Peer.CloudUser { - let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() + let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start() } else if strongSelf.messageId.peerId.namespace == Namespaces.Peer.SecretChat { let _ = strongSelf.context.engine.messages.addSecretChatMessageScreenshot(peerId: strongSelf.messageId.peerId).start() } diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift index ed309b3018..828fdd7df4 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift @@ -347,7 +347,7 @@ public func legacyEnqueueGifMessage(account: Account, data: Data, correlationId: fileAttributes.append(.Animated) let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes) - subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)) + subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])) subscriber.putCompletion() } else { subscriber.putError(Void()) @@ -389,7 +389,7 @@ public func legacyEnqueueVideoMessage(account: Account, data: Data, correlationI fileAttributes.append(.Animated) let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes) - subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)) + subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])) subscriber.putCompletion() } else { subscriber.putError(Void()) @@ -463,7 +463,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: false)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: []), uniqueId: item.uniqueId, isFile: false)) } } case let .asset(asset): @@ -486,7 +486,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: false)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: []), uniqueId: item.uniqueId, isFile: false)) case .tempFile: break } @@ -516,7 +516,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: true)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: []), uniqueId: item.uniqueId, isFile: true)) case let .asset(asset): var randomId: Int64 = 0 arc4random_buf(&randomId, 8) @@ -530,7 +530,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: true)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: []), uniqueId: item.uniqueId, isFile: true)) default: break } @@ -665,7 +665,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: asFile)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: []), uniqueId: item.uniqueId, isFile: asFile)) } } } diff --git a/submodules/Pasteboard/Sources/Pasteboard.swift b/submodules/Pasteboard/Sources/Pasteboard.swift index b25ab49f55..b4343090bf 100644 --- a/submodules/Pasteboard/Sources/Pasteboard.swift +++ b/submodules/Pasteboard/Sources/Pasteboard.swift @@ -83,7 +83,7 @@ public func chatInputStateStringFromRTF(_ data: Data, type: NSAttributedString.D } if let emojiId = emojiId { updatedString.removeAttribute(NSAttributedString.Key.link, range: range) - updatedString.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: emojiId, file: nil), range: range) + updatedString.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: emojiId, file: nil), range: range) } } }) diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 2fc6e2d2d7..8fb7849336 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -2151,7 +2151,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { if let emojiFile = state.emojiFile { let range = (secondaryAttributedText.string as NSString).range(of: "#") if range.location != NSNotFound { - secondaryAttributedText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: emojiFile.fileId.id, file: emojiFile), range: range) + secondaryAttributedText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: emojiFile.fileId.id, file: emojiFile), range: range) } } let accountContext = context.component.context diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index 7b30be4e18..d2faaa301e 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -1443,7 +1443,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { let baseItemLayer = InlineStickerItemLayer( context: itemNode.context, attemptSynchronousLoad: false, - emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: itemNode.item.listAnimation.fileId.id, file: itemNode.item.listAnimation), + emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: itemNode.item.listAnimation.fileId.id, file: itemNode.item.listAnimation), file: itemNode.item.listAnimation, cache: animationCache, renderer: animationRenderer, @@ -1918,9 +1918,12 @@ public final class StandaloneReactionAnimation: ASDisplayNode { itemNode.isExtracted = true var selfTargetBounds = targetView.bounds - if case .builtin = itemNode.item.reaction.rawValue { - selfTargetBounds = selfTargetBounds.insetBy(dx: -selfTargetBounds.width * 0.5, dy: -selfTargetBounds.height * 0.5) + if let targetView = targetView as? ReactionIconView, let iconFrame = targetView.iconFrame { + selfTargetBounds = iconFrame } + /*if case .builtin = itemNode.item.reaction.rawValue { + selfTargetBounds = selfTargetBounds.insetBy(dx: -selfTargetBounds.width * 0.5, dy: -selfTargetBounds.height * 0.5) + }*/ let selfTargetRect = self.view.convert(selfTargetBounds, from: targetView) @@ -2027,7 +2030,7 @@ public final class StandaloneReactionAnimation: ASDisplayNode { let baseItemLayer = InlineStickerItemLayer( context: itemNode.context, attemptSynchronousLoad: false, - emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: itemNode.item.listAnimation.fileId.id, file: itemNode.item.listAnimation), + emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: itemNode.item.listAnimation.fileId.id, file: itemNode.item.listAnimation), file: itemNode.item.listAnimation, cache: animationCache, renderer: animationRenderer, diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index 9d68f1e533..9e9e9349a7 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -537,7 +537,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll |> take(1)).start(next: { previewTheme, settings in let saveThemeTemplateFile: (String, LocalFileMediaResource, @escaping () -> Void) -> Void = { title, resource, completion in let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: resource.fileId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/x-tgtheme-ios", size: nil, attributes: [.FileName(fileName: "\(title).tgios-theme")]) - let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = enqueueMessages(account: context.account, peerId: context.account.peerId, messages: [message]).start() diff --git a/submodules/ShareController/Sources/ShareController.swift b/submodules/ShareController/Sources/ShareController.swift index 35302bd629..ad3420bddb 100644 --- a/submodules/ShareController/Sources/ShareController.swift +++ b/submodules/ShareController/Sources/ShareController.swift @@ -583,9 +583,9 @@ public final class ShareController: ViewController { for peerId in peerIds { var messages: [EnqueueMessage] = [] if !text.isEmpty { - messages.append(.message(text: url + "\n\n" + text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: url + "\n\n" + text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } else { - messages.append(.message(text: url, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: url, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) @@ -594,9 +594,9 @@ public final class ShareController: ViewController { for peerId in peerIds { var messages: [EnqueueMessage] = [] if !text.isEmpty { - messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } - messages.append(.message(text: string, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: string, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) } @@ -604,19 +604,19 @@ public final class ShareController: ViewController { for peerId in peerIds { var messages: [EnqueueMessage] = [] if !text.isEmpty { - messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } let attributedText = NSMutableAttributedString(string: string, attributes: [ChatTextInputAttributes.italic: true as NSNumber]) attributedText.append(NSAttributedString(string: "\n\n\(url)")) let entities = generateChatInputTextEntities(attributedText) - messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) } case let .image(representations): for peerId in peerIds { var messages: [EnqueueMessage] = [] - messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) } @@ -629,9 +629,9 @@ public final class ShareController: ViewController { for peerId in peerIds { var messages: [EnqueueMessage] = [] if !text.isEmpty && !sendTextAsCaption { - messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } - messages.append(.message(text: sendTextAsCaption ? text : "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: sendTextAsCaption ? text : "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) } @@ -639,9 +639,9 @@ public final class ShareController: ViewController { for peerId in peerIds { var messages: [EnqueueMessage] = [] if !text.isEmpty { - messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } - messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) } @@ -649,7 +649,7 @@ public final class ShareController: ViewController { for peerId in peerIds { var messagesToEnqueue: [EnqueueMessage] = [] if !text.isEmpty { - messagesToEnqueue.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messagesToEnqueue.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } for message in messages { messagesToEnqueue.append(.forward(source: message.id, grouping: .auto, attributes: [], correlationId: nil)) diff --git a/submodules/ShareItems/Sources/ShareItems.swift b/submodules/ShareItems/Sources/ShareItems.swift index f61b926064..9ceeaf925a 100644 --- a/submodules/ShareItems/Sources/ShareItems.swift +++ b/submodules/ShareItems/Sources/ShareItems.swift @@ -459,11 +459,11 @@ public func sentShareItems(account: Account, to peerIds: [PeerId], items: [Prepa for item in items { switch item { case let .text(text): - messages.append(.message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) case let .media(media): switch media { case let .media(reference): - let message: EnqueueMessage = .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: reference, replyToMessageId: nil, localGroupingKey: groupingKey, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: reference, replyToMessageId: nil, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: []) messages.append(message) mediaMessages.append(message) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift index 10342c97cc..98eca08ff2 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift @@ -203,9 +203,9 @@ final class StickerPackEmojisItemNode: GridItemNode { var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? loop: for attribute in file.attributes { switch attribute { - case let .CustomEmoji(_, displayText, packReference): + case let .CustomEmoji(_, displayText, _): text = displayText - emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: file.fileId.id, file: file) + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file) break loop default: break @@ -229,9 +229,9 @@ final class StickerPackEmojisItemNode: GridItemNode { var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? loop: for attribute in file.attributes { switch attribute { - case let .CustomEmoji(_, displayText, packReference): + case let .CustomEmoji(_, displayText, _): text = displayText - emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: file.fileId.id, file: file) + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file) break loop default: break diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 76db26f87d..36436c00bf 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -1669,7 +1669,7 @@ public final class StickerPackScreenImpl: ViewController { MessageTextEntity( range: 0 ..< (text as NSString).length, type: .CustomEmoji( - stickerPack: attribute.stickerPack, + stickerPack: nil, fileId: attribute.fileId ) ) diff --git a/submodules/TelegramCallsUI/Sources/CallRatingController.swift b/submodules/TelegramCallsUI/Sources/CallRatingController.swift index 094191b079..5bed132d4d 100644 --- a/submodules/TelegramCallsUI/Sources/CallRatingController.swift +++ b/submodules/TelegramCallsUI/Sources/CallRatingController.swift @@ -292,7 +292,7 @@ func rateCallAndSendLogs(engine: TelegramEngine, callId: CallId, starsCount: Int let name = "\(callId.id)_\(callId.accessHash).log.json" let path = callLogsPath(account: engine.account) + "/" + name let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: name)]) - let message = EnqueueMessage.message(text: comment, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: comment, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) return rate |> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [message]) |> mapToSignal({ _ -> Signal in @@ -300,7 +300,7 @@ func rateCallAndSendLogs(engine: TelegramEngine, callId: CallId, starsCount: Int })) } else if !comment.isEmpty { return rate - |> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [.message(text: comment, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + |> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [.message(text: comment, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) |> mapToSignal({ _ -> Signal in return .single(Void()) })) diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index bc3e5f39ad..42853c8fc9 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -1264,7 +1264,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController dismissController?() if let strongSelf = self { - let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: listenerLink, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: listenerLink, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) |> deliverOnMainQueue).start(next: { [weak self] _ in if let strongSelf = self { strongSelf.presentUndoOverlay(content: .forward(savedMessages: false, text: strongSelf.presentationData.strings.UserInfo_LinkForwardTooltip_Chat_One(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string), action: { _ in return true }) diff --git a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift index d2b70fb1e6..0dfbb197a4 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift @@ -9,13 +9,13 @@ public enum EnqueueMessageGrouping { } public enum EnqueueMessage { - case message(text: String, attributes: [MessageAttribute], inlineStickers: [MediaId: Media], mediaReference: AnyMediaReference?, replyToMessageId: MessageId?, localGroupingKey: Int64?, correlationId: Int64?) + case message(text: String, attributes: [MessageAttribute], inlineStickers: [MediaId: Media], mediaReference: AnyMediaReference?, replyToMessageId: MessageId?, localGroupingKey: Int64?, correlationId: Int64?, bubbleUpEmojiOrStickersets: [ItemCollectionId]) case forward(source: MessageId, grouping: EnqueueMessageGrouping, attributes: [MessageAttribute], correlationId: Int64?) public func withUpdatedReplyToMessageId(_ replyToMessageId: MessageId?) -> EnqueueMessage { switch self { - case let .message(text, attributes, inlineStickers, mediaReference, _, localGroupingKey, correlationId): - return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId) + case let .message(text, attributes, inlineStickers, mediaReference, _, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets): + return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets) case .forward: return self } @@ -23,8 +23,8 @@ public enum EnqueueMessage { public func withUpdatedAttributes(_ f: ([MessageAttribute]) -> [MessageAttribute]) -> EnqueueMessage { switch self { - case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId): - return .message(text: text, attributes: f(attributes), inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId) + case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets): + return .message(text: text, attributes: f(attributes), inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets) case let .forward(source, grouping, attributes, correlationId): return .forward(source: source, grouping: grouping, attributes: f(attributes), correlationId: correlationId) } @@ -32,8 +32,8 @@ public enum EnqueueMessage { public func withUpdatedGroupingKey(_ f: (Int64?) -> Int64?) -> EnqueueMessage { switch self { - case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId): - return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: f(localGroupingKey), correlationId: correlationId) + case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets): + return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: f(localGroupingKey), correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets) case .forward: return self } @@ -41,15 +41,15 @@ public enum EnqueueMessage { public func withUpdatedCorrelationId(_ value: Int64?) -> EnqueueMessage { switch self { - case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, _): - return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: value) + case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, _, bubbleUpEmojiOrStickersets): + return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: value, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets) case let .forward(source, grouping, attributes, _): return .forward(source: source, grouping: grouping, attributes: attributes, correlationId: value) } } public var groupingKey: Int64? { - if case let .message(_, _, _, _, _, localGroupingKey, _) = self { + if case let .message(_, _, _, _, _, localGroupingKey, _, _) = self { return localGroupingKey } else { return nil @@ -60,12 +60,21 @@ public enum EnqueueMessage { private extension EnqueueMessage { var correlationId: Int64? { switch self { - case let .message(_, _, _, _, _, _, correlationId): + case let .message(_, _, _, _, _, _, correlationId, _): return correlationId case let .forward(_, _, _, correlationId): return correlationId } } + + var bubbleUpEmojiOrStickersets: [ItemCollectionId] { + switch self { + case let .message(_, _, _, _, _, _, _, bubbleUpEmojiOrStickersets): + return bubbleUpEmojiOrStickersets + case .forward: + return [] + } + } } func augmentMediaWithReference(_ mediaReference: AnyMediaReference) -> Media { @@ -179,7 +188,7 @@ private func opportunisticallyTransformOutgoingMedia(network: Network, postbox: var hasMedia = false loop: for message in messages { switch message { - case let .message(_, _, _, mediaReference, _, _, _): + case let .message(_, _, _, mediaReference, _, _, _, _): if mediaReference != nil { hasMedia = true break loop @@ -196,14 +205,14 @@ private func opportunisticallyTransformOutgoingMedia(network: Network, postbox: var signals: [Signal<(Bool, EnqueueMessage), NoError>] = [] for message in messages { switch message { - case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId): + case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets): if let mediaReference = mediaReference { signals.append(opportunisticallyTransformMessageWithMedia(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, mediaReference: mediaReference, userInteractive: userInteractive) |> map { result -> (Bool, EnqueueMessage) in if let result = result { - return (true, .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: .standalone(media: result.media), replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId)) + return (true, .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: .standalone(media: result.media), replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)) } else { - return (false, .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId)) + return (false, .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)) } }) } else { @@ -265,17 +274,19 @@ public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal< var filteredAttributes: [MessageAttribute] = [] var replyToMessageId: MessageId? + var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] inner: for attribute in message.attributes { if let attribute = attribute as? ReplyMessageAttribute { replyToMessageId = attribute.messageId - } else if attribute is OutgoingMessageInfoAttribute { + } else if let attribute = attribute as? OutgoingMessageInfoAttribute { + bubbleUpEmojiOrStickersets = attribute.bubbleUpEmojiOrStickersets continue inner } else { filteredAttributes.append(attribute) } } - messages.append(.message(text: message.text, attributes: filteredAttributes, inlineStickers: [:], mediaReference: message.media.first.flatMap(AnyMediaReference.standalone), replyToMessageId: replyToMessageId, localGroupingKey: message.groupingKey, correlationId: nil)) + messages.append(.message(text: message.text, attributes: filteredAttributes, inlineStickers: [:], mediaReference: message.media.first.flatMap(AnyMediaReference.standalone), replyToMessageId: replyToMessageId, localGroupingKey: message.groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)) } } let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: messages.map { (false, $0) }) @@ -305,7 +316,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, } } switch message { - case let .message(_, attributes, _, _, replyToMessageId, _, _): + case let .message(_, attributes, _, _, replyToMessageId, _, _, _): if let replyToMessageId = replyToMessageId, replyToMessageId.peerId != peerId, let replyMessage = transaction.getMessage(replyToMessageId) { var canBeForwarded = true if replyMessage.id.namespace != Namespaces.Message.Cloud { @@ -329,7 +340,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, mediaReference = .standalone(media: media) } } - updatedMessages.append((transformedMedia, .message(text: sourceMessage.text, attributes: sourceMessage.attributes, inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))) + updatedMessages.append((transformedMedia, .message(text: sourceMessage.text, attributes: sourceMessage.attributes, inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))) continue outer } } @@ -367,11 +378,11 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, if transformedMedia { infoFlags.insert(.transformedMedia) } - attributes.append(OutgoingMessageInfoAttribute(uniqueId: randomId, flags: infoFlags, acknowledged: false, correlationId: message.correlationId)) + attributes.append(OutgoingMessageInfoAttribute(uniqueId: randomId, flags: infoFlags, acknowledged: false, correlationId: message.correlationId, bubbleUpEmojiOrStickersets: message.bubbleUpEmojiOrStickersets)) globallyUniqueIds.append(randomId) switch message { - case let .message(text, requestedAttributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, _): + case let .message(text, requestedAttributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, _, _): for (_, file) in inlineStickers { transaction.storeMediaIfNotPresent(media: file) } diff --git a/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift b/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift index 24ef0cda8e..4fcbd889b7 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift @@ -375,7 +375,7 @@ private func uploadedMediaImageContent(network: Network, postbox: Postbox, trans let attribute = updatedAttributes[index] as! OutgoingMessageInfoAttribute updatedAttributes[index] = attribute.withUpdatedFlags(attribute.flags.union([.transformedMedia])) } else { - updatedAttributes.append(OutgoingMessageInfoAttribute(uniqueId: Int64.random(in: Int64.min ... Int64.max), flags: [.transformedMedia], acknowledged: false, correlationId: nil)) + updatedAttributes.append(OutgoingMessageInfoAttribute(uniqueId: Int64.random(in: Int64.min ... Int64.max), flags: [.transformedMedia], acknowledged: false, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: updatedAttributes, media: currentMessage.media)) }) @@ -668,7 +668,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili let attribute = updatedAttributes[index] as! OutgoingMessageInfoAttribute updatedAttributes[index] = attribute.withUpdatedFlags(attribute.flags.union([.transformedMedia])) } else { - updatedAttributes.append(OutgoingMessageInfoAttribute(uniqueId: Int64.random(in: Int64.min ... Int64.max), flags: [.transformedMedia], acknowledged: false, correlationId: nil)) + updatedAttributes.append(OutgoingMessageInfoAttribute(uniqueId: Int64.random(in: Int64.min ... Int64.max), flags: [.transformedMedia], acknowledged: false, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: updatedAttributes, media: currentMessage.media)) }) diff --git a/submodules/TelegramCore/Sources/SecretChats/SetSecretChatMessageAutoremoveTimeoutInteractively.swift b/submodules/TelegramCore/Sources/SecretChats/SetSecretChatMessageAutoremoveTimeoutInteractively.swift index 80323fdb3f..2172531520 100644 --- a/submodules/TelegramCore/Sources/SecretChats/SetSecretChatMessageAutoremoveTimeoutInteractively.swift +++ b/submodules/TelegramCore/Sources/SecretChats/SetSecretChatMessageAutoremoveTimeoutInteractively.swift @@ -2,7 +2,6 @@ import Foundation import Postbox import SwiftSignalKit - func _internal_setSecretChatMessageAutoremoveTimeoutInteractively(account: Account, peerId: PeerId, timeout: Int32?) -> Signal { return account.postbox.transaction { transaction -> Void in if let peer = transaction.getPeer(peerId) as? TelegramSecretChat, let state = transaction.getPeerChatState(peerId) as? SecretChatState { @@ -16,7 +15,7 @@ func _internal_setSecretChatMessageAutoremoveTimeoutInteractively(account: Accou transaction.setPeerChatState(peerId, state: updatedState) } - let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.messageAutoremoveTimeoutUpdated(timeout == nil ? 0 : timeout!))), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))]) + let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.messageAutoremoveTimeoutUpdated(timeout == nil ? 0 : timeout!))), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))]) } } } @@ -31,7 +30,7 @@ func _internal_addSecretChatMessageScreenshot(account: Account, peerId: PeerId) default: break } - let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))]) + let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))]) } } } diff --git a/submodules/TelegramCore/Sources/State/ApplyUpdateMessage.swift b/submodules/TelegramCore/Sources/State/ApplyUpdateMessage.swift index 901b66591f..468565ba4e 100644 --- a/submodules/TelegramCore/Sources/State/ApplyUpdateMessage.swift +++ b/submodules/TelegramCore/Sources/State/ApplyUpdateMessage.swift @@ -91,6 +91,8 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes var updatedMessage: StoreMessage? + var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + transaction.updateMessage(message.id, update: { currentMessage in let updatedId: MessageId if let messageId = messageId { @@ -107,6 +109,12 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes updatedId = currentMessage.id } + for attribute in currentMessage.attributes { + if let attribute = attribute as? OutgoingMessageInfoAttribute { + bubbleUpEmojiOrStickersets = attribute.bubbleUpEmojiOrStickersets + } + } + let media: [Media] var attributes: [MessageAttribute] let text: String @@ -262,6 +270,9 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes } } } + if !bubbleUpEmojiOrStickersets.isEmpty { + applyBubbleUpEmojiOrStickersets(transaction: transaction, ids: bubbleUpEmojiOrStickersets) + } stateManager.addUpdates(result) stateManager.addUpdateGroups([.ensurePeerHasLocalState(id: message.id.peerId)]) @@ -335,6 +346,8 @@ func applyUpdateGroupMessages(postbox: Postbox, stateManager: AccountStateManage transaction.updateMessageGroupingKeysAtomically(ids, groupingKey: key) } + var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + for (message, _, updatedMessage) in mapping { transaction.updateMessage(message.id, update: { currentMessage in let updatedId: MessageId @@ -344,6 +357,16 @@ func applyUpdateGroupMessages(postbox: Postbox, stateManager: AccountStateManage updatedId = currentMessage.id } + for attribute in currentMessage.attributes { + if let attribute = attribute as? OutgoingMessageInfoAttribute { + for id in attribute.bubbleUpEmojiOrStickersets { + if !bubbleUpEmojiOrStickersets.contains(id) { + bubbleUpEmojiOrStickersets.append(id) + } + } + } + } + let media: [Media] let attributes: [MessageAttribute] let text: String @@ -409,7 +432,36 @@ func applyUpdateGroupMessages(postbox: Postbox, stateManager: AccountStateManage } } } + if !bubbleUpEmojiOrStickersets.isEmpty { + applyBubbleUpEmojiOrStickersets(transaction: transaction, ids: bubbleUpEmojiOrStickersets) + } stateManager.addUpdates(result) stateManager.addUpdateGroups([.ensurePeerHasLocalState(id: messages[0].id.peerId)]) } } + +private func applyBubbleUpEmojiOrStickersets(transaction: Transaction, ids: [ItemCollectionId]) { + let namespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks, Namespaces.ItemCollection.CloudEmojiPacks] + for namespace in namespaces { + let namespaceIds = ids.filter { $0.namespace == namespace } + if !namespaceIds.isEmpty { + let infos = transaction.getItemCollectionsInfos(namespace: namespace) + + var packDict: [ItemCollectionId: Int] = [:] + for i in 0 ..< infos.count { + packDict[infos[i].0] = i + } + var topSortedPacks: [(ItemCollectionId, ItemCollectionInfo)] = [] + var processedPacks = Set() + for id in namespaceIds { + if let index = packDict[id] { + topSortedPacks.append(infos[index]) + processedPacks.insert(id) + } + } + let restPacks = infos.filter { !processedPacks.contains($0.0) } + let sortedPacks = topSortedPacks + restPacks + transaction.replaceItemCollectionInfos(namespace: namespace, itemCollectionInfos: sortedPacks) + } + } +} diff --git a/submodules/TelegramCore/Sources/State/PendingMessageManager.swift b/submodules/TelegramCore/Sources/State/PendingMessageManager.swift index 94fa5ce7ed..86d70bdfef 100644 --- a/submodules/TelegramCore/Sources/State/PendingMessageManager.swift +++ b/submodules/TelegramCore/Sources/State/PendingMessageManager.swift @@ -798,12 +798,17 @@ public final class PendingMessageManager { flags |= (1 << 13) } + var bubbleUpEmojiOrStickersets = false + var singleMedias: [Api.InputSingleMedia] = [] for (message, content) in messages { var uniqueId: Int64? inner: for attribute in message.attributes { if let outgoingInfo = attribute as? OutgoingMessageInfoAttribute { uniqueId = outgoingInfo.uniqueId + if !outgoingInfo.bubbleUpEmojiOrStickersets.isEmpty { + bubbleUpEmojiOrStickersets = true + } break inner } } @@ -831,6 +836,10 @@ public final class PendingMessageManager { } } + if bubbleUpEmojiOrStickersets { + flags |= Int32(1 << 15) + } + sendMessageRequest = network.request(Api.functions.messages.sendMultiMedia(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, multiMedia: singleMedias, scheduleDate: scheduleTime, sendAs: sendAsInputPeer)) } @@ -1002,6 +1011,7 @@ public final class PendingMessageManager { var replyMessageId: Int32? var scheduleTime: Int32? var sendAsPeerId: PeerId? + var bubbleUpEmojiOrStickersets = false var flags: Int32 = 0 @@ -1010,6 +1020,7 @@ public final class PendingMessageManager { replyMessageId = replyAttribute.messageId.id } else if let outgoingInfo = attribute as? OutgoingMessageInfoAttribute { uniqueId = outgoingInfo.uniqueId + bubbleUpEmojiOrStickersets = !outgoingInfo.bubbleUpEmojiOrStickersets.isEmpty } else if let attribute = attribute as? ForwardSourceInfoAttribute { forwardSourceInfoAttribute = attribute } else if let attribute = attribute as? TextEntitiesMessageAttribute { @@ -1053,8 +1064,16 @@ public final class PendingMessageManager { let sendMessageRequest: Signal, MTRpcError> switch content.content { case .text: + if bubbleUpEmojiOrStickersets { + flags |= Int32(1 << 15) + } + sendMessageRequest = network.requestWithAdditionalInfo(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, message: message.text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, sendAs: sendAsInputPeer), info: .acknowledgement, tag: dependencyTag) case let .media(inputMedia, text): + if bubbleUpEmojiOrStickersets { + flags |= Int32(1 << 15) + } + sendMessageRequest = network.request(Api.functions.messages.sendMedia(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, media: inputMedia, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, sendAs: sendAsInputPeer), tag: dependencyTag) |> map(NetworkRequestResult.result) case let .forward(sourceInfo): diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_OutgoingMessageInfoAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_OutgoingMessageInfoAttribute.swift index 9426cf01ab..eabe75a341 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_OutgoingMessageInfoAttribute.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_OutgoingMessageInfoAttribute.swift @@ -20,12 +20,14 @@ public class OutgoingMessageInfoAttribute: MessageAttribute { public let flags: OutgoingMessageInfoFlags public let acknowledged: Bool public let correlationId: Int64? + public let bubbleUpEmojiOrStickersets: [ItemCollectionId] - public init(uniqueId: Int64, flags: OutgoingMessageInfoFlags, acknowledged: Bool, correlationId: Int64?) { + public init(uniqueId: Int64, flags: OutgoingMessageInfoFlags, acknowledged: Bool, correlationId: Int64?, bubbleUpEmojiOrStickersets: [ItemCollectionId]) { self.uniqueId = uniqueId self.flags = flags self.acknowledged = acknowledged self.correlationId = correlationId + self.bubbleUpEmojiOrStickersets = bubbleUpEmojiOrStickersets } required public init(decoder: PostboxDecoder) { @@ -33,6 +35,11 @@ public class OutgoingMessageInfoAttribute: MessageAttribute { self.flags = OutgoingMessageInfoFlags(rawValue: decoder.decodeInt32ForKey("f", orElse: 0)) self.acknowledged = decoder.decodeInt32ForKey("ack", orElse: 0) != 0 self.correlationId = decoder.decodeOptionalInt64ForKey("cid") + if let data = decoder.decodeDataForKey("bubbleUpEmojiOrStickersets") { + self.bubbleUpEmojiOrStickersets = ItemCollectionId.decodeArrayFromBuffer(ReadBuffer(data: data)) + } else { + self.bubbleUpEmojiOrStickersets = [] + } } public func encode(_ encoder: PostboxEncoder) { @@ -44,13 +51,16 @@ public class OutgoingMessageInfoAttribute: MessageAttribute { } else { encoder.encodeNil(forKey: "cid") } + let bubbleUpEmojiOrStickersetsBuffer = WriteBuffer() + ItemCollectionId.encodeArrayToBuffer(self.bubbleUpEmojiOrStickersets, buffer: bubbleUpEmojiOrStickersetsBuffer) + encoder.encodeData(bubbleUpEmojiOrStickersetsBuffer.makeData(), forKey: "bubbleUpEmojiOrStickersets") } public func withUpdatedFlags(_ flags: OutgoingMessageInfoFlags) -> OutgoingMessageInfoAttribute { - return OutgoingMessageInfoAttribute(uniqueId: self.uniqueId, flags: flags, acknowledged: self.acknowledged, correlationId: self.correlationId) + return OutgoingMessageInfoAttribute(uniqueId: self.uniqueId, flags: flags, acknowledged: self.acknowledged, correlationId: self.correlationId, bubbleUpEmojiOrStickersets: self.bubbleUpEmojiOrStickersets) } public func withUpdatedAcknowledged(_ acknowledged: Bool) -> OutgoingMessageInfoAttribute { - return OutgoingMessageInfoAttribute(uniqueId: self.uniqueId, flags: self.flags, acknowledged: acknowledged, correlationId: self.correlationId) + return OutgoingMessageInfoAttribute(uniqueId: self.uniqueId, flags: self.flags, acknowledged: acknowledged, correlationId: self.correlationId, bubbleUpEmojiOrStickersets: self.bubbleUpEmojiOrStickersets) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift index b8001dea16..ea6522eda3 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift @@ -41,19 +41,19 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, botId: Pe return true } if let media: Media = internalReference.file ?? internalReference.image { - return .message(text: caption, attributes: filteredAttributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: filteredAttributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } else { - return .message(text: caption, attributes: filteredAttributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: filteredAttributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } } else { - return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaGame(gameId: 0, accessHash: 0, name: "", title: internalReference.title ?? "", description: internalReference.description ?? "", image: internalReference.image, file: internalReference.file)), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaGame(gameId: 0, accessHash: 0, name: "", title: internalReference.title ?? "", description: internalReference.description ?? "", image: internalReference.image, file: internalReference.file)), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } } else if let file = internalReference.file, internalReference.type == "gif" { - return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } else if let image = internalReference.image { - return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: image), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: image), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } else if let file = internalReference.file { - return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } else { return nil } @@ -65,9 +65,9 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, botId: Pe let thumbnailResource = thumbnail.resource let imageDimensions = thumbnail.dimensions ?? PixelDimensions(width: 128, height: 128) let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: randomId), representations: [TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil)], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []) - return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: tmpImage), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: tmpImage), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } else { - return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } } else if externalReference.type == "document" || externalReference.type == "gif" || externalReference.type == "audio" || externalReference.type == "voice" { var videoThumbnails: [TelegramMediaFile.VideoThumbnail] = [] @@ -127,9 +127,9 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, botId: Pe } let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: videoThumbnails, immediateThumbnailData: nil, mimeType: externalReference.content?.mimeType ?? "application/binary", size: nil, attributes: fileAttributes) - return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } else { - return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } } case let .text(text, entities, _, replyMarkup): @@ -139,21 +139,21 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, botId: Pe if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) case let .mapLocation(media, replyMarkup): if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) case let .contact(media, replyMarkup): if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) case let .invoice(media, replyMarkup): if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestStartBot.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestStartBot.swift index adea19cb57..acb0dd2963 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestStartBot.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestStartBot.swift @@ -25,7 +25,7 @@ func _internal_requestStartBot(account: Account, botPeerId: PeerId, payload: Str } } } else { - return enqueueMessages(account: account, peerId: botPeerId, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) |> mapToSignal { _ -> Signal in + return enqueueMessages(account: account, peerId: botPeerId, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) |> mapToSignal { _ -> Signal in return .complete() } } diff --git a/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift index 250d30bdfc..c5ff0da858 100644 --- a/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift +++ b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift @@ -103,7 +103,7 @@ public func messageTextWithAttributes(message: EngineMessage) -> NSAttributedStr let updatedString = NSMutableAttributedString(attributedString: attributedText) for entity in entities.sorted(by: { $0.range.lowerBound > $1.range.lowerBound }) { - guard case let .CustomEmoji(stickerPack, fileId) = entity.type else { + guard case let .CustomEmoji(_, fileId) = entity.type else { continue } @@ -111,8 +111,7 @@ public func messageTextWithAttributes(message: EngineMessage) -> NSAttributedStr let currentDict = updatedString.attributes(at: range.lowerBound, effectiveRange: nil) var updatedAttributes: [NSAttributedString.Key: Any] = currentDict - //updatedAttributes[NSAttributedString.Key.foregroundColor] = UIColor.clear.cgColor - updatedAttributes[ChatTextInputAttributes.customEmoji] = ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile) + updatedAttributes[ChatTextInputAttributes.customEmoji] = ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile) let insertString = NSAttributedString(string: updatedString.attributedSubstring(from: range).string, attributes: updatedAttributes) updatedString.replaceCharacters(in: range, with: insertString) diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 22e99077a1..b1f8c7a495 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -278,10 +278,10 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, let index = ranges.count ranges.append((ranges.count, NSRange(location: location, length: length))) attributes[index] = spoilerAttributes(primaryTextColor: primaryTextColor) - case let .CustomEmoji(stickerPack, fileId): + case let .CustomEmoji(_, fileId): let index = ranges.count ranges.append((ranges.count, NSRange(location: location, length: length))) - attributes[index] = customEmojiAttributes(primaryTextColor: primaryTextColor, emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile)) + attributes[index] = customEmojiAttributes(primaryTextColor: primaryTextColor, emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile)) default: break } diff --git a/submodules/TelegramUI/Components/EmojiStatusComponent/Sources/EmojiStatusComponent.swift b/submodules/TelegramUI/Components/EmojiStatusComponent/Sources/EmojiStatusComponent.swift index cde6f3dcd6..b6c9db5aa4 100644 --- a/submodules/TelegramUI/Components/EmojiStatusComponent/Sources/EmojiStatusComponent.swift +++ b/submodules/TelegramUI/Components/EmojiStatusComponent/Sources/EmojiStatusComponent.swift @@ -404,7 +404,7 @@ public final class EmojiStatusComponent: Component { animationLayer = InlineStickerItemLayer( context: component.context, attemptSynchronousLoad: false, - emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: emojiFile.fileId.id, file: emojiFile), + emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: emojiFile.fileId.id, file: emojiFile), file: emojiFile, cache: component.animationCache, renderer: component.animationRenderer, diff --git a/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift b/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift index 271e4398e4..1e5b7a7408 100644 --- a/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift +++ b/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift @@ -159,6 +159,7 @@ public final class EmojiStatusSelectionComponent: Component { hideInputUpdated: { _, _, _ in }, switchToTextInput: {}, switchToGifSubject: { _ in }, + reorderItems: { _, _ in }, makeSearchContainerNode: { _ in return nil }, deviceMetrics: component.deviceMetrics, hiddenInputHeight: 0.0, @@ -397,6 +398,7 @@ public final class EmojiStatusSelectionController: ViewController { } self.isUserInteractionEnabled = false + destinationView.isHidden = true let hapticFeedback: HapticFeedback if let current = self.hapticFeedback { @@ -470,7 +472,7 @@ public final class EmojiStatusSelectionController: ViewController { let baseItemLayer = InlineStickerItemLayer( context: self.context, attemptSynchronousLoad: false, - emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: itemFile.fileId.id, file: itemFile), + emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: itemFile.fileId.id, file: itemFile), file: item.itemFile, cache: animationCache, renderer: animationRenderer, @@ -501,7 +503,6 @@ public final class EmojiStatusSelectionController: ViewController { self.layer.addSublayer(sourceCopyLayer) sourceCopyLayer.frame = sourceLayer.convert(sourceLayer.bounds, to: self.layer) sourceLayer.isHidden = true - destinationView.isHidden = true let previousSourceCopyFrame = sourceCopyLayer.frame @@ -512,7 +513,15 @@ public final class EmojiStatusSelectionController: ViewController { let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .linear) sourceCopyLayer.position = localDestinationFrame.center - transition.animatePositionWithKeyframes(layer: sourceCopyLayer, keyframes: generateParabollicMotionKeyframes(from: previousSourceCopyFrame.center, to: localDestinationFrame.center, elevation: -(localDestinationFrame.center.y - previousSourceCopyFrame.center.y) + 30.0), completion: { [weak self, weak sourceCopyLayer, weak destinationView] _ in + + var midPointY: CGFloat = localDestinationFrame.center.y - 30.0 + if let layout = self.validLayout { + if midPointY < layout.safeInsets.top + 8.0 { + midPointY = max(localDestinationFrame.center.y, layout.safeInsets.top + 8.0) + } + } + + transition.animatePositionWithKeyframes(layer: sourceCopyLayer, keyframes: generateParabollicMotionKeyframes(from: previousSourceCopyFrame.center, to: localDestinationFrame.center, midPointY: midPointY), completion: { [weak self, weak sourceCopyLayer, weak destinationView] _ in guard let strongSelf = self else { return } @@ -549,6 +558,7 @@ public final class EmojiStatusSelectionController: ViewController { sourceCopyLayer.animateKeyframes(values: scaleKeyframes.map({ $0 as NSNumber }), duration: 0.2, keyPath: "transform.scale", timingFunction: CAMediaTimingFunctionName.linear.rawValue) } else { itemCompleted = true + destinationView.isHidden = false } self.animateOut(completion: { @@ -877,8 +887,8 @@ public final class EmojiStatusSelectionController: ViewController { } } -private func generateParabollicMotionKeyframes(from sourcePoint: CGPoint, to targetPosition: CGPoint, elevation: CGFloat) -> [CGPoint] { - let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0, y: sourcePoint.y - elevation) +private func generateParabollicMotionKeyframes(from sourcePoint: CGPoint, to targetPosition: CGPoint, midPointY: CGFloat) -> [CGPoint] { + let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0, y: midPointY) let x1 = sourcePoint.x let y1 = sourcePoint.y diff --git a/submodules/TelegramUI/Components/EmojiSuggestionsComponent/Sources/EmojiSuggestionsComponent.swift b/submodules/TelegramUI/Components/EmojiSuggestionsComponent/Sources/EmojiSuggestionsComponent.swift index a1524f3435..7f928927f1 100644 --- a/submodules/TelegramUI/Components/EmojiSuggestionsComponent/Sources/EmojiSuggestionsComponent.swift +++ b/submodules/TelegramUI/Components/EmojiSuggestionsComponent/Sources/EmojiSuggestionsComponent.swift @@ -284,7 +284,7 @@ public final class EmojiSuggestionsComponent: Component { itemLayer = InlineStickerItemLayer( context: component.context, attemptSynchronousLoad: synchronousLoad, - emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: item.fileId.id, file: item), + emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: item.fileId.id, file: item), file: item, cache: component.animationCache, renderer: component.animationRenderer, diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 955f086c96..96d5a5dadc 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -1496,7 +1496,7 @@ private final class GroupExpandActionButton: UIButton { } public protocol EmojiContentPeekBehavior: AnyObject { - func setGestureRecognizerEnabled(view: UIView, isEnabled: Bool, itemAtPoint: @escaping (CGPoint) -> (EmojiPagerContentComponent.View.ItemLayer, TelegramMediaFile)?) + func setGestureRecognizerEnabled(view: UIView, isEnabled: Bool, itemAtPoint: @escaping (CGPoint) -> (AnyHashable, EmojiPagerContentComponent.View.ItemLayer, TelegramMediaFile)?) } public final class EmojiPagerContentComponent: Component { @@ -1571,7 +1571,7 @@ public final class EmojiPagerContentComponent: Component { public let presentController: (ViewController) -> Void public let presentGlobalOverlayController: (ViewController) -> Void public let navigationController: () -> NavigationController? - public let sendSticker: ((FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?) -> Void)? + public let sendSticker: ((FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?, [ItemCollectionId]) -> Void)? public let chatPeerId: PeerId? public let peekBehavior: EmojiContentPeekBehavior? public let customLayout: CustomLayout? @@ -1588,7 +1588,7 @@ public final class EmojiPagerContentComponent: Component { presentController: @escaping (ViewController) -> Void, presentGlobalOverlayController: @escaping (ViewController) -> Void, navigationController: @escaping () -> NavigationController?, - sendSticker: ((FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?) -> Void)?, + sendSticker: ((FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?, [ItemCollectionId]) -> Void)?, chatPeerId: PeerId?, peekBehavior: EmojiContentPeekBehavior?, customLayout: CustomLayout?, @@ -1842,6 +1842,22 @@ public final class EmojiPagerContentComponent: Component { self.selectedItems = selectedItems } + public func withUpdatedItemGroups(_ itemGroups: [ItemGroup]) -> EmojiPagerContentComponent { + return EmojiPagerContentComponent( + id: self.id, + context: self.context, + avatarPeer: self.avatarPeer, + animationCache: self.animationCache, + animationRenderer: self.animationRenderer, + inputInteractionHolder: self.inputInteractionHolder, + itemGroups: itemGroups, + itemLayoutType: self.itemLayoutType, + warpContentsOnEdges: self.warpContentsOnEdges, + enableLongPress: self.enableLongPress, + selectedItems: self.selectedItems + ) + } + public static func ==(lhs: EmojiPagerContentComponent, rhs: EmojiPagerContentComponent) -> Bool { if lhs === rhs { return true @@ -4399,7 +4415,7 @@ public final class EmojiPagerContentComponent: Component { if itemLayer.displayPlaceholder { return nil } - return (itemLayer, file) + return (item.1.groupId, itemLayer, file) }) let keyboardChildEnvironment = environment[EntityKeyboardChildEnvironment.self].value diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 74fadba6ac..2a2b10d8cb 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -49,7 +49,7 @@ public final class EntityKeyboardComponent: Component { } } - private enum ReorderCategory { + public enum ReorderCategory { case stickers case emoji } @@ -94,6 +94,7 @@ public final class EntityKeyboardComponent: Component { public let hideInputUpdated: (Bool, Bool, Transition) -> Void public let switchToTextInput: () -> Void public let switchToGifSubject: (GifPagerContentComponent.Subject) -> Void + public let reorderItems: (ReorderCategory, [EntityKeyboardTopPanelComponent.Item]) -> Void public let makeSearchContainerNode: (EntitySearchContentType) -> EntitySearchContainerNode? public let deviceMetrics: DeviceMetrics public let hiddenInputHeight: CGFloat @@ -116,6 +117,7 @@ public final class EntityKeyboardComponent: Component { hideInputUpdated: @escaping (Bool, Bool, Transition) -> Void, switchToTextInput: @escaping () -> Void, switchToGifSubject: @escaping (GifPagerContentComponent.Subject) -> Void, + reorderItems: @escaping (ReorderCategory, [EntityKeyboardTopPanelComponent.Item]) -> Void, makeSearchContainerNode: @escaping (EntitySearchContentType) -> EntitySearchContainerNode?, deviceMetrics: DeviceMetrics, hiddenInputHeight: CGFloat, @@ -137,6 +139,7 @@ public final class EntityKeyboardComponent: Component { self.hideInputUpdated = hideInputUpdated self.switchToTextInput = switchToTextInput self.switchToGifSubject = switchToGifSubject + self.reorderItems = reorderItems self.makeSearchContainerNode = makeSearchContainerNode self.deviceMetrics = deviceMetrics self.hiddenInputHeight = hiddenInputHeight @@ -766,31 +769,7 @@ public final class EntityKeyboardComponent: Component { } private func reorderPacks(category: ReorderCategory, items: [EntityKeyboardTopPanelComponent.Item]) { - guard let component = self.component else { - return - } - - var currentIds: [ItemCollectionId] = [] - for item in items { - guard let id = item.id.base as? ItemCollectionId else { - continue - } - currentIds.append(id) - } - let namespace: ItemCollectionId.Namespace - switch category { - case .stickers: - namespace = Namespaces.ItemCollection.CloudStickerPacks - case .emoji: - namespace = Namespaces.ItemCollection.CloudEmojiPacks - } - let _ = (component.emojiContent.context.engine.stickers.reorderStickerPacks(namespace: namespace, itemIds: currentIds) - |> deliverOnMainQueue).start(completed: { [weak self] in - guard let strongSelf = self else { - return - } - strongSelf.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) - }) + self.component?.reorderItems(category, items) } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 4d3e5152f4..d3459081dc 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -913,18 +913,18 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { } } -final class EntityKeyboardTopPanelItemEnvironment: Equatable { - let isExpanded: Bool - let isHighlighted: Bool - let highlightedSubgroupId: AnyHashable? +public final class EntityKeyboardTopPanelItemEnvironment: Equatable { + public let isExpanded: Bool + public let isHighlighted: Bool + public let highlightedSubgroupId: AnyHashable? - init(isExpanded: Bool, isHighlighted: Bool, highlightedSubgroupId: AnyHashable?) { + public init(isExpanded: Bool, isHighlighted: Bool, highlightedSubgroupId: AnyHashable?) { self.isExpanded = isExpanded self.isHighlighted = isHighlighted self.highlightedSubgroupId = highlightedSubgroupId } - static func ==(lhs: EntityKeyboardTopPanelItemEnvironment, rhs: EntityKeyboardTopPanelItemEnvironment) -> Bool { + public static func ==(lhs: EntityKeyboardTopPanelItemEnvironment, rhs: EntityKeyboardTopPanelItemEnvironment) -> Bool { if lhs.isExpanded != rhs.isExpanded { return false } @@ -1137,18 +1137,18 @@ private final class ReorderGestureRecognizer: UIGestureRecognizer { public final class EntityKeyboardTopPanelComponent: Component { public typealias EnvironmentType = EntityKeyboardTopContainerPanelEnvironment - final class Item: Equatable { - let id: AnyHashable - let isReorderable: Bool - let content: AnyComponent + public final class Item: Equatable { + public let id: AnyHashable + public let isReorderable: Bool + public let content: AnyComponent - init(id: AnyHashable, isReorderable: Bool, content: AnyComponent) { + public init(id: AnyHashable, isReorderable: Bool, content: AnyComponent) { self.id = id self.isReorderable = isReorderable self.content = content } - static func ==(lhs: Item, rhs: Item) -> Bool { + public static func ==(lhs: Item, rhs: Item) -> Bool { if lhs.id != rhs.id { return false } diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index 48e86a7696..d431683d97 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -2002,7 +2002,7 @@ private func extractAccountManagerState(records: AccountRecordsView map { messageIds -> MessageId? in if messageIds.isEmpty { return nil diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index f34f12fe0d..ba8d9e35b7 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -828,7 +828,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, enqueueMessage: { message in self?.sendMessages([message]) }, sendSticker: canSendMessagesToChat(strongSelf.presentationInterfaceState) ? { fileReference, sourceNode, sourceRect in - return self?.controllerInteraction?.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) ?? false + return self?.controllerInteraction?.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) ?? false } : nil, sendEmoji: canSendMessagesToChat(strongSelf.presentationInterfaceState) ? { text, attribute in self?.controllerInteraction?.sendEmoji(text, attribute) } : nil, setupTemporaryHiddenMedia: { signal, centralIndex, galleryMedia in @@ -1822,8 +1822,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - strongSelf.sendMessages([.message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)]) - }, sendSticker: { [weak self] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer in + strongSelf.sendMessages([.message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) + }, sendSticker: { [weak self] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer, bubbleUpEmojiOrStickersets in guard let strongSelf = self else { return false } @@ -1919,7 +1919,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - let messages: [EnqueueMessage] = [.message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId)] + let messages: [EnqueueMessage] = [.message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)] if silentPosting { let transformedMessages = strongSelf.transformEnqueueMessages(messages, silentPosting: silentPosting) strongSelf.sendMessages(transformedMessages) @@ -1980,7 +1980,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, nil) - var messages = [EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)] + var messages = [EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])] if silentPosting { messages = strongSelf.transformEnqueueMessages(messages, silentPosting: true) strongSelf.sendMessages(messages) @@ -2314,7 +2314,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G |> deliverOnMainQueue).start(next: { coordinate in if let strongSelf = self { if let coordinate = coordinate { - strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaMap(latitude: coordinate.latitude, longitude: coordinate.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaMap(latitude: coordinate.latitude, longitude: coordinate.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) } else { strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})]), in: .window(.root)) } @@ -2338,7 +2338,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let _ = (strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.context.account.peerId) |> deliverOnMainQueue).start(next: { peer in if let peer = peer as? TelegramUser, let phone = peer.phone, !phone.isEmpty { - strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaContact(firstName: peer.firstName ?? "", lastName: peer.lastName ?? "", phoneNumber: phone, peerId: peer.id, vCardData: nil)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaContact(firstName: peer.firstName ?? "", lastName: peer.lastName ?? "", phoneNumber: phone, peerId: peer.id, vCardData: nil)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) } }) } @@ -2382,7 +2382,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - strongSelf.sendMessages([.message(text: command, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: (postAsReply && messageId != nil) ? messageId! : nil, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: command, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: (postAsReply && messageId != nil) ? messageId! : nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) } }, openInstantPage: { [weak self] message, associatedData in if let strongSelf = self, strongSelf.isNodeLoaded, let navigationController = strongSelf.effectiveNavigationController, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) { @@ -2685,7 +2685,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.ShareMenu_Send, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() if let strongSelf = self { - strongSelf.sendMessages([.message(text: command, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: command, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) } })) } @@ -6421,7 +6421,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var correlationIds: [Int64] = [] for message in messages { switch message { - case let .message(_, _, _, _, _, _, correlationId): + case let .message(_, _, _, _, _, _, correlationId, _): if let correlationId = correlationId { correlationIds.append(correlationId) } @@ -7674,7 +7674,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - strongSelf.sendMessages([.message(text: messageText, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: messageText, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) strongSelf.interfaceInteraction?.updateShowCommands { _ in return false } @@ -8059,9 +8059,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } } - }, sendSticker: { [weak self] file, clearInput, sourceView, sourceRect, sourceLayer in + }, sendSticker: { [weak self] file, clearInput, sourceView, sourceRect, sourceLayer, bubbleUpEmojiOrStickersets in if let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState) { - return strongSelf.controllerInteraction?.sendSticker(file, false, false, nil, clearInput, sourceView, sourceRect, sourceLayer) ?? false + return strongSelf.controllerInteraction?.sendSticker(file, false, false, nil, clearInput, sourceView, sourceRect, sourceLayer, bubbleUpEmojiOrStickersets) ?? false } else { return false } @@ -11129,7 +11129,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } private func editMessageMediaWithMessages(_ messages: [EnqueueMessage]) { - if let message = messages.first, case let .message(text, attributes, _, maybeMediaReference, _, _, _) = message, let mediaReference = maybeMediaReference { + if let message = messages.first, case let .message(text, attributes, _, maybeMediaReference, _, _, _, _) = message, let mediaReference = maybeMediaReference { self.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in var entities: [MessageTextEntity] = [] for attribute in attributes { @@ -11543,7 +11543,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else { return } - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: strongSelf.transformEnqueueMessages([message])) |> deliverOnMainQueue).start(next: { [weak self] _ in if let strongSelf = self, strongSelf.presentationInterfaceState.subject != .scheduledMessages { @@ -11580,7 +11580,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { strongSelf.chatDisplayNode.collapseInput() @@ -11615,7 +11615,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - textEnqueueMessage = .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + textEnqueueMessage = .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) } if peers.count > 1 { var enqueueMessages: [EnqueueMessage] = [] @@ -11654,7 +11654,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } }, nil) - let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) enqueueMessages.append(message) } } @@ -11720,7 +11720,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let textEnqueueMessage = textEnqueueMessage { enqueueMessages.append(textEnqueueMessage) } - enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)) + enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) strongSelf.sendMessages(strongSelf.transformEnqueueMessages(enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime)) } else { let contactController = strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .filter(peer: peerAndContactData.0, contactId: nil, contactData: contactData, completion: { peer, contactData in @@ -11745,7 +11745,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let textEnqueueMessage = textEnqueueMessage { enqueueMessages.append(textEnqueueMessage) } - enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)) + enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) strongSelf.sendMessages(strongSelf.transformEnqueueMessages(enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime)) } }), completed: nil, cancelled: nil) @@ -12177,7 +12177,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(item.fileSize), attributes: attributes) - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyMessageId, localGroupingKey: groupingKey, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyMessageId, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: []) messages.append(message) } if let _ = groupingKey, messages.count % 10 == 0 { @@ -12505,7 +12505,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { strongSelf.chatDisplayNode.collapseInput() @@ -12564,7 +12564,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } }, nil) - let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) enqueueMessages.append(message) } } @@ -12625,7 +12625,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } }, nil) - let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) strongSelf.sendMessages([message]) } else { let contactController = strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .filter(peer: peerAndContactData.0, contactId: nil, contactData: contactData, completion: { peer, contactData in @@ -12645,7 +12645,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } }, nil) - let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) strongSelf.sendMessages([message]) } }), completed: nil, cancelled: nil) @@ -12986,7 +12986,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G )), replyToMessageId: nil, localGroupingKey: nil, - correlationId: nil + correlationId: nil, + bubbleUpEmojiOrStickersets: [] ) strongSelf.sendMessages([message.withUpdatedReplyToMessageId(replyMessageId)]) }) @@ -13092,7 +13093,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let value = value { self.present(UndoOverlayController(presentationData: self.presentationData, content: .dice(dice: dice, context: self.context, text: value, action: canSendMessagesToChat(self.presentationInterfaceState) ? self.presentationData.strings.Conversation_SendDice : nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState), action == .undo { - strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: dice.emoji)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: dice.emoji)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) } return false }), in: .current) @@ -13115,9 +13116,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let defaultReplyMessageId = defaultReplyMessageId { switch message { - case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId): + case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets): if replyToMessageId == nil { - message = .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: defaultReplyMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId) + message = .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: defaultReplyMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets) } case .forward: break @@ -13396,7 +13397,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G fileAttributes.append(.ImageSize(size: PixelDimensions(size))) let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "image/webp", size: Int64(data.count), attributes: fileAttributes) - let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ @@ -13667,7 +13668,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, usedCorrelationId ? correlationId : nil) - strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.compressedData.count), attributes: [.Audio(isVoice: true, duration: Int(data.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId)]) + strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.compressedData.count), attributes: [.Audio(isVoice: true, duration: Int(data.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])]) strongSelf.recorderFeedback?.tap() strongSelf.recorderFeedback = nil @@ -13764,7 +13765,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, nil) - let messages: [EnqueueMessage] = [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: recordedMediaPreview.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(recordedMediaPreview.fileSize), attributes: [.Audio(isVoice: true, duration: Int(recordedMediaPreview.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: self.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)] + let messages: [EnqueueMessage] = [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: recordedMediaPreview.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(recordedMediaPreview.fileSize), attributes: [.Audio(isVoice: true, duration: Int(recordedMediaPreview.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: self.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])] let transformedMessages: [EnqueueMessage] if let silentPosting = silentPosting { @@ -14667,7 +14668,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } } } @@ -15161,7 +15162,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G Queue.mainQueue().async { unblockingPeer.set(false) if let strongSelf = self, restartBot { - let _ = enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() + let _ = enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start() } } })).start()) @@ -15443,7 +15444,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G break } }, sendFile: nil, sendSticker: { [weak self] f, sourceView, sourceRect in - return self?.interfaceInteraction?.sendSticker(f, true, sourceView, sourceRect, nil) ?? false + return self?.interfaceInteraction?.sendSticker(f, true, sourceView, sourceRect, nil, []) ?? false }, requestMessageActionUrlAuth: { [weak self] subject in if case let .url(url) = subject { self?.controllerInteraction?.requestMessageActionUrlAuth(url, subject) diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index f8a7a28af9..6d01a09100 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -4,6 +4,7 @@ import Postbox import SwiftSignalKit import AsyncDisplayKit import TelegramCore +import Postbox import Display import TelegramUIPreferences import AccountContext @@ -74,7 +75,7 @@ public final class ChatControllerInteraction { let toggleMessagesSelection: ([MessageId], Bool) -> Void let sendCurrentMessage: (Bool) -> Void let sendMessage: (String) -> Void - let sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?) -> Bool + let sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?, [ItemCollectionId]) -> Bool let sendEmoji: (String, ChatTextInputTextCustomEmojiAttribute) -> Void let sendGif: (FileMediaReference, UIView, CGRect, Bool, Bool) -> Bool let sendBotContextResultAsGif: (ChatContextResultCollection, ChatContextResult, UIView, CGRect, Bool) -> Bool @@ -180,7 +181,7 @@ public final class ChatControllerInteraction { toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, - sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?) -> Bool, + sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?, [ItemCollectionId]) -> Bool, sendEmoji: @escaping (String, ChatTextInputTextCustomEmojiAttribute) -> Void, sendGif: @escaping (FileMediaReference, UIView, CGRect, Bool, Bool) -> Bool, sendBotContextResultAsGif: @escaping (ChatContextResultCollection, ChatContextResult, UIView, CGRect, Bool) -> Bool, diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 0659b56597..78e643edc8 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -2970,10 +2970,14 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var inlineStickers: [MediaId: Media] = [:] var firstLockedPremiumEmoji: TelegramMediaFile? + var bubbleUpEmojiOrStickersetsById: [Int64: ItemCollectionId] = [:] effectiveInputText.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: effectiveInputText.length), using: { value, _, _ in if let value = value as? ChatTextInputTextCustomEmojiAttribute { if let file = value.file { inlineStickers[file.fileId] = file + if let packId = value.interactivelySelectedFromPackId { + bubbleUpEmojiOrStickersetsById[file.fileId.id] = packId + } if file.isPremiumEmoji && !self.chatPresentationInterfaceState.isPremium && self.chatPresentationInterfaceState.chatLocation.peerId != self.context.account.peerId { if firstLockedPremiumEmoji == nil { firstLockedPremiumEmoji = file @@ -3016,7 +3020,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let trimmedInputText = effectiveInputText.string.trimmingCharacters(in: .whitespacesAndNewlines) let peerId = effectivePresentationInterfaceState.chatLocation.peerId if peerId?.namespace != Namespaces.Peer.SecretChat, let interactiveEmojis = self.interactiveEmojis, interactiveEmojis.emojis.contains(trimmedInputText) { - messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: trimmedInputText)), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: trimmedInputText)), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } else { let inputText = convertMarkdownToAttributes(effectiveInputText) @@ -3033,8 +3037,23 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } else { webpage = self.chatPresentationInterfaceState.urlPreview?.1 } + + var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + for entity in entities { + if case let .CustomEmoji(_, fileId) = entity.type { + if let packId = bubbleUpEmojiOrStickersetsById[fileId] { + if !bubbleUpEmojiOrStickersets.contains(packId) { + bubbleUpEmojiOrStickersets.append(packId) + } + } + } + } + + if bubbleUpEmojiOrStickersets.count > 1 { + bubbleUpEmojiOrStickersets.removeAll() + } - messages.append(.message(text: text.string, attributes: attributes, inlineStickers: inlineStickers, mediaReference: webpage.flatMap(AnyMediaReference.standalone), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text.string, attributes: attributes, inlineStickers: inlineStickers, mediaReference: webpage.flatMap(AnyMediaReference.standalone), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)) } } diff --git a/submodules/TelegramUI/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Sources/ChatEmptyNode.swift index bf7c3fe2f8..3a81a68828 100644 --- a/submodules/TelegramUI/Sources/ChatEmptyNode.swift +++ b/submodules/TelegramUI/Sources/ChatEmptyNode.swift @@ -134,7 +134,7 @@ final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNodeSticke guard let stickerItem = self.stickerItem else { return } - let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self.view, self.stickerNode.bounds, nil) + let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self.view, self.stickerNode.bounds, nil, []) } func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { @@ -303,7 +303,7 @@ final class ChatEmptyNodeNearbyChatContent: ASDisplayNode, ChatEmptyNodeStickerC guard let stickerItem = self.stickerItem else { return } - let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self.view, self.stickerNode.bounds, nil) + let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self.view, self.stickerNode.bounds, nil, []) } func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index ea86c133fc..501229552c 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -633,6 +633,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { private let entityKeyboardView: ComponentHostView private let defaultToEmojiTab: Bool + private var stableReorderableGroupOrder: [EntityKeyboardComponent.ReorderCategory: [ItemCollectionId]] = [:] private var currentInputData: InputData private var inputDataDisposable: Disposable? private var hasRecentGifsDisposable: Disposable? @@ -902,6 +903,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { super.init() + self.currentInputData = self.processInputData(inputData: self.currentInputData) + self.topBackgroundExtension = 34.0 self.followsDefaultHeight = true @@ -911,7 +914,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { var premiumToastCounter = 0 self.emojiInputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak self, weak interfaceInteraction, weak controllerInteraction] _, item, _, _, _, _ in + performItemAction: { [weak self, weak interfaceInteraction, weak controllerInteraction] groupId, item, _, _, _, _ in let _ = (ChatEntityKeyboardInputNode.hasPremium(context: context, chatPeerId: chatPeerId, premiumIfSavedMessages: true) |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in guard let strongSelf = self, let controllerInteraction = controllerInteraction, let interfaceInteraction = interfaceInteraction else { return @@ -922,9 +925,14 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? loop: for attribute in file.attributes { switch attribute { - case let .CustomEmoji(_, displayText, packReference): + case let .CustomEmoji(_, displayText, _): text = displayText - emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: file.fileId.id, file: file) + + var packId: ItemCollectionId? + if let id = groupId.base as? ItemCollectionId { + packId = id + } + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: packId, fileId: file.fileId.id, file: file) break loop default: break @@ -1087,11 +1095,11 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { navigationController: { [weak controllerInteraction] in return controllerInteraction?.navigationController() }, - sendSticker: { [weak controllerInteraction] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer in + sendSticker: { [weak controllerInteraction] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer, bubbleUpEmojiOrStickersets in guard let controllerInteraction = controllerInteraction else { return } - let _ = controllerInteraction.sendSticker(fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer) + let _ = controllerInteraction.sendSticker(fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer, bubbleUpEmojiOrStickersets) }, chatPeerId: chatPeerId, peekBehavior: nil, @@ -1137,7 +1145,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { guard let controllerInteraction = controllerInteraction else { return false } - return controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + return controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) } )) @@ -1152,7 +1160,11 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return } - let _ = interfaceInteraction.sendSticker(.standalone(media: file), false, view, rect, layer) + var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + if let id = groupId.base as? ItemCollectionId { + bubbleUpEmojiOrStickersets.append(id) + } + let _ = interfaceInteraction.sendSticker(.standalone(media: file), false, view, rect, layer, bubbleUpEmojiOrStickersets) } }) }, @@ -1182,7 +1194,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { guard let controllerInteraction = controllerInteraction else { return false } - return controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + return controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) } )) }, @@ -1287,11 +1299,11 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { navigationController: { [weak controllerInteraction] in return controllerInteraction?.navigationController() }, - sendSticker: { [weak controllerInteraction] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer in + sendSticker: { [weak controllerInteraction] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer, bubbleUpEmojiOrStickersets in guard let controllerInteraction = controllerInteraction else { return } - let _ = controllerInteraction.sendSticker(fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer) + let _ = controllerInteraction.sendSticker(fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer, bubbleUpEmojiOrStickersets) }, chatPeerId: chatPeerId, peekBehavior: stickerPeekBehavior, @@ -1331,7 +1343,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } transition = Transition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(contentAnimation) } - strongSelf.currentInputData = inputData + strongSelf.currentInputData = strongSelf.processInputData(inputData: inputData) strongSelf.performLayout(transition: transition) }) @@ -1547,6 +1559,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } strongSelf.gifMode = subject }, + reorderItems: { [weak self] category, items in + guard let strongSelf = self else { + return + } + strongSelf.reorderItems(category: category, items: items) + }, makeSearchContainerNode: { [weak controllerInteraction] content in guard let controllerInteraction = controllerInteraction else { return nil @@ -1593,6 +1611,108 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return (expandedHeight, 0.0) } + private func processStableItemGroupList(category: EntityKeyboardComponent.ReorderCategory, itemGroups: [EmojiPagerContentComponent.ItemGroup]) -> [EmojiPagerContentComponent.ItemGroup] { + let nextIds: [ItemCollectionId] = itemGroups.compactMap { group -> ItemCollectionId? in + if group.isEmbedded { + return nil + } + if group.isFeatured { + return nil + } + if let collectionId = group.groupId.base as? ItemCollectionId { + return collectionId + } else { + return nil + } + } + + let stableOrder = self.stableReorderableGroupOrder[category] ?? nextIds + + var updatedGroups: [EmojiPagerContentComponent.ItemGroup] = [] + + for group in itemGroups { + if !(group.groupId.base is ItemCollectionId) { + updatedGroups.append(group) + } else { + if group.isEmbedded { + continue + } + if group.isFeatured { + continue + } + if !stableOrder.contains(where: { AnyHashable($0) == group.groupId }) { + updatedGroups.append(group) + } + } + } + for id in stableOrder { + if let group = itemGroups.first(where: { $0.groupId == AnyHashable(id) }) { + updatedGroups.append(group) + } + } + for group in itemGroups { + if !updatedGroups.contains(where: { $0.groupId == group.groupId }) { + updatedGroups.append(group) + } + } + + let updatedIds = updatedGroups.compactMap { group -> ItemCollectionId? in + if group.isEmbedded { + return nil + } + if group.isFeatured { + return nil + } + if let collectionId = group.groupId.base as? ItemCollectionId { + return collectionId + } else { + return nil + } + } + + self.stableReorderableGroupOrder[category] = updatedIds + + return updatedGroups + } + + private func processInputData(inputData: InputData) -> InputData { + return InputData( + emoji: inputData.emoji.withUpdatedItemGroups(self.processStableItemGroupList(category: .emoji, itemGroups: inputData.emoji.itemGroups)), + stickers: inputData.stickers.flatMap { stickers in + return stickers.withUpdatedItemGroups(self.processStableItemGroupList(category: .stickers, itemGroups: stickers.itemGroups)) + }, + gifs: inputData.gifs, + availableGifSearchEmojies: inputData.availableGifSearchEmojies + ) + } + + private func reorderItems(category: EntityKeyboardComponent.ReorderCategory, items: [EntityKeyboardTopPanelComponent.Item]) { + var currentIds: [ItemCollectionId] = [] + for item in items { + guard let id = item.id.base as? ItemCollectionId else { + continue + } + currentIds.append(id) + } + let namespace: ItemCollectionId.Namespace + switch category { + case .stickers: + namespace = Namespaces.ItemCollection.CloudStickerPacks + case .emoji: + namespace = Namespaces.ItemCollection.CloudEmojiPacks + } + + self.stableReorderableGroupOrder.removeValue(forKey: category) + + let _ = (self.context.engine.stickers.reorderStickerPacks(namespace: namespace, itemIds: currentIds) + |> deliverOnMainQueue).start(completed: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.performLayout(transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) + }) + } + private func openGifContextMenu(item: GifPagerContentComponent.Item, sourceView: UIView, sourceRect: CGRect, gesture: ContextGesture, isSaved: Bool) { let file = item @@ -1726,133 +1846,6 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let contextController = ContextController(account: strongSelf.context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceView: sourceView, sourceRect: sourceRect)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) strongSelf.controllerInteraction?.presentGlobalOverlayController(contextController, nil) }) - - /*let canSaveGif: Bool - if item.file.fileId.namespace == Namespaces.Media.CloudFile { - canSaveGif = true - } else { - canSaveGif = false - } - - let _ = (self.context.engine.stickers.isGifSaved(id: file.fileId) - |> deliverOnMainQueue).start(next: { [weak self] isGifSaved in - guard let strongSelf = self else { - return - } - var isGifSaved = isGifSaved - if !canSaveGif { - isGifSaved = false - } - let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) - - let gallery = GalleryController(context: strongSelf.context, source: .standaloneMessage(message), streamSingleVideo: true, replaceRootController: { _, _ in - }, baseNavigationController: nil) - gallery.setHintWillBePresentedInPreviewingContext(true) - - var items: [ContextMenuItem] = [] - items.append(.action(ContextMenuActionItem(text: presentationData.strings.MediaPicker_Send, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.actionSheet.primaryTextColor) - }, action: { _, f in - f(.default) - if isSaved { - let _ = self?.controllerInteraction?.sendGif(FileMediaReference.savedGif(media: file), sourceView, sourceRect, false, false) - }/* else if let (collection, result) = file.contextResult { - let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode, sourceRect, false) - }*/ - }))) - - if let currentState = strongSelf.currentState { - let interfaceState = currentState.interfaceState - - var isScheduledMessages = false - if case .scheduledMessages = interfaceState.subject { - isScheduledMessages = true - } - if !isScheduledMessages { - if case let .peer(peerId) = interfaceState.chatLocation { - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - - if peerId != self?.context.account.peerId && peerId.namespace != Namespaces.Peer.SecretChat { - items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_SendSilently, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/SilentIcon"), color: theme.actionSheet.primaryTextColor) - }, action: { _, f in - f(.default) - if isSaved { - let _ = self?.controllerInteraction.sendGif(file.file, sourceNode.view, sourceRect, true, false) - } else if let (collection, result) = file.contextResult { - let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode, sourceRect, true) - } - }))) - } - - if isSaved { - items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) - }, action: { _, f in - f(.default) - - let _ = self?.controllerInteraction.sendGif(file.file, sourceNode.view, sourceRect, false, true) - }))) - } - } - } - } - - if isSaved || isGifSaved { - items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor) - }, action: { _, f in - f(.dismissWithoutContent) - - guard let strongSelf = self else { - return - } - let _ = removeSavedGif(postbox: strongSelf.context.account.postbox, mediaId: file.fileId).start() - }))) - } else if canSaveGif && !isGifSaved { - items.append(.action(ContextMenuActionItem(text: presentationData.strings.Preview_SaveGif, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.actionSheet.primaryTextColor) - }, action: { _, f in - f(.dismissWithoutContent) - - guard let strongSelf = self else { - return - } - - let context = strongSelf.context - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let controllerInteraction = strongSelf.controllerInteraction - let _ = (toggleGifSaved(account: context.account, fileReference: FileMediaReference.savedGif(media: file), saved: true) - |> deliverOnMainQueue).start(next: { result in - switch result { - case .generic: - controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil) - case let .limitExceeded(limit, premiumLimit): - let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) - let text: String - if limit == premiumLimit || premiumConfiguration.isPremiumDisabled { - text = presentationData.strings.Premium_MaxSavedGifsFinalText - } else { - text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string - } - controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: false, action: { action in - if case .info = action { - let controller = PremiumIntroScreen(context: context, source: .savedGifs) - controllerInteraction?.navigationController()?.pushViewController(controller) - return true - } - return false - }), nil) - } - }) - }))) - } - - let contextController = ContextController(account: strongSelf.context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceView: sourceView, sourceRect: sourceRect)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) - strongSelf.controllerInteraction?.presentGlobalOverlayController(contextController, nil) - })*/ } } @@ -1925,7 +1918,7 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV self.clipsToBounds = true let inputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak self] _, item, _, _, _, _ in + performItemAction: { [weak self] groupId, item, _, _, _, _ in let _ = (ChatEntityKeyboardInputNode.hasPremium(context: context, chatPeerId: nil, premiumIfSavedMessages: false) |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in guard let strongSelf = self else { return @@ -1936,9 +1929,13 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? loop: for attribute in file.attributes { switch attribute { - case let .CustomEmoji(_, displayText, packReference): + case let .CustomEmoji(_, displayText, _): text = displayText - emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: file.fileId.id, file: file) + var packId: ItemCollectionId? + if let id = groupId.base as? ItemCollectionId { + packId = id + } + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: packId, fileId: file.fileId.id, file: file) break loop default: break @@ -2141,16 +2138,21 @@ private final class EmojiContentPeekBehaviorImpl: EmojiContentPeekBehavior { self.chatPeerId = chatPeerId } - func setGestureRecognizerEnabled(view: UIView, isEnabled: Bool, itemAtPoint: @escaping (CGPoint) -> (EmojiPagerContentComponent.View.ItemLayer, TelegramMediaFile)?) { + func setGestureRecognizerEnabled(view: UIView, isEnabled: Bool, itemAtPoint: @escaping (CGPoint) -> (AnyHashable, EmojiPagerContentComponent.View.ItemLayer, TelegramMediaFile)?) { if self.peekRecognizer == nil { let peekRecognizer = PeekControllerGestureRecognizer(contentAtPoint: { [weak self, weak view] point in guard let strongSelf = self else { return nil } - guard let (itemLayer, file) = itemAtPoint(point) else { + guard let (groupId, itemLayer, file) = itemAtPoint(point) else { return nil } + var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + if let id = groupId.base as? ItemCollectionId { + bubbleUpEmojiOrStickersets.append(id) + } + let context = strongSelf.context let accountPeerId = context.account.peerId return combineLatest( @@ -2176,7 +2178,7 @@ private final class EmojiContentPeekBehaviorImpl: EmojiContentPeekBehavior { guard let strongSelf = self else { return } - let _ = strongSelf.controllerInteraction.sendSticker(fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer) + let _ = strongSelf.controllerInteraction.sendSticker(fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer, bubbleUpEmojiOrStickersets) } if let chatPeerId = strongSelf.chatPeerId { diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift index adcd4b91ed..3ee921b2e4 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift @@ -212,7 +212,7 @@ func serviceTasksForChatPresentationIntefaceState(context: AccountContext, chatP if let value = value as? ChatTextInputTextCustomEmojiAttribute { if value.fileId == id { text.removeAttribute(ChatTextInputAttributes.customEmoji, range: range) - text.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: file.fileId.id, file: file), range: range) + text.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file), range: range) } } }) diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index 4180590a27..dc5e78f491 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -694,7 +694,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState let id = Int64.random(in: Int64.min ... Int64.max) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: logPath, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: "CallStats.log")]) - let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index 364a3cf5f8..c9724d21f4 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -797,7 +797,7 @@ final class ChatMediaInputNode: ChatInputNode { sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) } else { return false } @@ -865,7 +865,7 @@ final class ChatMediaInputNode: ChatInputNode { sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) } else { return false } @@ -1097,7 +1097,7 @@ final class ChatMediaInputNode: ChatInputNode { let packReference: StickerPackReference = .id(id: info.id.id, accessHash: info.accessHash) let controller = StickerPackScreen(context: strongSelf.context, updatedPresentationData: strongSelf.controllerInteraction.updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) } else { return false } @@ -1609,9 +1609,9 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, animationNode.view, animationNode.bounds, nil) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, animationNode.view, animationNode.bounds, nil, []) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, imageNode.view, imageNode.bounds, nil) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, imageNode.view, imageNode.bounds, nil, []) } } f(.default) @@ -1623,9 +1623,9 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil, []) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil, []) } } f(.default) @@ -1679,7 +1679,7 @@ final class ChatMediaInputNode: ChatInputNode { if let packReference = packReference { let controller = StickerPackScreen(context: strongSelf.context, updatedPresentationData: strongSelf.controllerInteraction.updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { file, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect, nil) + return strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect, nil, []) } else { return false } @@ -1761,9 +1761,9 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, animationNode.view, animationNode.bounds, nil) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, animationNode.view, animationNode.bounds, nil, []) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, imageNode.view, imageNode.bounds, nil) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, imageNode.view, imageNode.bounds, nil, []) } } f(.default) @@ -1775,9 +1775,9 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil, []) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil, []) } } f(.default) @@ -1833,7 +1833,7 @@ final class ChatMediaInputNode: ChatInputNode { if let packReference = packReference { let controller = StickerPackScreen(context: strongSelf.context, updatedPresentationData: strongSelf.controllerInteraction.updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { file, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect, nil) + return strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect, nil, []) } else { return false } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift index 47635290c9..d55f0eeebb 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift @@ -412,7 +412,7 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { if let interfaceInteraction = self.interfaceInteraction, let (_, item, _) = self.currentState, case .ended = recognizer.state { if let isLocked = self.isLocked, isLocked { } else { - let _ = interfaceInteraction.sendSticker(.standalone(media: item.file), false, false, nil, false, self.view, self.bounds, nil) + let _ = interfaceInteraction.sendSticker(.standalone(media: item.file), false, false, nil, false, self.view, self.bounds, nil, []) self.imageNode.layer.animateAlpha(from: 0.5, to: 1.0, duration: 1.0) } } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputTrendingPane.swift b/submodules/TelegramUI/Sources/ChatMediaInputTrendingPane.swift index 1b0375f792..f4369e9256 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputTrendingPane.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputTrendingPane.swift @@ -326,7 +326,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane { let packReference: StickerPackReference = .id(id: info.id.id, accessHash: info.accessHash) let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) } else { return false } diff --git a/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift b/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift index 9c59e4d874..df77623653 100644 --- a/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift +++ b/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift @@ -395,7 +395,6 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode { private let containerNode: ContextControllerSourceNode private let avatarNode: AvatarNode private var videoNode: UniversalVideoNode? - private var credibilityIconNode: ASImageNode? private var videoContent: NativeVideoContent? private let playbackStartDisposable = MetaDisposable() @@ -520,25 +519,7 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode { let _ = context.engine.peers.fetchAndUpdateCachedPeerData(peerId: peer.id).start() } })) - - let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) - if !premiumConfiguration.isPremiumDisabled { - let credibilityIconNode: ASImageNode - if let current = self.credibilityIconNode { - credibilityIconNode = current - } else { - credibilityIconNode = ASImageNode() - credibilityIconNode.displaysAsynchronously = false - credibilityIconNode.displayWithoutProcessing = true - credibilityIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white) - self.containerNode.addSubnode(credibilityIconNode) - } - credibilityIconNode.frame = CGRect(origin: CGPoint(x: 29.0 - UIScreenPixel, y: 29.0 - UIScreenPixel), size: CGSize(width: 10.0, height: 10.0)) - } - } else { - self.credibilityIconNode?.removeFromSupernode() - self.credibilityIconNode = nil - + } else { self.cachedDataDisposable.set(nil) self.videoContent = nil diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index b83c15a204..98fb474230 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -318,7 +318,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { let updatedString = NSMutableAttributedString(attributedString: attributedText) for entity in entities.sorted(by: { $0.range.lowerBound > $1.range.lowerBound }) { - guard case let .CustomEmoji(stickerPack, fileId) = entity.type else { + guard case let .CustomEmoji(_, fileId) = entity.type else { continue } @@ -327,7 +327,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { let currentDict = updatedString.attributes(at: range.lowerBound, effectiveRange: nil) var updatedAttributes: [NSAttributedString.Key: Any] = currentDict updatedAttributes[NSAttributedString.Key.foregroundColor] = UIColor.clear.cgColor - updatedAttributes[ChatTextInputAttributes.customEmoji] = ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile) + updatedAttributes[ChatTextInputAttributes.customEmoji] = ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile) let insertString = NSAttributedString(string: updatedString.attributedSubstring(from: range).string, attributes: updatedAttributes) updatedString.replaceCharacters(in: range, with: insertString) diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsController.swift b/submodules/TelegramUI/Sources/ChatRecentActionsController.swift index b700e2524d..41e6d21994 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsController.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsController.swift @@ -105,7 +105,7 @@ final class ChatRecentActionsController: TelegramBaseController { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _, _ in + }, sendSticker: { _, _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index 3a351f1757..7202f67970 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -261,7 +261,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, activateMessagePinch: { _ in }, openMessageContextActions: { _, _, _, _ in }, navigateToMessage: { _, _ in }, navigateToMessageStandalone: { _ in - }, tapMessage: nil, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _, _, _, _, _ in return false }, sendEmoji: { _, _ in }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { [weak self] url, _, _, _ in + }, tapMessage: nil, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _, _, _, _, _, _ in return false }, sendEmoji: { _, _ in }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { [weak self] url, _, _, _ in self?.openUrl(url) }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { [weak self] message, associatedData in if let strongSelf = self, let navigationController = strongSelf.getNavigationController() { diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 39a2e22322..0530ebeaa7 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -2587,9 +2587,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? loop: for attribute in file.attributes { switch attribute { - case let .CustomEmoji(_, displayText, packReference): + case let .CustomEmoji(_, displayText, _): text = displayText - emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: file.fileId.id, file: file) + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file) break loop default: break @@ -2614,7 +2614,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { if adjacentString.string != previousText.string || adjacentString.attribute(ChatTextInputAttributes.customEmoji, at: 0, effectiveRange: nil) != nil { break } - inputText.replaceCharacters(in: replaceRange, with: NSAttributedString(string: text, attributes: [ChatTextInputAttributes.customEmoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: emojiAttribute.stickerPack, fileId: emojiAttribute.fileId, file: emojiAttribute.file)])) + inputText.replaceCharacters(in: replaceRange, with: NSAttributedString(string: text, attributes: [ChatTextInputAttributes.customEmoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: emojiAttribute.interactivelySelectedFromPackId, fileId: emojiAttribute.fileId, file: emojiAttribute.file)])) replacedUpperBound = replaceRange.lowerBound } else { break diff --git a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift index 486a15d938..ac51a66b60 100644 --- a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift +++ b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift @@ -112,7 +112,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { return false }, openPeer: { _, _, _, _, _ in }, openPeerMention: { _ in }, openMessageContextMenu: { _, _, _, _, _, _ in }, openMessageReactionContextMenu: { _, _, _, _ in }, updateMessageReaction: { _, _ in }, activateMessagePinch: { _ in }, openMessageContextActions: { _, _, _, _ in }, navigateToMessage: { _, _ in }, navigateToMessageStandalone: { _ in - }, tapMessage: nil, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { fileReference, _, _, _, _, node, rect, _ in return selectStickerImpl?(fileReference, node, rect) ?? false }, sendEmoji: { _, _ in }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { _, _, _, _ in }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { _, _ in }, openWallpaper: { _ in }, openTheme: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in }, updateInputMode: { _ in }, openMessageShareMenu: { _ in + }, tapMessage: nil, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { fileReference, _, _, _, _, node, rect, _, _ in return selectStickerImpl?(fileReference, node, rect) ?? false }, sendEmoji: { _, _ in }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { _, _, _, _ in }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { _, _ in }, openWallpaper: { _ in }, openTheme: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in }, updateInputMode: { _ in }, openMessageShareMenu: { _ in }, presentController: { _, _ in }, presentControllerInCurrent: { _, _ in }, navigationController: { @@ -237,7 +237,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) } else { return false } @@ -350,7 +350,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) } else { return false } diff --git a/submodules/TelegramUI/Sources/EmojisChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/EmojisChatInputContextPanelNode.swift index c94ca1f172..782187ba89 100644 --- a/submodules/TelegramUI/Sources/EmojisChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/EmojisChatInputContextPanelNode.swift @@ -206,9 +206,9 @@ final class EmojisChatInputContextPanelNode: ChatInputContextPanelNode { if let file = file { loop: for attribute in file.attributes { switch attribute { - case let .CustomEmoji(_, displayText, packReference): + case let .CustomEmoji(_, displayText, _): text = displayText - emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: file.fileId.id, file: file) + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file) break loop default: break diff --git a/submodules/TelegramUI/Sources/EmojisChatInputPanelItem.swift b/submodules/TelegramUI/Sources/EmojisChatInputPanelItem.swift index ea075f56ba..6420e83f3b 100644 --- a/submodules/TelegramUI/Sources/EmojisChatInputPanelItem.swift +++ b/submodules/TelegramUI/Sources/EmojisChatInputPanelItem.swift @@ -136,7 +136,7 @@ final class EmojisChatInputPanelItemNode: ListViewItemNode { emojiView = EmojiTextAttachmentView( context: item.context, emoji: ChatTextInputTextCustomEmojiAttribute( - stickerPack: nil, + interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file ), diff --git a/submodules/TelegramUI/Sources/ForwardAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ForwardAccessoryPanelNode.swift index 064cb6b28d..2678e8d4bd 100644 --- a/submodules/TelegramUI/Sources/ForwardAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ForwardAccessoryPanelNode.swift @@ -202,7 +202,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode { case let .CustomEmoji(_, fileId): let range = NSRange(location: entity.range.lowerBound, length: entity.range.upperBound - entity.range.lowerBound) if range.lowerBound >= 0 && range.upperBound <= additionalText.length { - additionalText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: fileId, file: messages[0].associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile), range: range) + additionalText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: messages[0].associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile), range: range) } default: break diff --git a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift index b229b974d7..57796fba8f 100644 --- a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift @@ -165,7 +165,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont if let strongSelf = self { let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.interfaceInteraction?.getNavigationController(), sendSticker: { file, sourceView, sourceRect in if let strongSelf = self { - return strongSelf.interfaceInteraction?.sendSticker(file, false, sourceView, sourceRect, nil) ?? false + return strongSelf.interfaceInteraction?.sendSticker(file, false, sourceView, sourceRect, nil, []) ?? false } else { return false } diff --git a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift index ae6925f588..828551c40f 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift @@ -73,7 +73,7 @@ private struct StickerEntry: Identifiable, Comparable { return HorizontalStickerGridItem(account: account, file: self.file, theme: theme, isPreviewed: { item in return false//stickersInteraction.previewedStickerItem == item }, sendSticker: { file, node, rect in - let _ = interfaceInteraction.sendSticker(file, true, node, rect, nil) + let _ = interfaceInteraction.sendSticker(file, true, node, rect, nil, []) }) } } @@ -181,7 +181,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { .action(ContextMenuActionItem(text: strongSelf.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in f(.default) - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, false, nil, true, itemNode.view, itemNode.bounds, nil) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, false, nil, true, itemNode.view, itemNode.bounds, nil, []) })), .action(ContextMenuActionItem(text: isStarred ? strongSelf.strings.Stickers_RemoveFromFavorites : strongSelf.strings.Stickers_AddToFavorites, icon: { theme in generateTintedImage(image: isStarred ? UIImage(bundleImageName: "Chat/Context Menu/Unfave") : UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in f(.default) @@ -225,7 +225,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { if let packReference = packReference { let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: controllerInteraction.navigationController(), sendSticker: { file, sourceNode, sourceRect in if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { - return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect, nil) + return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect, nil, []) } else { return false } diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index 986bd97fbf..193604a501 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -112,9 +112,9 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, animationNode.view, animationNode.bounds, nil) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, animationNode.view, animationNode.bounds, nil, []) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, imageNode.view, imageNode.bounds, nil) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, imageNode.view, imageNode.bounds, nil, []) } } f(.default) @@ -126,9 +126,9 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, animationNode.view, animationNode.bounds, nil) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, animationNode.view, animationNode.bounds, nil, []) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, imageNode.view, imageNode.bounds, nil) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, imageNode.view, imageNode.bounds, nil, []) } } f(.default) @@ -180,7 +180,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie if let packReference = packReference { let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: controllerInteraction.navigationController(), sendSticker: { file, sourceNode, sourceRect in if let strongSelf = self, let controllerInteraction = strongSelf.getControllerInteraction?() { - return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect, nil) + return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect, nil, []) } else { return false } @@ -577,7 +577,7 @@ final class InlineReactionSearchPanel: ChatInputContextPanelNode { guard let strongSelf = self else { return } - let _ = strongSelf.controllerInteraction?.sendSticker(file, false, false, strongSelf.query, true, node, rect, nil) + let _ = strongSelf.controllerInteraction?.sendSticker(file, false, false, strongSelf.query, true, node, rect, nil, []) } self.view.disablesInteractiveTransitionGestureRecognizer = true diff --git a/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift b/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift index c08dd6594f..3b0c5b2fe9 100644 --- a/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift +++ b/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift @@ -212,7 +212,7 @@ func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect, } let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: [.FileName(fileName: "video.mp4"), .Video(duration: Int(finalDuration), size: PixelDimensions(finalDimensions), flags: [.instantRoundVideo])]) - var message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + var message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let scheduleTime: Int32? = scheduleTimestamp > 0 ? scheduleTimestamp : nil diff --git a/submodules/TelegramUI/Sources/OpenChatMessage.swift b/submodules/TelegramUI/Sources/OpenChatMessage.swift index 4469c3d2c1..ba65a7fb87 100644 --- a/submodules/TelegramUI/Sources/OpenChatMessage.swift +++ b/submodules/TelegramUI/Sources/OpenChatMessage.swift @@ -66,7 +66,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool { params.dismissInput() let controllerParams = LocationViewParams(sendLiveLocation: { location in - let outMessage: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let outMessage: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) params.enqueueMessage(outMessage) }, stopLiveLocation: { messageId in params.context.liveLocationManager?.cancelLiveLocation(peerId: messageId?.peerId ?? params.message.id.peerId) diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 199bbd74af..60378caf0d 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -80,7 +80,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in - }, sendSticker: { _, _, _, _, _, _, _, _ in + }, sendSticker: { _, _, _, _, _, _, _, _, _ in return false }, sendEmoji: { _, _ in }, sendGif: { _, _, _, _, _ in diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index d7ccde14a8..4fd01a8600 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -314,7 +314,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _, _ in + }, sendSticker: { _, _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in @@ -2273,7 +2273,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true) }, sendCurrentMessage: { _ in }, sendMessage: { _ in - }, sendSticker: { _, _, _, _, _, _, _, _ in + }, sendSticker: { _, _, _, _, _, _, _, _, _ in return false }, sendEmoji: { _, _ in }, sendGif: { _, _, _, _, _ in @@ -5107,7 +5107,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate if case let .user(peer) = peer, let _ = peer.botInfo { strongSelf.activeActionDisposable.set(strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: block).start()) if !block { - let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() + let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start() if let navigationController = strongSelf.controller?.navigationController as? NavigationController { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id))) } @@ -5532,7 +5532,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate case .help: text = "/help" } - let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() + let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start() if let navigationController = strongSelf.controller?.navigationController as? NavigationController { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: strongSelf.peerId))) @@ -6741,7 +6741,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])) } } } diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index 7d8c6e8ce7..058685628b 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -260,7 +260,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _, _ in + }, sendSticker: { _, _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index f68d5e83e3..d02ec6ceff 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1281,7 +1281,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { tapMessage?(message) }, clickThroughMessage: { clickThroughMessage?() - }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _, _, _, _, _ in return false }, sendEmoji: { _, _ in }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in + }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _, _, _, _, _, _ in return false }, sendEmoji: { _, _ in }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { _, _, _, _ in }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { _, _ in }, openWallpaper: { _ in }, openTheme: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in }, updateInputMode: { _ in }, openMessageShareMenu: { _ in }, presentController: { _, _ in diff --git a/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift b/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift index 4de60fb20e..cb55258fa2 100644 --- a/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift @@ -227,7 +227,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { let packReference: StickerPackReference = .id(id: info.id.id, accessHash: info.accessHash) let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { [weak self] fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) } else { return false } @@ -322,7 +322,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { } }, sendSticker: { [weak self] file, sourceView, sourceRect in if let strongSelf = self { - let _ = strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceView, sourceRect, nil) + let _ = strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceView, sourceRect, nil, []) } }, getItemIsPreviewed: { item in return inputNodeInteraction.previewedStickerPackItem == .pack(item.file) diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift index ea088a38f6..2ee6fa30c7 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift @@ -126,7 +126,7 @@ final class StickersChatInputContextPanelItemNode: ListViewItemNode { for i in 0 ..< self.nodes.count { if self.nodes[i].frame.contains(location) { let file = item.files[i] - let _ = item.interfaceInteraction.sendSticker(.standalone(media: file), true, self.nodes[i].view, self.nodes[i].bounds, nil) + let _ = item.interfaceInteraction.sendSticker(.standalone(media: file), true, self.nodes[i].view, self.nodes[i].bounds, nil, []) break } } diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift index 76c41904a1..116aaec010 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift @@ -137,7 +137,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { .action(ContextMenuActionItem(text: strongSelf.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in f(.default) - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, false, nil, true, itemNode.view, itemNode.bounds, nil) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, false, nil, true, itemNode.view, itemNode.bounds, nil, []) })), .action(ContextMenuActionItem(text: isStarred ? strongSelf.strings.Stickers_RemoveFromFavorites : strongSelf.strings.Stickers_AddToFavorites, icon: { theme in generateTintedImage(image: isStarred ? UIImage(bundleImageName: "Chat/Context Menu/Unfave") : UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in f(.default) @@ -181,7 +181,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { if let packReference = packReference { let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: controllerInteraction.navigationController(), sendSticker: { file, sourceNode, sourceRect in if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { - return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect, nil) + return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect, nil, []) } else { return false } diff --git a/submodules/TextFormat/Sources/ChatTextInputAttributes.swift b/submodules/TextFormat/Sources/ChatTextInputAttributes.swift index 172113d076..b940175bf7 100644 --- a/submodules/TextFormat/Sources/ChatTextInputAttributes.swift +++ b/submodules/TextFormat/Sources/ChatTextInputAttributes.swift @@ -193,12 +193,12 @@ public final class ChatTextInputTextUrlAttribute: NSObject { } public final class ChatTextInputTextCustomEmojiAttribute: NSObject { - public let stickerPack: StickerPackReference? + public let interactivelySelectedFromPackId: ItemCollectionId? public let fileId: Int64 public let file: TelegramMediaFile? - public init(stickerPack: StickerPackReference?, fileId: Int64, file: TelegramMediaFile?) { - self.stickerPack = stickerPack + public init(interactivelySelectedFromPackId: ItemCollectionId?, fileId: Int64, file: TelegramMediaFile?) { + self.interactivelySelectedFromPackId = interactivelySelectedFromPackId self.fileId = fileId self.file = file diff --git a/submodules/TextFormat/Sources/GenerateTextEntities.swift b/submodules/TextFormat/Sources/GenerateTextEntities.swift index 35efbe4f81..87bc82400d 100644 --- a/submodules/TextFormat/Sources/GenerateTextEntities.swift +++ b/submodules/TextFormat/Sources/GenerateTextEntities.swift @@ -165,7 +165,7 @@ public func generateChatInputTextEntities(_ text: NSAttributedString, maxAnimate } else if key == ChatTextInputAttributes.spoiler { entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .Spoiler)) } else if key == ChatTextInputAttributes.customEmoji, let value = value as? ChatTextInputTextCustomEmojiAttribute { - entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .CustomEmoji(stickerPack: value.stickerPack, fileId: value.fileId))) + entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .CustomEmoji(stickerPack: nil, fileId: value.fileId))) } } }) diff --git a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift index d24684327b..7400c9b364 100644 --- a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift +++ b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift @@ -41,8 +41,8 @@ public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [M string.addAttribute(ChatTextInputAttributes.underline, value: true as NSNumber, range: range) case .Spoiler: string.addAttribute(ChatTextInputAttributes.spoiler, value: true as NSNumber, range: range) - case let .CustomEmoji(stickerPack, fileId): - string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: nil), range: range) + case let .CustomEmoji(_, fileId): + string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: nil), range: range) default: break } @@ -250,8 +250,8 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Timecode), value: TelegramTimecode(time: time, text: text), range: range) } } - case let .CustomEmoji(stickerPack, fileId): - string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: message?.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile), range: range) + case let .CustomEmoji(_, fileId): + string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: message?.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile), range: range) default: break } diff --git a/submodules/WatchBridge/Sources/WatchRequestHandlers.swift b/submodules/WatchBridge/Sources/WatchRequestHandlers.swift index 1f348c5f9f..d3ec3fb8d3 100644 --- a/submodules/WatchBridge/Sources/WatchRequestHandlers.swift +++ b/submodules/WatchBridge/Sources/WatchRequestHandlers.swift @@ -199,17 +199,17 @@ final class WatchSendMessageHandler: WatchRequestHandler { if args.replyToMid != 0, let peerId = peerId { replyMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.replyToMid) } - messageSignal = .single((.message(text: args.text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil), peerId)) + messageSignal = .single((.message(text: args.text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []), peerId)) } else if let args = subscription as? TGBridgeSendLocationMessageSubscription, let location = args.location { let peerId = makePeerIdFromBridgeIdentifier(args.peerId) let map = TelegramMediaMap(latitude: location.latitude, longitude: location.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: makeVenue(from: location.venue), liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil) - messageSignal = .single((.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: map), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil), peerId)) + messageSignal = .single((.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: map), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []), peerId)) } else if let args = subscription as? TGBridgeSendStickerMessageSubscription { let peerId = makePeerIdFromBridgeIdentifier(args.peerId) messageSignal = mediaForSticker(documentId: args.document.documentId, account: context.account) |> map({ media -> (EnqueueMessage?, PeerId?) in if let media = media { - return (.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil), peerId) + return (.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []), peerId) } else { return (nil, nil) } @@ -720,7 +720,7 @@ final class WatchAudioHandler: WatchRequestHandler { replyMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: replyToMid) } - let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.count), attributes: [.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)]).start() + let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.count), attributes: [.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start() } }) } else {