mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Search by sticker pack name
This commit is contained in:
parent
4f23fa6e09
commit
dcfc993fa4
6 changed files with 208 additions and 13 deletions
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue