Add emoji search result cache

This commit is contained in:
Ali
2023-01-27 14:06:44 +01:00
parent 50ac94a2fe
commit b3140ffed9
14 changed files with 577 additions and 357 deletions

View File

@@ -234,6 +234,23 @@ public final class EmojiStatusSelectionComponent: Component {
public final class EmojiStatusSelectionController: ViewController {
private final class Node: ViewControllerTracingNode {
private struct EmojiSearchResult {
var groups: [EmojiPagerContentComponent.ItemGroup]
var id: AnyHashable
var version: Int
var isPreset: Bool
}
private struct EmojiSearchState {
var result: EmojiSearchResult?
var isSearching: Bool
init(result: EmojiSearchResult?, isSearching: Bool) {
self.result = result
self.isSearching = isSearching
}
}
private weak var controller: EmojiStatusSelectionController?
private let context: AccountContext
private weak var sourceView: UIView?
@@ -258,7 +275,9 @@ public final class EmojiStatusSelectionController: ViewController {
private var scheduledEmojiContentAnimationHint: EmojiPagerContentComponent.ContentAnimation?
private let emojiSearchDisposable = MetaDisposable()
private let emojiSearchResult = Promise<(groups: [EmojiPagerContentComponent.ItemGroup], id: AnyHashable)?>(nil)
private let emojiSearchState = Promise<EmojiSearchState>(EmojiSearchState(result: nil, isSearching: false))
private var emojiSearchStateValue: EmojiSearchState = EmojiSearchState(result: nil, isSearching: false)
private var emptyResultEmojis: [TelegramMediaFile] = []
private var stableEmptyResultEmoji: TelegramMediaFile?
private let stableEmptyResultEmojiDisposable = MetaDisposable()
@@ -349,16 +368,16 @@ public final class EmojiStatusSelectionController: ViewController {
self.emojiContentDisposable = (combineLatest(queue: .mainQueue(),
emojiContent,
self.emojiSearchResult.get()
self.emojiSearchState.get()
)
|> deliverOnMainQueue).start(next: { [weak self] emojiContent, emojiSearchResult in
|> deliverOnMainQueue).start(next: { [weak self] emojiContent, emojiSearchState in
guard let strongSelf = self else {
return
}
strongSelf.controller?._ready.set(.single(true))
var emojiContent = emojiContent
if let emojiSearchResult = emojiSearchResult {
if let emojiSearchResult = emojiSearchState.result {
var emptySearchResults: EmojiPagerContentComponent.EmptySearchResults?
if !emojiSearchResult.groups.contains(where: { !$0.items.isEmpty }) {
if strongSelf.stableEmptyResultEmoji == nil {
@@ -371,7 +390,7 @@ public final class EmojiStatusSelectionController: ViewController {
} else {
strongSelf.stableEmptyResultEmoji = nil
}
emojiContent = emojiContent.withUpdatedItemGroups(panelItemGroups: emojiContent.panelItemGroups, contentItemGroups: emojiSearchResult.groups, itemContentUniqueId: EmojiPagerContentComponent.ContentId(id: emojiSearchResult.id, version: 0), emptySearchResults: emptySearchResults, searchState: .active)
emojiContent = emojiContent.withUpdatedItemGroups(panelItemGroups: emojiContent.panelItemGroups, contentItemGroups: emojiSearchResult.groups, itemContentUniqueId: EmojiPagerContentComponent.ContentId(id: emojiSearchResult.id, version: emojiSearchResult.version), emptySearchResults: emptySearchResults, searchState: emojiSearchState.isSearching ? .searching : .active)
} else {
strongSelf.stableEmptyResultEmoji = nil
}
@@ -433,22 +452,22 @@ public final class EmojiStatusSelectionController: ViewController {
requestUpdate: { _ in
},
updateSearchQuery: { query in
guard let strongSelf = self else {
guard let self = self else {
return
}
switch query {
case .none:
strongSelf.emojiSearchDisposable.set(nil)
strongSelf.emojiSearchResult.set(.single(nil))
self.emojiSearchDisposable.set(nil)
self.emojiSearchState.set(.single(EmojiSearchState(result: nil, isSearching: false)))
case let .text(rawQuery, languageCode):
let query = rawQuery.trimmingCharacters(in: .whitespacesAndNewlines)
if query.isEmpty {
strongSelf.emojiSearchDisposable.set(nil)
strongSelf.emojiSearchResult.set(.single(nil))
self.emojiSearchDisposable.set(nil)
self.emojiSearchState.set(.single(EmojiSearchState(result: nil, isSearching: false)))
} else {
let context = strongSelf.context
let context = self.context
var signal = context.engine.stickers.searchEmojiKeywords(inputLanguageCode: languageCode, query: query, completeMatch: false)
if !languageCode.lowercased().hasPrefix("en") {
@@ -550,18 +569,22 @@ public final class EmojiStatusSelectionController: ViewController {
}
}
strongSelf.emojiSearchDisposable.set((resultSignal
var version = 0
self.emojiSearchStateValue.isSearching = true
self.emojiSearchDisposable.set((resultSignal
|> delay(0.15, queue: .mainQueue())
|> deliverOnMainQueue).start(next: { result in
guard let strongSelf = self else {
|> deliverOnMainQueue).start(next: { [weak self] result in
guard let self else {
return
}
strongSelf.emojiSearchResult.set(.single((result, AnyHashable(query))))
self.emojiSearchStateValue = EmojiSearchState(result: EmojiSearchResult(groups: result, id: AnyHashable(query), version: version, isPreset: false), isSearching: false)
version += 1
}))
}
case let .category(value):
let resultSignal = strongSelf.context.engine.stickers.searchEmoji(emojiString: value)
|> mapToSignal { files -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in
let resultSignal = self.context.engine.stickers.searchEmoji(emojiString: value)
|> mapToSignal { files, isFinalResult -> Signal<(items: [EmojiPagerContentComponent.ItemGroup], isFinalResult: Bool), NoError> in
var items: [EmojiPagerContentComponent.Item] = []
var existingIds = Set<MediaId>()
@@ -581,7 +604,7 @@ public final class EmojiStatusSelectionController: ViewController {
items.append(item)
}
return .single([EmojiPagerContentComponent.ItemGroup(
return .single(([EmojiPagerContentComponent.ItemGroup(
supergroupId: "search",
groupId: "search",
title: nil,
@@ -595,16 +618,26 @@ public final class EmojiStatusSelectionController: ViewController {
displayPremiumBadges: false,
headerItem: nil,
items: items
)])
)], isFinalResult))
}
strongSelf.emojiSearchDisposable.set((resultSignal
|> delay(0.15, queue: .mainQueue())
|> deliverOnMainQueue).start(next: { result in
guard let strongSelf = self else {
var version = 0
self.emojiSearchDisposable.set((resultSignal
|> deliverOnMainQueue).start(next: { [weak self] result in
guard let self else {
return
}
strongSelf.emojiSearchResult.set(.single((result, AnyHashable(value))))
guard let group = result.items.first else {
return
}
if group.items.isEmpty && !result.isFinalResult {
self.emojiSearchStateValue.isSearching = true
return
}
self.emojiSearchStateValue = EmojiSearchState(result: EmojiSearchResult(groups: result.items, id: AnyHashable(value), version: version, isPreset: true), isSearching: false)
version += 1
}))
}
},