diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 2f6e8197d6..ddce377bf3 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -704,7 +704,15 @@ public final class AnimationCacheImpl: AnimationCache { init(queue: Queue, basePath: String, allocateTempFile: @escaping () -> String) { self.queue = queue - self.fetchQueues = (0 ..< 2).map { _ in Queue() } + + let fetchQueueCount: Int + if ProcessInfo.processInfo.activeProcessorCount > 2 { + fetchQueueCount = 4 + } else { + fetchQueueCount = 2 + } + + self.fetchQueues = (0 ..< fetchQueueCount).map { i in Queue(name: "AnimationCacheImpl-Fetch\(i)", qos: .default) } self.basePath = basePath self.allocateTempFile = allocateTempFile } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 873088a728..dad5427e80 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -912,11 +912,13 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if let inputNode = inputNodeForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentNode: self.inputNode, interfaceInteraction: self.interfaceInteraction, inputMediaNode: self.inputMediaNode, controllerInteraction: self.controllerInteraction, inputPanelNode: self.inputPanelNode, makeMediaInputNode: { return self.makeMediaInputNode() }) { - /*if let inputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode { - if inputPanelNode.isFocused { - self.context.sharedContext.mainWindow?.simulateKeyboardDismiss(transition: .animated(duration: 0.5, curve: .spring)) + if self.inputMediaNode != nil { + if let inputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode { + if inputPanelNode.isFocused { + self.context.sharedContext.mainWindow?.simulateKeyboardDismiss(transition: .animated(duration: 0.5, curve: .spring)) + } } - }*/ + } if let inputMediaNode = inputNode as? ChatMediaInputNode, self.inputMediaNode == nil { self.inputMediaNode = inputMediaNode inputMediaNode.requestDisableStickerAnimations = { [weak self] disabled in @@ -934,11 +936,16 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { inputNode.alpha = 1.0 inputNode.layer.removeAnimation(forKey: "opacity") immediatelyLayoutInputNodeAndAnimateAppearance = true - /*if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { - self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: inputPanelNode) - } else {*/ - self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) - //} + + if self.inputMediaNode != nil { + if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { + self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: inputPanelNode) + } else { + self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) + } + } else { + self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) + } if let externalTopPanelContainer = inputNode.externalTopPanelContainer { if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { @@ -2098,7 +2105,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.inputMediaNodeDataPromise.set(ChatEntityKeyboardInputNode.inputData(context: self.context, interfaceInteraction: interfaceInteraction, controllerInteraction: self.controllerInteraction)) } - if self.inputMediaNode == nil && !"".isEmpty { + if self.inputMediaNode == nil && !self.context.sharedContext.immediateExperimentalUISettings.inlineStickers { let peerId: PeerId? = self.chatPresentationInterfaceState.chatLocation.peerId let inputNode = ChatMediaInputNode(context: self.context, peerId: peerId, chatLocation: self.chatPresentationInterfaceState.chatLocation, controllerInteraction: self.controllerInteraction, chatWallpaper: self.chatPresentationInterfaceState.chatWallpaper, theme: theme, strings: strings, fontSize: fontSize, gifPaneIsActiveUpdated: { [weak self] value in if let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction { @@ -2522,9 +2529,19 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { }) } } else { - self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in - return (.media(mode: .other, expanded: nil, focused: false), state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) - }) + if self.openStickersDisposable == nil { + self.openStickersDisposable = (self.inputMediaNodeDataPromise.get() + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] _ in + guard let strongSelf = self else { + return + } + + strongSelf.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in + return (.media(mode: .other, expanded: nil, focused: false), state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) + }) + }) + } } } diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 662db807d6..0fbdb124a7 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -110,7 +110,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let emojiItems: Signal = context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000) |> map { view -> EmojiPagerContentComponent in - var emojiItems: [EmojiPagerContentComponent.Item] = [] + struct ItemGroup { + var id: AnyHashable + var items: [EmojiPagerContentComponent.Item] + } + var itemGroups: [ItemGroup] = [] + var itemGroupIndexById: [AnyHashable: Int] = [:] var emojiCollectionIds = Set() for (id, info, _) in view.collectionInfos { @@ -125,27 +130,45 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { guard let item = entry.item as? StickerPackItem else { continue } - if emojiCollectionIds.contains(entry.index.collectionId) { - let resultItem = EmojiPagerContentComponent.Item( - emoji: "", - file: item.file - ) - emojiItems.append(resultItem) + if item.file.isAnimatedSticker || item.file.isVideoSticker { + if emojiCollectionIds.contains(entry.index.collectionId) { + let resultItem = EmojiPagerContentComponent.Item( + emoji: "", + file: item.file + ) + + let groupId = entry.index.collectionId + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) + } + } } } - var itemGroups: [EmojiPagerContentComponent.ItemGroup] = [] - itemGroups.append(EmojiPagerContentComponent.ItemGroup( - id: "all", - title: nil, - items: emojiItems - )) return EmojiPagerContentComponent( context: context, animationCache: animationCache, animationRenderer: animationRenderer, inputInteraction: emojiInputInteraction, - itemGroups: itemGroups, + itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in + var title: String? + if group.id == AnyHashable("recent") { + //TODO:localize + title = "Recently Used".uppercased() + } else { + for (id, info, _) in view.collectionInfos { + if AnyHashable(id) == group.id, let info = info as? StickerPackCollectionInfo { + title = info.title.uppercased() + break + } + } + } + + return EmojiPagerContentComponent.ItemGroup(id: group.id, title: title, items: group.items) + }, itemLayoutType: .compact ) } diff --git a/submodules/TelegramUI/Sources/ChatInputNode.swift b/submodules/TelegramUI/Sources/ChatInputNode.swift index ca1ebffaab..d365208a9f 100644 --- a/submodules/TelegramUI/Sources/ChatInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatInputNode.swift @@ -13,7 +13,7 @@ class ChatInputNode: ASDisplayNode { var externalTopPanelContainer: UIView? - var topBackgroundExtension: CGFloat = 0.0 + var topBackgroundExtension: CGFloat = 41.0 var topBackgroundExtensionUpdated: ((ContainedViewLayoutTransition) -> Void)? func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool) -> (CGFloat, CGFloat) { diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift index a988e0bdc1..031c020cfa 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift @@ -12,7 +12,7 @@ func inputNodeForChatPresentationIntefaceState(_ chatPresentationInterfaceState: } switch chatPresentationInterfaceState.inputMode { case .media: - if "".isEmpty { + if context.sharedContext.immediateExperimentalUISettings.inlineStickers { if let currentNode = currentNode as? ChatEntityKeyboardInputNode { return currentNode } else if let inputMediaNode = inputMediaNode {