diff --git a/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift b/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift index 6218989e60..b28c582f06 100644 --- a/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift +++ b/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift @@ -471,7 +471,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode { let host: String? = concealed ? urlString : parsedUrl?.host if let url = parsedUrl, let host = host { primaryUrl = urlString - title = NSAttributedString(string: (tempTitleString as String).uppercased(), font: titleFont, textColor: item.presentationData.theme.theme.list.itemPrimaryTextColor) + title = NSAttributedString(string: (tempTitleString as String).capitalized, font: titleFont, textColor: item.presentationData.theme.theme.list.itemPrimaryTextColor) if url.path.hasPrefix("/addstickers/") { iconText = NSAttributedString(string: "S", font: iconFont, textColor: UIColor.white) } else if url.path.hasPrefix("/addemoji/") { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift index dd77464a69..8bacb1df10 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift @@ -394,79 +394,47 @@ func _internal_searchEmoji(account: Account, query: [String], scope: SearchStick if query == ["\u{2764}"] { query = ["\u{2764}\u{FE0F}"] } - + let combinedQuery = query.sorted().joined(separator: "") + let querySet = Set(query) return account.postbox.transaction { transaction -> ([FoundStickerItem], CachedStickerQueryResult?, Bool, SearchStickersConfiguration) in let isPremium = transaction.getPeer(account.peerId)?.isPremium ?? false var result: [FoundStickerItem] = [] if scope.contains(.installed) { - var currentItems = Set(result.map { $0.file.fileId }) - var recentItems: [TelegramMediaFile] = [] - var recentAnimatedItems: [TelegramMediaFile] = [] - var recentItemsIds = Set() - var matchingRecentItemsIds = Set() - - for entry in transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.LocalRecentEmoji) { - if let item = entry.contents.get(RecentEmojiItem.self), case let .file(file) = item.content { - if !currentItems.contains(file.fileId) { - currentItems.insert(file.fileId) - - for case let .Sticker(displayText, _, _) in file.attributes { - for queryItem in query { - if displayText.hasPrefix(queryItem) { - matchingRecentItemsIds.insert(file.fileId) - break - } - } - recentItemsIds.insert(file.fileId) - if file.isAnimatedSticker || file.isVideoSticker { - recentAnimatedItems.append(file) - } else { - recentItems.append(file) - } - break - } - } - } - } - - var searchQueries: [ItemCollectionSearchQuery] = query.map { queryItem -> ItemCollectionSearchQuery in - return .exact(ValueBoxKey(queryItem)) - } - if query == ["\u{2764}"] { - searchQueries = [.any([ValueBoxKey("\u{2764}"), ValueBoxKey("\u{2764}\u{FE0F}")])] - } - + var currentItems = Set() var installedItems: [FoundStickerItem] = [] - for searchQuery in searchQueries { - for item in transaction.searchItemCollection(namespace: Namespaces.ItemCollection.CloudEmojiPacks, query: searchQuery) { - if let item = item as? StickerPackItem { - if !currentItems.contains(item.file.fileId) { - currentItems.insert(item.file.fileId) - - var stringRepresentations: [String] = [] - for key in item.indexKeys { - key.withDataNoCopy { data in - if let string = String(data: data, encoding: .utf8) { - stringRepresentations.append(string) + for info in transaction.getItemCollectionsInfos(namespace: Namespaces.ItemCollection.CloudEmojiPacks) { + if let info = info.1 as? StickerPackCollectionInfo { + let items = transaction.getItemCollectionItems(collectionId: info.id) + for item in items { + if let item = item as? StickerPackItem { + let file = item.file + if !currentItems.contains(file.fileId) { + currentItems.insert(file.fileId) + + var stringRepresentations: [String] = [] + for key in item.indexKeys { + key.withDataNoCopy { data in + if let string = String(data: data, encoding: .utf8) { + stringRepresentations.append(string) + } + } + } + for stringRepresentation in stringRepresentations { + if querySet.contains(stringRepresentation) { + installedItems.append(FoundStickerItem(file: file, stringRepresentations: stringRepresentations)) + break } } } - if !recentItemsIds.contains(item.file.fileId) { - installedItems.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations)) - } else { - matchingRecentItemsIds.insert(item.file.fileId) - } } } } } - result.append(contentsOf: installedItems) } - - let combinedQuery = query.joined(separator: "") + var cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedEmojiQueryResults, key: CachedStickerQueryResult.cacheKey(combinedQuery)))?.get(CachedStickerQueryResult.self) let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) @@ -476,10 +444,6 @@ func _internal_searchEmoji(account: Account, query: [String], scope: SearchStick if let currentCached = cached, currentTime > currentCached.timestamp + searchStickersConfiguration.cacheTimeout { cached = nil } - #if DEBUG - cached = nil - #endif - return (result, cached, isPremium, searchStickersConfiguration) } |> mapToSignal { localItems, cached, isPremium, searchStickersConfiguration -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> in @@ -487,29 +451,15 @@ func _internal_searchEmoji(account: Account, query: [String], scope: SearchStick return .single((localItems, true)) } - var tempResult: [FoundStickerItem] = [] - let currentItemIds = Set(localItems.map { $0.file.fileId }) - - var otherItems: [FoundStickerItem] = [] - - for item in localItems { - otherItems.append(item) - } - + var intermediateResult: [FoundStickerItem] = localItems + var currentItemIds = Set(localItems.map { $0.file.fileId }) if let cached = cached { - var cachedItems: [FoundStickerItem] = [] - for file in cached.items { if !currentItemIds.contains(file.fileId) { - cachedItems.append(FoundStickerItem(file: file, stringRepresentations: [])) + currentItemIds.insert(file.fileId) + intermediateResult.append(FoundStickerItem(file: file, stringRepresentations: [])) } } - - otherItems.append(contentsOf: cachedItems) - - let allOtherItems = otherItems - - tempResult.append(contentsOf: allOtherItems) } let remote = account.network.request(Api.functions.messages.searchCustomEmoji(emoticon: query.joined(separator: ""), hash: cached?.hash ?? 0)) @@ -536,39 +486,29 @@ func _internal_searchEmoji(account: Account, query: [String], scope: SearchStick |> mapToSignal { result -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> in return account.postbox.transaction { transaction -> (items: [FoundStickerItem], isFinalResult: Bool) in if let (fileItems, hash) = result { - var result: [FoundStickerItem] = [] + var result: [FoundStickerItem] = localItems var currentItemIds = Set(localItems.map { $0.file.fileId }) - - var otherItems: [FoundStickerItem] = [] - - for item in localItems { - otherItems.append(item) - } - + var files: [TelegramMediaFile] = [] for file in fileItems { files.append(file) if !currentItemIds.contains(file.fileId) { currentItemIds.insert(file.fileId) - otherItems.append(FoundStickerItem(file: file, stringRepresentations: [])) + result.append(FoundStickerItem(file: file, stringRepresentations: [])) } } - let allOtherItems = otherItems - - result.append(contentsOf: allOtherItems) - let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) if let entry = CodableEntry(CachedStickerQueryResult(items: files, hash: hash, timestamp: currentTime)) { - transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedEmojiQueryResults, key: CachedStickerQueryResult.cacheKey(query.joined(separator: ""))), entry: entry) + transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedEmojiQueryResults, key: CachedStickerQueryResult.cacheKey(combinedQuery)), entry: entry) } return (result, true) } - return (tempResult, true) + return (intermediateResult, true) } } - return .single((tempResult, false)) + return .single((intermediateResult, false)) |> then(remote) } } diff --git a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift index ea507f66bf..25b189dc89 100644 --- a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift @@ -1031,64 +1031,44 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { let resultSignal = signal |> mapToSignal { keywords -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in + var allEmoticons: [String: String] = [:] + for keyword in keywords { + for emoticon in keyword.emoticons { + allEmoticons[emoticon] = keyword.keyword + } + } + return combineLatest( - context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), - context.engine.stickers.availableReactions(), - hasPremium + hasPremium, + context.engine.stickers.searchEmoji(emojiString: Array(allEmoticons.keys)) ) - |> take(1) - |> map { view, availableReactions, hasPremium -> [EmojiPagerContentComponent.ItemGroup] in - var result: [(String, TelegramMediaFile?, String)] = [] - - var allEmoticons: [String: String] = [:] - for keyword in keywords { - for emoticon in keyword.emoticons { - allEmoticons[emoticon] = keyword.keyword - } + |> mapToSignal { hasPremium, foundEmoji -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in + if foundEmoji.items.isEmpty && !foundEmoji.isFinalResult { + return .complete() } - - for entry in view.entries { - guard let item = entry.item as? StickerPackItem else { - continue - } - for attribute in item.file.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - if !item.file.isPremiumEmoji || hasPremium { - if !alt.isEmpty, let keyword = allEmoticons[alt] { - result.append((alt, item.file, keyword)) - } else if alt == query { - result.append((alt, item.file, alt)) - } - } - default: - break - } - } - } - var items: [EmojiPagerContentComponent.Item] = [] var existingIds = Set() - for item in result { - if let itemFile = item.1 { - if existingIds.contains(itemFile.fileId) { - continue - } - existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) - let item = EmojiPagerContentComponent.Item( - animationData: animationData, - content: .animation(animationData), - itemFile: itemFile, subgroupId: nil, - icon: .none, - tintMode: animationData.isTemplate ? .primary : .none - ) - items.append(item) + for itemFile in foundEmoji.items { + if existingIds.contains(itemFile.fileId) { + continue } + existingIds.insert(itemFile.fileId) + if itemFile.isPremiumEmoji && !hasPremium { + continue + } + let animationData = EntityKeyboardAnimationData(file: itemFile) + let item = EmojiPagerContentComponent.Item( + animationData: animationData, + content: .animation(animationData), + itemFile: itemFile, subgroupId: nil, + icon: .none, + tintMode: animationData.isTemplate ? .primary : .none + ) + items.append(item) } - - return [EmojiPagerContentComponent.ItemGroup( + + return .single([EmojiPagerContentComponent.ItemGroup( supergroupId: "search", groupId: "search", title: nil, @@ -1103,7 +1083,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { headerItem: nil, fillWithLoadingPlaceholders: false, items: items - )] + )]) } } @@ -1171,7 +1151,6 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { return } if group.items.isEmpty && !result.isFinalResult { - //self.emojiSearchStateValue.isSearching = true self.emojiSearchStateValue = EmojiSearchState(result: EmojiSearchResult(groups: [ EmojiPagerContentComponent.ItemGroup( supergroupId: "search", @@ -1192,10 +1171,8 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { ], id: AnyHashable(value), version: version, isPreset: true), isSearching: false) return } - //DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0, execute: { - self.emojiSearchStateValue = EmojiSearchState(result: EmojiSearchResult(groups: result.items, id: AnyHashable(value), version: version, isPreset: true), isSearching: false) - version += 1 - //}) + self.emojiSearchStateValue = EmojiSearchState(result: EmojiSearchResult(groups: result.items, id: AnyHashable(value), version: version, isPreset: true), isSearching: false) + version += 1 })) } },