Search by sticker pack name

This commit is contained in:
Ali 2023-11-07 17:58:50 +04:00
parent 4f23fa6e09
commit dcfc993fa4
6 changed files with 208 additions and 13 deletions

View file

@ -1502,15 +1502,21 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
}
|> distinctUntilChanged
let remotePacksSignal: Signal<(sets: FoundStickerSets, isFinalResult: Bool), NoError> = .single((FoundStickerSets(), false)) |> then(
context.engine.stickers.searchEmojiSetsRemotely(query: query) |> map {
($0, true)
}
)
let resultSignal = signal
|> 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
context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000) |> take(1),
context.engine.stickers.availableReactions() |> take(1),
hasPremium |> take(1),
remotePacksSignal
)
|> take(1)
|> map { view, availableReactions, hasPremium -> [EmojiPagerContentComponent.ItemGroup] in
|> map { view, availableReactions, hasPremium, foundPacks -> [EmojiPagerContentComponent.ItemGroup] in
var result: [(String, TelegramMediaFile?, String)] = []
var allEmoticons: [String: String] = [:]
@ -1561,7 +1567,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
}
}
return [EmojiPagerContentComponent.ItemGroup(
var resultGroups: [EmojiPagerContentComponent.ItemGroup] = []
resultGroups.append(EmojiPagerContentComponent.ItemGroup(
supergroupId: "search",
groupId: "search",
title: nil,
@ -1576,7 +1583,59 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
headerItem: nil,
fillWithLoadingPlaceholders: false,
items: items
)]
))
for (collectionId, info, _, _) in foundPacks.sets.infos {
if let info = info as? StickerPackCollectionInfo {
var topItems: [StickerPackItem] = []
for e in foundPacks.sets.entries {
if let item = e.item as? StickerPackItem {
if e.index.collectionId == collectionId {
topItems.append(item)
}
}
}
var groupItems: [EmojiPagerContentComponent.Item] = []
for item in topItems {
var tintMode: EmojiPagerContentComponent.Item.TintMode = .none
if item.file.isCustomTemplateEmoji {
tintMode = .primary
}
let animationData = EntityKeyboardAnimationData(file: item.file)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: item.file,
subgroupId: nil,
icon: .none,
tintMode: tintMode
)
groupItems.append(resultItem)
}
resultGroups.append(EmojiPagerContentComponent.ItemGroup(
supergroupId: AnyHashable(info.id),
groupId: AnyHashable(info.id),
title: info.title,
subtitle: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
isEmbedded: false,
hasClear: false,
collapsedLineCount: 3,
displayPremiumBadges: false,
headerItem: nil,
fillWithLoadingPlaceholders: false,
items: groupItems
))
}
}
return resultGroups
}
}

View file

