mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-17 20:00:38 +00:00
Improve emoji search
This commit is contained in:
parent
2f0114f69e
commit
688b88a37e
@ -471,7 +471,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode {
|
|||||||
let host: String? = concealed ? urlString : parsedUrl?.host
|
let host: String? = concealed ? urlString : parsedUrl?.host
|
||||||
if let url = parsedUrl, let host = host {
|
if let url = parsedUrl, let host = host {
|
||||||
primaryUrl = urlString
|
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/") {
|
if url.path.hasPrefix("/addstickers/") {
|
||||||
iconText = NSAttributedString(string: "S", font: iconFont, textColor: UIColor.white)
|
iconText = NSAttributedString(string: "S", font: iconFont, textColor: UIColor.white)
|
||||||
} else if url.path.hasPrefix("/addemoji/") {
|
} else if url.path.hasPrefix("/addemoji/") {
|
||||||
|
|||||||
@ -394,56 +394,24 @@ func _internal_searchEmoji(account: Account, query: [String], scope: SearchStick
|
|||||||
if query == ["\u{2764}"] {
|
if query == ["\u{2764}"] {
|
||||||
query = ["\u{2764}\u{FE0F}"]
|
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
|
return account.postbox.transaction { transaction -> ([FoundStickerItem], CachedStickerQueryResult?, Bool, SearchStickersConfiguration) in
|
||||||
let isPremium = transaction.getPeer(account.peerId)?.isPremium ?? false
|
let isPremium = transaction.getPeer(account.peerId)?.isPremium ?? false
|
||||||
|
|
||||||
var result: [FoundStickerItem] = []
|
var result: [FoundStickerItem] = []
|
||||||
if scope.contains(.installed) {
|
if scope.contains(.installed) {
|
||||||
var currentItems = Set<MediaId>(result.map { $0.file.fileId })
|
var currentItems = Set<MediaId>()
|
||||||
var recentItems: [TelegramMediaFile] = []
|
|
||||||
var recentAnimatedItems: [TelegramMediaFile] = []
|
|
||||||
var recentItemsIds = Set<MediaId>()
|
|
||||||
var matchingRecentItemsIds = Set<MediaId>()
|
|
||||||
|
|
||||||
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 installedItems: [FoundStickerItem] = []
|
var installedItems: [FoundStickerItem] = []
|
||||||
|
|
||||||
for searchQuery in searchQueries {
|
for info in transaction.getItemCollectionsInfos(namespace: Namespaces.ItemCollection.CloudEmojiPacks) {
|
||||||
for item in transaction.searchItemCollection(namespace: Namespaces.ItemCollection.CloudEmojiPacks, query: searchQuery) {
|
if let info = info.1 as? StickerPackCollectionInfo {
|
||||||
|
let items = transaction.getItemCollectionItems(collectionId: info.id)
|
||||||
|
for item in items {
|
||||||
if let item = item as? StickerPackItem {
|
if let item = item as? StickerPackItem {
|
||||||
if !currentItems.contains(item.file.fileId) {
|
let file = item.file
|
||||||
currentItems.insert(item.file.fileId)
|
if !currentItems.contains(file.fileId) {
|
||||||
|
currentItems.insert(file.fileId)
|
||||||
|
|
||||||
var stringRepresentations: [String] = []
|
var stringRepresentations: [String] = []
|
||||||
for key in item.indexKeys {
|
for key in item.indexKeys {
|
||||||
@ -453,20 +421,20 @@ func _internal_searchEmoji(account: Account, query: [String], scope: SearchStick
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !recentItemsIds.contains(item.file.fileId) {
|
for stringRepresentation in stringRepresentations {
|
||||||
installedItems.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations))
|
if querySet.contains(stringRepresentation) {
|
||||||
} else {
|
installedItems.append(FoundStickerItem(file: file, stringRepresentations: stringRepresentations))
|
||||||
matchingRecentItemsIds.insert(item.file.fileId)
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.append(contentsOf: installedItems)
|
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)
|
var cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedEmojiQueryResults, key: CachedStickerQueryResult.cacheKey(combinedQuery)))?.get(CachedStickerQueryResult.self)
|
||||||
|
|
||||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
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 {
|
if let currentCached = cached, currentTime > currentCached.timestamp + searchStickersConfiguration.cacheTimeout {
|
||||||
cached = nil
|
cached = nil
|
||||||
}
|
}
|
||||||
#if DEBUG
|
|
||||||
cached = nil
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (result, cached, isPremium, searchStickersConfiguration)
|
return (result, cached, isPremium, searchStickersConfiguration)
|
||||||
}
|
}
|
||||||
|> mapToSignal { localItems, cached, isPremium, searchStickersConfiguration -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> in
|
|> 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))
|
return .single((localItems, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempResult: [FoundStickerItem] = []
|
var intermediateResult: [FoundStickerItem] = localItems
|
||||||
let currentItemIds = Set<MediaId>(localItems.map { $0.file.fileId })
|
var currentItemIds = Set<MediaId>(localItems.map { $0.file.fileId })
|
||||||
|
|
||||||
var otherItems: [FoundStickerItem] = []
|
|
||||||
|
|
||||||
for item in localItems {
|
|
||||||
otherItems.append(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let cached = cached {
|
if let cached = cached {
|
||||||
var cachedItems: [FoundStickerItem] = []
|
|
||||||
|
|
||||||
for file in cached.items {
|
for file in cached.items {
|
||||||
if !currentItemIds.contains(file.fileId) {
|
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))
|
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
|
|> mapToSignal { result -> Signal<(items: [FoundStickerItem], isFinalResult: Bool), NoError> in
|
||||||
return account.postbox.transaction { transaction -> (items: [FoundStickerItem], isFinalResult: Bool) in
|
return account.postbox.transaction { transaction -> (items: [FoundStickerItem], isFinalResult: Bool) in
|
||||||
if let (fileItems, hash) = result {
|
if let (fileItems, hash) = result {
|
||||||
var result: [FoundStickerItem] = []
|
var result: [FoundStickerItem] = localItems
|
||||||
var currentItemIds = Set<MediaId>(localItems.map { $0.file.fileId })
|
var currentItemIds = Set<MediaId>(localItems.map { $0.file.fileId })
|
||||||
|
|
||||||
var otherItems: [FoundStickerItem] = []
|
|
||||||
|
|
||||||
for item in localItems {
|
|
||||||
otherItems.append(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
var files: [TelegramMediaFile] = []
|
var files: [TelegramMediaFile] = []
|
||||||
for file in fileItems {
|
for file in fileItems {
|
||||||
files.append(file)
|
files.append(file)
|
||||||
if !currentItemIds.contains(file.fileId) {
|
if !currentItemIds.contains(file.fileId) {
|
||||||
currentItemIds.insert(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)
|
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||||
if let entry = CodableEntry(CachedStickerQueryResult(items: files, hash: hash, timestamp: currentTime)) {
|
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 (result, true)
|
||||||
}
|
}
|
||||||
return (tempResult, true)
|
return (intermediateResult, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return .single((tempResult, false))
|
return .single((intermediateResult, false))
|
||||||
|> then(remote)
|
|> then(remote)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1031,15 +1031,6 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
|
|
||||||
let resultSignal = signal
|
let resultSignal = signal
|
||||||
|> mapToSignal { keywords -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in
|
|> mapToSignal { keywords -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in
|
||||||
return combineLatest(
|
|
||||||
context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000),
|
|
||||||
context.engine.stickers.availableReactions(),
|
|
||||||
hasPremium
|
|
||||||
)
|
|
||||||
|> take(1)
|
|
||||||
|> map { view, availableReactions, hasPremium -> [EmojiPagerContentComponent.ItemGroup] in
|
|
||||||
var result: [(String, TelegramMediaFile?, String)] = []
|
|
||||||
|
|
||||||
var allEmoticons: [String: String] = [:]
|
var allEmoticons: [String: String] = [:]
|
||||||
for keyword in keywords {
|
for keyword in keywords {
|
||||||
for emoticon in keyword.emoticons {
|
for emoticon in keyword.emoticons {
|
||||||
@ -1047,35 +1038,25 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for entry in view.entries {
|
return combineLatest(
|
||||||
guard let item = entry.item as? StickerPackItem else {
|
hasPremium,
|
||||||
continue
|
context.engine.stickers.searchEmoji(emojiString: Array(allEmoticons.keys))
|
||||||
|
)
|
||||||
|
|> mapToSignal { hasPremium, foundEmoji -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in
|
||||||
|
if foundEmoji.items.isEmpty && !foundEmoji.isFinalResult {
|
||||||
|
return .complete()
|
||||||
}
|
}
|
||||||
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 items: [EmojiPagerContentComponent.Item] = []
|
||||||
|
|
||||||
var existingIds = Set<MediaId>()
|
var existingIds = Set<MediaId>()
|
||||||
for item in result {
|
for itemFile in foundEmoji.items {
|
||||||
if let itemFile = item.1 {
|
|
||||||
if existingIds.contains(itemFile.fileId) {
|
if existingIds.contains(itemFile.fileId) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
existingIds.insert(itemFile.fileId)
|
existingIds.insert(itemFile.fileId)
|
||||||
|
if itemFile.isPremiumEmoji && !hasPremium {
|
||||||
|
continue
|
||||||
|
}
|
||||||
let animationData = EntityKeyboardAnimationData(file: itemFile)
|
let animationData = EntityKeyboardAnimationData(file: itemFile)
|
||||||
let item = EmojiPagerContentComponent.Item(
|
let item = EmojiPagerContentComponent.Item(
|
||||||
animationData: animationData,
|
animationData: animationData,
|
||||||
@ -1086,9 +1067,8 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
)
|
)
|
||||||
items.append(item)
|
items.append(item)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return [EmojiPagerContentComponent.ItemGroup(
|
return .single([EmojiPagerContentComponent.ItemGroup(
|
||||||
supergroupId: "search",
|
supergroupId: "search",
|
||||||
groupId: "search",
|
groupId: "search",
|
||||||
title: nil,
|
title: nil,
|
||||||
@ -1103,7 +1083,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
headerItem: nil,
|
headerItem: nil,
|
||||||
fillWithLoadingPlaceholders: false,
|
fillWithLoadingPlaceholders: false,
|
||||||
items: items
|
items: items
|
||||||
)]
|
)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1171,7 +1151,6 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if group.items.isEmpty && !result.isFinalResult {
|
if group.items.isEmpty && !result.isFinalResult {
|
||||||
//self.emojiSearchStateValue.isSearching = true
|
|
||||||
self.emojiSearchStateValue = EmojiSearchState(result: EmojiSearchResult(groups: [
|
self.emojiSearchStateValue = EmojiSearchState(result: EmojiSearchResult(groups: [
|
||||||
EmojiPagerContentComponent.ItemGroup(
|
EmojiPagerContentComponent.ItemGroup(
|
||||||
supergroupId: "search",
|
supergroupId: "search",
|
||||||
@ -1192,10 +1171,8 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
], id: AnyHashable(value), version: version, isPreset: true), isSearching: false)
|
], id: AnyHashable(value), version: version, isPreset: true), isSearching: false)
|
||||||
return
|
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)
|
self.emojiSearchStateValue = EmojiSearchState(result: EmojiSearchResult(groups: result.items, id: AnyHashable(value), version: version, isPreset: true), isSearching: false)
|
||||||
version += 1
|
version += 1
|
||||||
//})
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user