@ -6613,6 +6613,23 @@ public extension Api.functions.messages {
})
}
}
public extension Api.functions.messages {
static func searchEmojiStickerSets(flags: Int32, q: String, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.FoundStickerSets>) {
let buffer = Buffer()
buffer.appendInt32(-1833678516)
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(q, buffer: buffer, boxed: false)
serializeInt64(hash, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.searchEmojiStickerSets", parameters: [("flags", String(describing: flags)), ("q", String(describing: q)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FoundStickerSets? in
let reader = BufferReader(buffer)
var result: Api.messages.FoundStickerSets?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.messages.FoundStickerSets
}
return result
})
}
}
public extension Api.functions.messages {
static func searchGlobal(flags: Int32, folderId: Int32?, q: String, filter: Api.MessagesFilter, minDate: Int32, maxDate: Int32, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Messages>) {
let buffer = Buffer()

View file

@ -558,6 +558,54 @@ func _internal_searchStickerSetsRemotely(network: Network, query: String) -> Sig
}
}
func _internal_searchEmojiSetsRemotely(postbox: Postbox, network: Network, query: String) -> Signal<FoundStickerSets, NoError> {
return network.request(Api.functions.messages.searchEmojiStickerSets(flags: 0, q: query, hash: 0))
|> mapError {_ in}
|> mapToSignal { value in
var index: Int32 = 1000
switch value {
case let .foundStickerSets(_, sets: sets):
var result = FoundStickerSets()
for set in sets {
let parsed = parsePreviewStickerSet(set, namespace: Namespaces.ItemCollection.CloudEmojiPacks)
let values = parsed.1.map({ ItemCollectionViewEntry(index: ItemCollectionViewEntryIndex(collectionIndex: index, collectionId: parsed.0.id, itemIndex: $0.index), item: $0) })
result = result.withUpdatedInfosAndEntries(infos: [(parsed.0.id, parsed.0, parsed.1.first, false)], entries: values)
index += 1
}
return .single(result)
default:
break
}
return .complete()
}
|> `catch` { _ -> Signal<FoundStickerSets, NoError> in
return .single(FoundStickerSets())
}
|> mapToSignal { result -> Signal<FoundStickerSets, NoError> in
return postbox.combinedView(keys: [PostboxViewKey.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudEmojiPacks])])
|> map { combinedView -> Set<ItemCollectionId> in
var installed = Set<ItemCollectionId>()
if let view = combinedView.views[PostboxViewKey.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudEmojiPacks])] as? ItemCollectionInfosView {
var installedIds = Set<ItemCollectionId>()
if let ids = view.entriesByNamespace[Namespaces.ItemCollection.CloudEmojiPacks] {
installedIds = Set(ids.map(\.id))
}
installed = installedIds.intersection(Set(result.infos.map(\.0)))
}
return installed
}
|> distinctUntilChanged
|> map { installed -> FoundStickerSets in
return FoundStickerSets(infos: result.infos.map { info in
return (info.0, info.1, info.2, installed.contains(info.0))
}, entries: result.entries)
}
}
}
func _internal_searchStickerSets(postbox: Postbox, query: String) -> Signal<FoundStickerSets, NoError> {
return postbox.transaction { transaction -> Signal<FoundStickerSets, NoError> in
let infos = transaction.getItemCollectionsInfos(namespace: Namespaces.ItemCollection.CloudStickerPacks)

View file

@ -37,6 +37,10 @@ public extension TelegramEngine {
public func searchStickerSetsRemotely(query: String) -> Signal<FoundStickerSets, NoError> {
return _internal_searchStickerSetsRemotely(network: self.account.network, query: query)
}
public func searchEmojiSetsRemotely(query: String) -> Signal<FoundStickerSets, NoError> {
return _internal_searchEmojiSetsRemotely(postbox: self.account.postbox, network: self.account.network, query: query)
}
public func searchStickerSets(query: String) -> Signal<FoundStickerSets, NoError> {
return _internal_searchStickerSets(postbox: self.account.postbox, query: query)

View file

@ -882,13 +882,18 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
}
}
let remoteSignal: Signal<(items: [TelegramMediaFile], isFinalResult: Bool), NoError>
let remotePacksSignal: Signal<(sets: FoundStickerSets, isFinalResult: Bool), NoError>
if hasPremium {
remoteSignal = context.engine.stickers.searchEmoji(emojiString: Array(allEmoticons.keys))
remotePacksSignal = .single((FoundStickerSets(), false)) |> then(context.engine.stickers.searchEmojiSetsRemotely(query: query) |> map {
($0, true)
})
} else {
remoteSignal = .single(([], true))
remotePacksSignal = .single((FoundStickerSets(), true))
}
return remoteSignal
|> mapToSignal { foundEmoji -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in
return combineLatest(remoteSignal, remotePacksSignal)
|> mapToSignal { foundEmoji, foundPacks -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in
if foundEmoji.items.isEmpty && !foundEmoji.isFinalResult {
return .complete()
}
@ -940,8 +945,9 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
if hasPremium {
appendUnicodeEmoji()
}
return .single([EmojiPagerContentComponent.ItemGroup(
var resultGroups: [EmojiPagerContentComponent.ItemGroup] = []
resultGroups.append(EmojiPagerContentComponent.ItemGroup(
supergroupId: "search",
groupId: "search",
title: nil,
@ -956,7 +962,59 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
headerItem: nil,
fillWithLoadingPlaceholders: false,
items: items
)])
))
for (collectionId, info, _, _) in foundPacks.sets.infos {
if let info = info as? StickerPackCollectionInfo {
var topItems: [StickerPackItem] = []
for e in foundPacks.sets.entries {
if let item = e.item as? StickerPackItem {
if e.index.collectionId == collectionId {
topItems.append(item)
}
}
}
var groupItems: [EmojiPagerContentComponent.Item] = []
for item in topItems {
var tintMode: EmojiPagerContentComponent.Item.TintMode = .none
if item.file.isCustomTemplateEmoji {
tintMode = .primary
}
let animationData = EntityKeyboardAnimationData(file: item.file)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: item.file,
subgroupId: nil,
icon: .none,
tintMode: tintMode
)
groupItems.append(resultItem)
}
resultGroups.append(EmojiPagerContentComponent.ItemGroup(
supergroupId: AnyHashable(info.id),
groupId: AnyHashable(info.id),
title: info.title,
subtitle: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
isEmbedded: false,
hasClear: false,
collapsedLineCount: 3,
displayPremiumBadges: false,
headerItem: nil,
fillWithLoadingPlaceholders: false,
items: groupItems
))
}
}
return .single(resultGroups)
}
}

View file

@ -410,7 +410,16 @@ final class PeerAllowedReactionsScreenComponent: Component {
if nextCustomReactionCount > boostStatus.level {
//TODO:localize
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
self.environment?.controller()?.present(UndoOverlayController(presentationData: presentationData, content: .sticker(context: component.context, file: itemFile, loop: false, title: nil, text: "Your channel needs to reach **Level \(nextCustomReactionCount)** to add **\(nextCustomReactionCount) custom emoji as reactions.**", undoText: nil, customAction: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current)
var animateAsReplacement = false
if let currentUndoController = self.currentUndoController {
currentUndoController.dismiss()
animateAsReplacement = true
}
let undoController = UndoOverlayController(presentationData: presentationData, content: .sticker(context: component.context, file: itemFile, loop: false, title: nil, text: "Your channel needs to reach **Level \(nextCustomReactionCount)** to add **\(nextCustomReactionCount) custom emoji as reactions.**", undoText: nil, customAction: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: animateAsReplacement, action: { _ in return false })
self.currentUndoController = undoController
self.environment?.controller()?.present(undoController, in: .current)
}
}
}