Various optimizations

This commit is contained in:
Isaac 2025-03-04 14:13:07 +01:00
parent 1cd77c768b
commit faa765b601
38 changed files with 421 additions and 125 deletions

View File

@ -15,7 +15,7 @@ import ItemListStickerPackItem
private struct ArchivedStickersNoticeEntry: Comparable, Identifiable {
let index: Int
let info: StickerPackCollectionInfo
let info: StickerPackCollectionInfo.Accessor
let topItem: StickerPackItem?
let count: String
@ -135,7 +135,7 @@ private final class ArchivedStickersNoticeAlertContentNode: AlertContentNode {
} else {
countTitle = presentationData.strings.StickerPack_StickerCount(pack.0.count)
}
entries.append(ArchivedStickersNoticeEntry(index: index, info: pack.0, topItem: pack.1, count: countTitle))
entries.append(ArchivedStickersNoticeEntry(index: index, info: StickerPackCollectionInfo.Accessor(pack.0), topItem: pack.1, count: countTitle))
index += 1
}

View File

@ -30,7 +30,7 @@ public final class TrendingPaneInteraction {
public final class TrendingPanePackEntry: Identifiable, Comparable {
public let index: Int
public let info: StickerPackCollectionInfo
public let info: StickerPackCollectionInfo.Accessor
public let theme: PresentationTheme
public let strings: PresentationStrings
public let topItems: [StickerPackItem]
@ -38,7 +38,7 @@ public final class TrendingPanePackEntry: Identifiable, Comparable {
public let unread: Bool
public let topSeparator: Bool
public init(index: Int, info: StickerPackCollectionInfo, theme: PresentationTheme, strings: PresentationStrings, topItems: [StickerPackItem], installed: Bool, unread: Bool, topSeparator: Bool) {
public init(index: Int, info: StickerPackCollectionInfo.Accessor, theme: PresentationTheme, strings: PresentationStrings, topItems: [StickerPackItem], installed: Bool, unread: Bool, topSeparator: Bool) {
self.index = index
self.info = info
self.theme = theme
@ -88,9 +88,9 @@ public final class TrendingPanePackEntry: Identifiable, Comparable {
public func item(context: AccountContext, interaction: TrendingPaneInteraction, grid: Bool) -> GridItem {
let info = self.info
return StickerPaneSearchGlobalItem(context: context, theme: self.theme, strings: self.strings, listAppearance: false, info: self.info, topItems: self.topItems, topSeparator: self.topSeparator, regularInsets: false, installed: self.installed, unread: self.unread, open: {
interaction.openPack(info)
interaction.openPack(info._parse())
}, install: {
interaction.installPack(info)
interaction.installPack(info._parse())
}, getItemIsPreviewed: { item in
return interaction.getItemIsPreviewed(item)
}, itemContext: interaction.itemContext)
@ -272,16 +272,17 @@ public final class ChatMediaInputTrendingPane: ChatMediaInputPane {
if installed {
return .complete()
} else {
let parsedInfo = info._parse()
return preloadedStickerPackThumbnail(account: context.account, info: info, items: items)
|> filter { $0 }
|> ignoreValues
|> then(
context.engine.stickers.addStickerPackInteractively(info: info, items: items)
context.engine.stickers.addStickerPackInteractively(info: parsedInfo, items: items)
|> ignoreValues
)
|> mapToSignal { _ -> Signal<(StickerPackCollectionInfo, [StickerPackItem]), NoError> in
}
|> then(.single((info, items)))
|> then(.single((parsedInfo, items)))
}
case .fetching:
break

View File

@ -35,7 +35,7 @@ private final class FeaturedInteraction {
private final class FeaturedPackEntry: Identifiable, Comparable {
let index: Int
let info: StickerPackCollectionInfo
let info: StickerPackCollectionInfo.Accessor
let theme: PresentationTheme
let strings: PresentationStrings
let topItems: [StickerPackItem]
@ -44,7 +44,7 @@ private final class FeaturedPackEntry: Identifiable, Comparable {
let topSeparator: Bool
let regularInsets: Bool
init(index: Int, info: StickerPackCollectionInfo, theme: PresentationTheme, strings: PresentationStrings, topItems: [StickerPackItem], installed: Bool, unread: Bool, topSeparator: Bool, regularInsets: Bool = false) {
init(index: Int, info: StickerPackCollectionInfo.Accessor, theme: PresentationTheme, strings: PresentationStrings, topItems: [StickerPackItem], installed: Bool, unread: Bool, topSeparator: Bool, regularInsets: Bool = false) {
self.index = index
self.info = info
self.theme = theme
@ -98,9 +98,9 @@ private final class FeaturedPackEntry: Identifiable, Comparable {
func item(context: AccountContext, interaction: FeaturedInteraction, isOther: Bool) -> GridItem {
let info = self.info
return StickerPaneSearchGlobalItem(context: context, theme: self.theme, strings: self.strings, listAppearance: true, fillsRow: false, info: self.info, topItems: self.topItems, topSeparator: self.topSeparator, regularInsets: self.regularInsets, installed: self.installed, unread: self.unread, open: {
interaction.openPack(info)
interaction.openPack(info._parse())
}, install: {
interaction.installPack(info, !self.installed)
interaction.installPack(info._parse(), !self.installed)
}, getItemIsPreviewed: { item in
return interaction.getItemIsPreviewed(item)
}, itemContext: interaction.itemContext, sectionTitle: isOther ? self.strings.FeaturedStickers_OtherSection : nil)
@ -1041,7 +1041,7 @@ private enum FeaturedSearchEntryId: Equatable, Hashable {
private enum FeaturedSearchEntry: Identifiable, Comparable {
case sticker(index: Int, code: String?, stickerItem: FoundStickerItem, theme: PresentationTheme)
case global(index: Int, info: StickerPackCollectionInfo, topItems: [StickerPackItem], installed: Bool, topSeparator: Bool)
case global(index: Int, info: StickerPackCollectionInfo.Accessor, topItems: [StickerPackItem], installed: Bool, topSeparator: Bool)
var stableId: FeaturedSearchEntryId {
switch self {
@ -1108,9 +1108,9 @@ private enum FeaturedSearchEntry: Identifiable, Comparable {
})
case let .global(_, info, topItems, installed, topSeparator):
return StickerPaneSearchGlobalItem(context: context, theme: theme, strings: strings, listAppearance: true, fillsRow: true, info: info, topItems: topItems, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: {
interaction.open(info)
interaction.open(info._parse())
}, install: {
interaction.install(info, topItems, !installed)
interaction.install(info._parse(), topItems, !installed)
}, getItemIsPreviewed: { item in
return interaction.getItemIsPreviewed(item)
}, itemContext: itemContext)
@ -1436,7 +1436,7 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode {
}
}
}
entries.append(.global(index: index, info: info, topItems: topItems, installed: installed, topSeparator: !isFirstGlobal))
entries.append(.global(index: index, info: StickerPackCollectionInfo.Accessor(info), topItems: topItems, installed: installed, topSeparator: !isFirstGlobal))
isFirstGlobal = false
index += 1
}

View File

@ -84,7 +84,7 @@ public final class StickerPaneSearchGlobalItem: GridItem {
public let strings: PresentationStrings
public let listAppearance: Bool
public let fillsRow: Bool
public let info: StickerPackCollectionInfo
public let info: StickerPackCollectionInfo.Accessor
public let topItems: [StickerPackItem]
public let topSeparator: Bool
public let regularInsets: Bool
@ -111,7 +111,7 @@ public final class StickerPaneSearchGlobalItem: GridItem {
return (128.0 + additionalHeight, self.fillsRow)
}
public init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, listAppearance: Bool, fillsRow: Bool = true, info: StickerPackCollectionInfo, topItems: [StickerPackItem], topSeparator: Bool, regularInsets: Bool, installed: Bool, installing: Bool = false, unread: Bool, open: @escaping () -> Void, install: @escaping () -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, itemContext: StickerPaneSearchGlobalItemContext, sectionTitle: String? = nil) {
public init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, listAppearance: Bool, fillsRow: Bool = true, info: StickerPackCollectionInfo.Accessor, topItems: [StickerPackItem], topSeparator: Bool, regularInsets: Bool, installed: Bool, installing: Bool = false, unread: Bool, open: @escaping () -> Void, install: @escaping () -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, itemContext: StickerPaneSearchGlobalItemContext, sectionTitle: String? = nil) {
self.context = context
self.theme = theme
self.strings = strings

View File

@ -40,7 +40,7 @@ public enum ItemListStickerPackItemControl: Equatable {
public final class ItemListStickerPackItem: ListViewItem, ItemListItem {
let presentationData: ItemListPresentationData
let context: AccountContext
let packInfo: StickerPackCollectionInfo
let packInfo: StickerPackCollectionInfo.Accessor
let itemCount: String
let topItem: StickerPackItem?
let unread: Bool
@ -56,7 +56,7 @@ public final class ItemListStickerPackItem: ListViewItem, ItemListItem {
let removePack: () -> Void
let toggleSelected: () -> Void
public init(presentationData: ItemListPresentationData, context: AccountContext, packInfo: StickerPackCollectionInfo, itemCount: String, topItem: StickerPackItem?, unread: Bool, control: ItemListStickerPackItemControl, editing: ItemListStickerPackItemEditing, enabled: Bool, playAnimatedStickers: Bool, style: ItemListStyle = .blocks, sectionId: ItemListSectionId, action: (() -> Void)?, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, addPack: @escaping () -> Void, removePack: @escaping () -> Void, toggleSelected: @escaping () -> Void) {
public init(presentationData: ItemListPresentationData, context: AccountContext, packInfo: StickerPackCollectionInfo.Accessor, itemCount: String, topItem: StickerPackItem?, unread: Bool, control: ItemListStickerPackItemControl, editing: ItemListStickerPackItemEditing, enabled: Bool, playAnimatedStickers: Bool, style: ItemListStyle = .blocks, sectionId: ItemListSectionId, action: (() -> Void)?, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, addPack: @escaping () -> Void, removePack: @escaping () -> Void, toggleSelected: @escaping () -> Void) {
self.presentationData = presentationData
self.context = context
self.packInfo = packInfo
@ -487,7 +487,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
var thumbnailItem: StickerPackThumbnailItem?
var resourceReference: MediaResourceReference?
if let thumbnail = item.packInfo.thumbnail {
if item.packInfo.hasThumbnail, let thumbnail = item.packInfo._parse().thumbnail {
if thumbnail.typeHint != .generic {
thumbnailItem = .animated(thumbnail.resource, thumbnail.dimensions, thumbnail.typeHint == .video, item.packInfo.flags.contains(.isCustomTemplateEmoji))
} else {
@ -845,7 +845,12 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
var imageSize = PixelDimensions(width: 512, height: 512)
var immediateThumbnailData: Data?
if let data = item.packInfo.immediateThumbnailData {
if item.packInfo.thumbnail?.typeHint == .video || item.topItem?.file.isVideoSticker == true {
var isVideoTypeHint = false
if item.packInfo.hasThumbnail, let thumbnail = item.packInfo._parse().thumbnail {
isVideoTypeHint = thumbnail.typeHint == .video
}
if isVideoTypeHint || item.topItem?.file.isVideoSticker == true {
imageSize = PixelDimensions(width: 100, height: 100)
}
immediateThumbnailData = data

View File

@ -1741,7 +1741,7 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate {
if let strongSelf = self {
strongSelf.scheduledEmojiContentAnimationHint = EmojiPagerContentComponent.ContentAnimation(type: .groupInstalled(id: collectionId, scrollToGroup: true))
}
let _ = strongSelf.context.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info, items: featuredEmojiPack.topItems).start()
let _ = strongSelf.context.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info._parse(), items: featuredEmojiPack.topItems).start()
break
}

View File

@ -141,7 +141,7 @@ private enum ArchivedStickerPacksEntry: ItemListNodeEntry {
case let .info(_, text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .pack(_, _, _, info, topItem, count, animatedStickers, enabled, editing, selected):
return ItemListStickerPackItem(presentationData: presentationData, context: arguments.context, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: editing.editing ? .check(checked: selected ?? false) : .installation(installed: false), editing: editing, enabled: enabled, playAnimatedStickers: animatedStickers, sectionId: self.section, action: {
return ItemListStickerPackItem(presentationData: presentationData, context: arguments.context, packInfo: StickerPackCollectionInfo.Accessor(info), itemCount: count, topItem: topItem, unread: false, control: editing.editing ? .check(checked: selected ?? false) : .installation(installed: false), editing: editing, enabled: enabled, playAnimatedStickers: animatedStickers, sectionId: self.section, action: {
arguments.openStickerPack(info)
}, setPackIdWithRevealedOptions: { current, previous in
arguments.setPackIdWithRevealedOptions(current, previous)
@ -323,11 +323,12 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv
if installed {
return .complete()
} else {
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
let parsedInfo = info._parse()
return context.engine.stickers.addStickerPackInteractively(info: parsedInfo, items: items)
|> ignoreValues
|> mapToSignal { _ -> Signal<(StickerPackCollectionInfo, [StickerPackItem]), NoError> in
}
|> then(.single((info, items)))
|> then(.single((parsedInfo, items)))
}
case .fetching:
break
@ -489,11 +490,12 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv
if installed {
return .complete()
} else {
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
let parsedInfo = info._parse()
return context.engine.stickers.addStickerPackInteractively(info: parsedInfo, items: items)
|> ignoreValues
|> mapToSignal { _ -> Signal<(StickerPackCollectionInfo, [StickerPackItem]), NoError> in
}
|> then(.single((info, items)))
|> then(.single((parsedInfo, items)))
}
case .fetching:
break

View File

@ -34,7 +34,7 @@ private enum FeaturedStickerPacksEntryId: Hashable {
}
private enum FeaturedStickerPacksEntry: ItemListNodeEntry {
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, Bool, StickerPackItem?, String, Bool, Bool)
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo.Accessor, Bool, StickerPackItem?, String, Bool, Bool)
var section: ItemListSectionId {
switch self {
@ -103,10 +103,10 @@ private enum FeaturedStickerPacksEntry: ItemListNodeEntry {
switch self {
case let .pack(_, _, _, info, unread, topItem, count, playAnimatedStickers, installed):
return ItemListStickerPackItem(presentationData: presentationData, context: arguments.context, packInfo: info, itemCount: count, topItem: topItem, unread: unread, control: .installation(installed: installed), editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false, selectable: false), enabled: true, playAnimatedStickers: playAnimatedStickers, sectionId: self.section, action: {
arguments.openStickerPack(info)
arguments.openStickerPack(info._parse())
}, setPackIdWithRevealedOptions: { _, _ in
}, addPack: {
arguments.addPack(info)
arguments.addPack(info._parse())
}, removePack: {
}, toggleSelected: {
})
@ -178,7 +178,7 @@ public func featuredStickerPacksController(context: AccountContext) -> ViewContr
if installed {
return .complete()
} else {
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
return context.engine.stickers.addStickerPackInteractively(info: info._parse(), items: items)
}
case .fetching:
break

View File

@ -433,7 +433,7 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
case let .packsTitle(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .pack(_, _, _, info, topItem, count, animatedStickers, enabled, editing, selected):
return ItemListStickerPackItem(presentationData: presentationData, context: arguments.context, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: editing.editing ? .check(checked: selected ?? false) : .none, editing: editing, enabled: enabled, playAnimatedStickers: animatedStickers, sectionId: self.section, action: {
return ItemListStickerPackItem(presentationData: presentationData, context: arguments.context, packInfo: StickerPackCollectionInfo.Accessor(info), itemCount: count, topItem: topItem, unread: false, control: editing.editing ? .check(checked: selected ?? false) : .none, editing: editing, enabled: enabled, playAnimatedStickers: animatedStickers, sectionId: self.section, action: {
arguments.openStickerPack(info)
}, setPackIdWithRevealedOptions: { current, previous in
arguments.setPackIdWithRevealedOptions(current, previous)
@ -853,7 +853,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
if installed {
return .complete()
} else {
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
return context.engine.stickers.addStickerPackInteractively(info: info._parse(), items: items)
}
case .fetching:
break

View File

@ -196,6 +196,7 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
case let .result(info, items, _):
var preloadSignals: [Signal<Bool, NoError>] = []
let info = info._parse()
if let thumbnail = info.thumbnail {
let signal = Signal<Bool, NoError> { subscriber in
let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: .stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)).start()

View File

@ -539,11 +539,12 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, ASScrol
guard let strongSelf = self, let (positionInList, _) = indexAndItems else {
return
}
strongSelf.actionPerformed?(info, items, .remove(positionInList: positionInList))
strongSelf.actionPerformed?(info._parse(), items, .remove(positionInList: positionInList))
})
} else {
let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start()
self.actionPerformed?(info, items, .add)
let parsedInfo = info._parse()
let _ = self.context.engine.stickers.addStickerPackInteractively(info: parsedInfo, items: items).start()
self.actionPerformed?(parsedInfo, items, .add)
}
self.cancelButtonPressed()
default:

View File

@ -459,7 +459,7 @@ private final class StickerPackContainer: ASDisplayNode {
var contents: [LoadedStickerPack] = []
for (info, items, isInstalled) in strongSelf.currentStickerPacks {
contents.append(.result(info: info, items: items, installed: isInstalled))
contents.append(.result(info: StickerPackCollectionInfo.Accessor(info), items: items, installed: isInstalled))
}
strongSelf.updateStickerPackContents(contents, hasPremium: false)
@ -476,7 +476,7 @@ private final class StickerPackContainer: ASDisplayNode {
var contents: [LoadedStickerPack] = []
for (info, items, isInstalled) in strongSelf.currentStickerPacks {
contents.append(.result(info: info, items: items, installed: isInstalled))
contents.append(.result(info: StickerPackCollectionInfo.Accessor(info), items: items, installed: isInstalled))
}
strongSelf.updateStickerPackContents(contents, hasPremium: false)
@ -1534,7 +1534,7 @@ private final class StickerPackContainer: ASDisplayNode {
self.requestDismiss()
dismissed = true
case .navigatedNext, .ignored:
self.updateStickerPackContents([.result(info: info, items: items, installed: !installed)], hasPremium: false)
self.updateStickerPackContents([.result(info: StickerPackCollectionInfo.Accessor(info), items: items, installed: !installed)], hasPremium: false)
}
let actionPerformed = self.controller?.actionPerformed
@ -1707,11 +1707,11 @@ private final class StickerPackContainer: ASDisplayNode {
var installedCount = 0
for content in contents {
if case let .result(info, items, isInstalled) = content {
entries.append(.emojis(index: index, stableId: index, info: info, items: items, title: info.title, isInstalled: isInstalled))
entries.append(.emojis(index: index, stableId: index, info: info._parse(), items: items, title: info.title, isInstalled: isInstalled))
if isInstalled {
installedCount += 1
}
currentStickerPacks.append((info, items, isInstalled))
currentStickerPacks.append((info._parse(), items, isInstalled))
}
index += 1
}
@ -1772,6 +1772,9 @@ private final class StickerPackContainer: ASDisplayNode {
case let .result(info, items, installed):
isEditable = info.flags.contains(.isCreator) && !info.flags.contains(.isEmoji)
self.onReady()
let info = info._parse()
if !items.isEmpty && self.currentStickerPack == nil {
if let _ = self.validLayout, abs(self.expandScrollProgress - 1.0) < .ulpOfOne {
scrollToItem = GridNodeScrollToItem(index: 0, position: .top(0.0), transition: .immediate, directionHint: .up, adjustForSection: false)

View File

@ -587,7 +587,8 @@ public func chatMessageAnimatedSticker(postbox: Postbox, userLocation: MediaReso
}
}
public func preloadedStickerPackThumbnail(account: Account, info: StickerPackCollectionInfo, items: [ItemCollectionItem]) -> Signal<Bool, NoError> {
public func preloadedStickerPackThumbnail(account: Account, info: StickerPackCollectionInfo.Accessor, items: [ItemCollectionItem]) -> Signal<Bool, NoError> {
let info = info._parse()
if let thumbnail = info.thumbnail {
let signal = Signal<Bool, NoError> { subscriber in
let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: .stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)).start()

View File

@ -0,0 +1,6 @@
namespace TelegramCore;
struct ItemCollectionId {
namespace: int;
id: int64;
}

View File

@ -0,0 +1,19 @@
include "ItemCollectionId.fbs";
include "TelegramMediaImageRepresentation.fbs";
namespace TelegramCore;
table StickerPackCollectionInfo {
id:ItemCollectionId (id: 0, required);
flags:int32 (id: 1);
accessHash:int64 (id: 2);
title:string (id: 3, required);
shortName:string (id: 4, required);
thumbnail:TelegramMediaImageRepresentation (id: 5);
thumbnailFileId:int64 (id: 6);
immediateThumbnailData:[ubyte] (id: 7);
hash:int32 (id: 8);
count:int32 (id: 9);
}
root_type StickerPackCollectionInfo;

View File

@ -159,7 +159,7 @@ func updatedFeaturedStickerPacks(network: Network, postbox: Postbox, category: F
items = Array(items.prefix(5))
}
}
updatedPacks.append(FeaturedStickerPackItem(info: info, topItems: items, unread: unreadIds.contains(info.id.id)))
updatedPacks.append(FeaturedStickerPackItem(info: StickerPackCollectionInfo.Accessor(info), topItems: items, unread: unreadIds.contains(info.id.id)))
}
let isPremium = flags & (1 << 0) != 0
return .content(FeaturedListContent(
@ -194,7 +194,7 @@ func updatedFeaturedStickerPacks(network: Network, postbox: Postbox, category: F
items = previousPack.topItems
}
}
updatedPacks.append(FeaturedStickerPackItem(info: info, topItems: items, unread: unreadIds.contains(info.id.id)))
updatedPacks.append(FeaturedStickerPackItem(info: StickerPackCollectionInfo.Accessor(info), topItems: items, unread: unreadIds.contains(info.id.id)))
}
let isPremium = flags & (1 << 0) != 0
return .content(FeaturedListContent(
@ -247,7 +247,7 @@ public func requestOldFeaturedStickerPacks(network: Network, postbox: Postbox, o
var updatedPacks: [FeaturedStickerPackItem] = []
for set in sets {
let (info, items) = parsePreviewStickerSet(set, namespace: Namespaces.ItemCollection.CloudStickerPacks)
updatedPacks.append(FeaturedStickerPackItem(info: info, topItems: items, unread: unreadIds.contains(info.id.id)))
updatedPacks.append(FeaturedStickerPackItem(info: StickerPackCollectionInfo.Accessor(info), topItems: items, unread: unreadIds.contains(info.id.id)))
}
return updatedPacks
}

View File

@ -1,12 +1,15 @@
import Foundation
import Postbox
import FlatBuffers
import FlatSerialization
public final class CachedStickerPack: Codable {
public let info: StickerPackCollectionInfo?
public let info: StickerPackCollectionInfo.Accessor?
public let items: [StickerPackItem]
public let hash: Int32
public init(info: StickerPackCollectionInfo?, items: [StickerPackItem], hash: Int32) {
self.info = info
self.info = info.flatMap(StickerPackCollectionInfo.Accessor.init)
self.items = items
self.hash = hash
}
@ -14,8 +17,12 @@ public final class CachedStickerPack: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
if let infoData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: "in") {
self.info = StickerPackCollectionInfo(decoder: PostboxDecoder(buffer: MemoryBuffer(data: infoData.data)))
if let serializedInfoData = try container.decodeIfPresent(Data.self, forKey: "ind") {
var byteBuffer = ByteBuffer(data: serializedInfoData)
self.info = StickerPackCollectionInfo.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_StickerPackCollectionInfo, serializedInfoData)
} else if let infoData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: "in") {
let info = StickerPackCollectionInfo(decoder: PostboxDecoder(buffer: MemoryBuffer(data: infoData.data)))
self.info = StickerPackCollectionInfo.Accessor(info)
} else {
self.info = nil
}
@ -31,7 +38,17 @@ public final class CachedStickerPack: Codable {
var container = encoder.container(keyedBy: StringCodingKey.self)
if let info = self.info {
try container.encode(PostboxEncoder().encodeObjectToRawData(info), forKey: "in")
if let infoData = info._wrappedData {
try container.encode(infoData, forKey: "ind")
} else if let info = info._wrappedObject {
var builder = FlatBufferBuilder(initialSize: 1024)
let value = info.encodeToFlatBuffers(builder: &builder)
builder.finish(offset: value)
let serializedInstantPage = builder.data
try container.encode(serializedInstantPage, forKey: "ind")
} else {
preconditionFailure()
}
} else {
try container.encodeNil(forKey: "in")
}

View File

@ -1,5 +1,7 @@
import Foundation
import Postbox
import FlatBuffers
import FlatSerialization
public struct FeaturedStickerPackItemId {
public let rawValue: MemoryBuffer
@ -22,11 +24,11 @@ public struct FeaturedStickerPackItemId {
}
public final class FeaturedStickerPackItem: Codable {
public let info: StickerPackCollectionInfo
public let info: StickerPackCollectionInfo.Accessor
public let topItems: [StickerPackItem]
public let unread: Bool
public init(info: StickerPackCollectionInfo, topItems: [StickerPackItem], unread: Bool) {
public init(info: StickerPackCollectionInfo.Accessor, topItems: [StickerPackItem], unread: Bool) {
self.info = info
self.topItems = topItems
self.unread = unread
@ -35,8 +37,13 @@ public final class FeaturedStickerPackItem: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
let infoData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "i")
self.info = StickerPackCollectionInfo(decoder: PostboxDecoder(buffer: MemoryBuffer(data: infoData.data)))
if let serializedInfoData = try container.decodeIfPresent(Data.self, forKey: "infd") {
var byteBuffer = ByteBuffer(data: serializedInfoData)
self.info = StickerPackCollectionInfo.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_StickerPackCollectionInfo, serializedInfoData)
} else {
let infoData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "i")
self.info = StickerPackCollectionInfo.Accessor(StickerPackCollectionInfo(decoder: PostboxDecoder(buffer: MemoryBuffer(data: infoData.data))))
}
self.topItems = (try container.decode([AdaptedPostboxDecoder.RawObjectData].self, forKey: "t")).map { itemData in
return StickerPackItem(decoder: PostboxDecoder(buffer: MemoryBuffer(data: itemData.data)))
@ -48,7 +55,17 @@ public final class FeaturedStickerPackItem: Codable {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(PostboxEncoder().encodeObjectToRawData(self.info), forKey: "i")
if let infoData = self.info._wrappedData {
try container.encode(infoData, forKey: "infd")
} else if let info = self.info._wrappedObject {
var builder = FlatBufferBuilder(initialSize: 1024)
let value = info.encodeToFlatBuffers(builder: &builder)
builder.finish(offset: value)
let serializedInstantPage = builder.data
try container.encode(serializedInstantPage, forKey: "infd")
} else {
preconditionFailure()
}
try container.encode(self.topItems.map { item in
return PostboxEncoder().encodeObjectToRawData(item)
}, forKey: "t")

View File

@ -1,5 +1,7 @@
import Foundation
import Postbox
import FlatBuffers
import FlatSerialization
public struct StickerPackCollectionInfoFlags: OptionSet {
public var rawValue: Int32
@ -39,7 +41,6 @@ public struct StickerPackCollectionInfoFlags: OptionSet {
public static let isCreator = StickerPackCollectionInfoFlags(rawValue: 1 << 7)
}
public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable {
public let id: ItemCollectionId
public let flags: StickerPackCollectionInfoFlags
@ -102,6 +103,56 @@ public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable {
encoder.encodeInt32(self.hash, forKey: "h")
encoder.encodeInt32(self.flags.rawValue, forKey: "f")
encoder.encodeInt32(self.count, forKey: "n")
#if DEBUG
var builder = FlatBufferBuilder(initialSize: 1024)
let offset = self.encodeToFlatBuffers(builder: &builder)
builder.finish(offset: offset)
let serializedData = builder.data
var byteBuffer = ByteBuffer(data: serializedData)
let deserializedValue = FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_StickerPackCollectionInfo
let parsedValue = try! StickerPackCollectionInfo(flatBuffersObject: deserializedValue)
assert(self == parsedValue)
#endif
}
public init(flatBuffersObject: TelegramCore_StickerPackCollectionInfo) throws {
self.id = ItemCollectionId(flatBuffersObject.id)
self.flags = StickerPackCollectionInfoFlags(rawValue: flatBuffersObject.flags)
self.accessHash = flatBuffersObject.accessHash
self.title = flatBuffersObject.title
self.shortName = flatBuffersObject.shortName
self.thumbnail = try flatBuffersObject.thumbnail.flatMap(TelegramMediaImageRepresentation.init(flatBuffersObject:))
self.thumbnailFileId = flatBuffersObject.thumbnailFileId == Int64.min ? nil : flatBuffersObject.thumbnailFileId
self.immediateThumbnailData = flatBuffersObject.immediateThumbnailData.isEmpty ? nil : Data(flatBuffersObject.immediateThumbnailData)
self.hash = flatBuffersObject.hash
self.count = flatBuffersObject.count
}
public func encodeToFlatBuffers(builder: inout FlatBufferBuilder) -> Offset {
let titleOffset = builder.create(string: self.title)
let shortNameOffset = builder.create(string: self.shortName)
let thumbnailOffset = self.thumbnail.flatMap { $0.encodeToFlatBuffers(builder: &builder) }
let immediateThumbnailDataOffset = self.immediateThumbnailData.flatMap { builder.createVector(bytes: $0) }
let start = TelegramCore_StickerPackCollectionInfo.startStickerPackCollectionInfo(&builder)
TelegramCore_StickerPackCollectionInfo.add(id: self.id.asFlatBuffersObject(), &builder)
TelegramCore_StickerPackCollectionInfo.add(flags: self.flags.rawValue, &builder)
TelegramCore_StickerPackCollectionInfo.add(accessHash: self.accessHash, &builder)
TelegramCore_StickerPackCollectionInfo.add(title: titleOffset, &builder)
TelegramCore_StickerPackCollectionInfo.add(shortName: shortNameOffset, &builder)
if let thumbnailOffset {
TelegramCore_StickerPackCollectionInfo.add(thumbnail: thumbnailOffset, &builder)
}
TelegramCore_StickerPackCollectionInfo.add(thumbnailFileId: self.thumbnailFileId ?? Int64.min, &builder)
if let immediateThumbnailDataOffset {
TelegramCore_StickerPackCollectionInfo.addVectorOf(immediateThumbnailData: immediateThumbnailDataOffset, &builder)
}
TelegramCore_StickerPackCollectionInfo.add(hash: self.hash, &builder)
TelegramCore_StickerPackCollectionInfo.add(count: self.count, &builder)
return TelegramCore_StickerPackCollectionInfo.endStickerPackCollectionInfo(&builder, start: start)
}
public static func ==(lhs: StickerPackCollectionInfo, rhs: StickerPackCollectionInfo) -> Bool {
@ -129,6 +180,141 @@ public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable {
if lhs.count != rhs.count {
return false
}
if lhs.thumbnail != rhs.thumbnail {
return false
}
return true
}
}
public extension StickerPackCollectionInfo {
struct Accessor: Equatable {
let _wrappedObject: StickerPackCollectionInfo?
let _wrapped: TelegramCore_StickerPackCollectionInfo?
let _wrappedData: Data?
public init(_ wrapped: TelegramCore_StickerPackCollectionInfo, _ _wrappedData: Data) {
self._wrapped = wrapped
self._wrappedData = _wrappedData
self._wrappedObject = nil
}
public init(_ wrapped: StickerPackCollectionInfo) {
self._wrapped = nil
self._wrappedData = nil
self._wrappedObject = wrapped
}
public func _parse() -> StickerPackCollectionInfo {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject
} else {
return try! StickerPackCollectionInfo(flatBuffersObject: self._wrapped!)
}
}
public static func ==(lhs: StickerPackCollectionInfo.Accessor, rhs: StickerPackCollectionInfo.Accessor) -> Bool {
if let lhsWrappedObject = lhs._wrappedObject, let rhsWrappedObject = rhs._wrappedObject {
return lhsWrappedObject == rhsWrappedObject
} else if let lhsWrappedData = lhs._wrappedData, let rhsWrappedData = rhs._wrappedData {
return lhsWrappedData == rhsWrappedData
} else {
return lhs._parse() == rhs._parse()
}
}
}
}
public extension StickerPackCollectionInfo.Accessor {
var id: ItemCollectionId {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.id
}
return ItemCollectionId(self._wrapped!.id)
}
var accessHash: Int64 {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.accessHash
}
return self._wrapped!.accessHash
}
var flags: StickerPackCollectionInfoFlags {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.flags
}
return StickerPackCollectionInfoFlags(rawValue: self._wrapped!.flags)
}
var title: String {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.title
}
return self._wrapped!.title
}
var shortName: String {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.shortName
}
return self._wrapped!.shortName
}
var hash: Int32 {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.hash
}
return self._wrapped!.hash
}
var immediateThumbnailData: Data? {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.immediateThumbnailData
}
return self._wrapped!.immediateThumbnailData.isEmpty ? nil : Data(self._wrapped!.immediateThumbnailData)
}
var thumbnailFileId: Int64? {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.thumbnailFileId
}
return self._wrapped!.thumbnailFileId == Int64.min ? nil : self._wrapped!.thumbnailFileId
}
var count: Int32 {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.count
}
return self._wrapped!.count
}
var hasThumbnail: Bool {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.thumbnail != nil
}
return self._wrapped!.thumbnail != nil
}
var thumbnailDimensions: PixelDimensions? {
if let _wrappedObject = self._wrappedObject {
return _wrappedObject.thumbnail?.dimensions
}
if let thumbnail = self._wrapped!.thumbnail {
return PixelDimensions(width: thumbnail.width, height: thumbnail.height)
} else {
return nil
}
}
}

View File

@ -12,7 +12,7 @@ private struct WrappedStickerPackCollectionInfo: Equatable {
}
public struct PeerSpecificStickerPackData {
public let packInfo: (StickerPackCollectionInfo, [ItemCollectionItem])?
public let packInfo: (StickerPackCollectionInfo.Accessor, [ItemCollectionItem])?
public let canSetup: Bool
}

View File

@ -6,7 +6,7 @@ import MurMurHash32
public enum CachedStickerPackResult {
case none
case fetching
case result(StickerPackCollectionInfo, [StickerPackItem], Bool)
case result(StickerPackCollectionInfo.Accessor, [StickerPackItem], Bool)
}
func cacheStickerPack(transaction: Transaction, info: StickerPackCollectionInfo, items: [StickerPackItem], reference: StickerPackReference? = nil) {
@ -228,7 +228,7 @@ func _internal_cachedStickerPack(postbox: Postbox, network: Network, reference:
if let result = result {
cacheStickerPack(transaction: transaction, info: result.0, items: result.1, reference: reference)
let currentInfo = transaction.getItemCollectionInfo(collectionId: result.0.id) as? StickerPackCollectionInfo
return .result(result.0, result.1, currentInfo != nil)
return .result(StickerPackCollectionInfo.Accessor(result.0), result.1, currentInfo != nil)
} else {
return .none
}
@ -244,7 +244,7 @@ func _internal_cachedStickerPack(postbox: Postbox, network: Network, reference:
}
}
func cachedStickerPack(transaction: Transaction, reference: StickerPackReference) -> (StickerPackCollectionInfo, [StickerPackItem], Bool)? {
func cachedStickerPack(transaction: Transaction, reference: StickerPackReference) -> (StickerPackCollectionInfo.Accessor, [StickerPackItem], Bool)? {
let namespaces: [Int32] = [Namespaces.ItemCollection.CloudStickerPacks, Namespaces.ItemCollection.CloudMaskPacks, Namespaces.ItemCollection.CloudEmojiPacks]
switch reference {
case let .id(id, _):
@ -252,7 +252,7 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference
if let currentInfo = transaction.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo {
let items = transaction.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id))
if !items.isEmpty {
return (currentInfo, items.compactMap { $0 as? StickerPackItem }, true)
return (StickerPackCollectionInfo.Accessor(currentInfo), items.compactMap { $0 as? StickerPackItem }, true)
}
}
if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info {
@ -267,7 +267,7 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference
if info.shortName.lowercased() == shortName {
let items = transaction.getItemCollectionItems(collectionId: info.id)
if !items.isEmpty {
return (info, items.compactMap { $0 as? StickerPackItem }, true)
return (StickerPackCollectionInfo.Accessor(info), items.compactMap { $0 as? StickerPackItem }, true)
}
}
}
@ -282,7 +282,7 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference
if let currentInfo = transaction.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo {
let items = transaction.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id))
if !items.isEmpty {
return (currentInfo, items.compactMap { $0 as? StickerPackItem }, true)
return (StickerPackCollectionInfo.Accessor(currentInfo), items.compactMap { $0 as? StickerPackItem }, true)
}
}
if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info {
@ -294,7 +294,7 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference
if let currentInfo = transaction.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo {
let items = transaction.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id))
if !items.isEmpty {
return (currentInfo, items.compactMap { $0 as? StickerPackItem }, true)
return (StickerPackCollectionInfo.Accessor(currentInfo), items.compactMap { $0 as? StickerPackItem }, true)
}
}
if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info {
@ -306,7 +306,7 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference
if let currentInfo = transaction.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo {
let items = transaction.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id))
if !items.isEmpty {
return (currentInfo, items.compactMap { $0 as? StickerPackItem }, true)
return (StickerPackCollectionInfo.Accessor(currentInfo), items.compactMap { $0 as? StickerPackItem }, true)
}
}
if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info {
@ -318,7 +318,7 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference
if let currentInfo = transaction.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo {
let items = transaction.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id))
if !items.isEmpty {
return (currentInfo, items.compactMap { $0 as? StickerPackItem }, true)
return (StickerPackCollectionInfo.Accessor(currentInfo), items.compactMap { $0 as? StickerPackItem }, true)
}
}
if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info {
@ -330,7 +330,7 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference
if let currentInfo = transaction.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo {
let items = transaction.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id))
if !items.isEmpty {
return (currentInfo, items.compactMap { $0 as? StickerPackItem }, true)
return (StickerPackCollectionInfo.Accessor(currentInfo), items.compactMap { $0 as? StickerPackItem }, true)
}
}
if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info {
@ -342,7 +342,7 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference
if let currentInfo = transaction.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo {
let items = transaction.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id))
if !items.isEmpty {
return (currentInfo, items.compactMap { $0 as? StickerPackItem }, true)
return (StickerPackCollectionInfo.Accessor(currentInfo), items.compactMap { $0 as? StickerPackItem }, true)
}
}
if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info {
@ -354,7 +354,7 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference
if let currentInfo = transaction.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo {
let items = transaction.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id))
if !items.isEmpty {
return (currentInfo, items.compactMap { $0 as? StickerPackItem }, true)
return (StickerPackCollectionInfo.Accessor(currentInfo), items.compactMap { $0 as? StickerPackItem }, true)
}
}
if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info {
@ -366,7 +366,7 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference
if let currentInfo = transaction.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo {
let items = transaction.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id))
if !items.isEmpty {
return (currentInfo, items.compactMap { $0 as? StickerPackItem }, true)
return (StickerPackCollectionInfo.Accessor(currentInfo), items.compactMap { $0 as? StickerPackItem }, true)
}
}
if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info {

View File

@ -37,7 +37,7 @@ extension StickerPackReference {
public enum LoadedStickerPack {
case fetching
case none
case result(info: StickerPackCollectionInfo, items: [StickerPackItem], installed: Bool)
case result(info: StickerPackCollectionInfo.Accessor, items: [StickerPackItem], installed: Bool)
}
func updatedRemoteStickerPack(postbox: Postbox, network: Network, reference: StickerPackReference) -> Signal<(StickerPackCollectionInfo, [StickerPackItem])?, NoError> {

View File

@ -52,3 +52,13 @@ public extension PixelDimensions {
return TelegramCore_PixelDimensions(width: self.width, height: self.height)
}
}
public extension ItemCollectionId {
init(_ id: TelegramCore_ItemCollectionId) {
self.init(namespace: id.namespace, id: id.id)
}
func asFlatBuffersObject() -> TelegramCore_ItemCollectionId {
return TelegramCore_ItemCollectionId(namespace: self.namespace, id: self.id)
}
}

View File

@ -556,7 +556,7 @@ final class AvatarEditorScreenComponent: Component {
if installed {
return .complete()
} else {
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
return context.engine.stickers.addStickerPackInteractively(info: info._parse(), items: items)
}
case .fetching:
break
@ -691,7 +691,7 @@ final class AvatarEditorScreenComponent: Component {
if installed {
return .complete()
} else {
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
return context.engine.stickers.addStickerPackInteractively(info: info._parse(), items: items)
}
case .fetching:
break

View File

@ -546,7 +546,11 @@ public final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode, Chat
public func updatePeer(peer: Peer) {
if let previousPeer = self.peer, previousPeer.nameColor != peer.nameColor {
self.peer = peer
self.avatarNode.setPeer(context: self.context, theme: self.presentationData.theme.theme, peer: EnginePeer(peer), authorOfMessage: self.messageReference, overrideImage: nil, emptyColor: .black, synchronousLoad: false, displayDimensions: CGSize(width: 38.0, height: 38.0))
if peer.smallProfileImage != nil {
self.avatarNode.setPeerV2(context: self.context, theme: self.presentationData.theme.theme, peer: EnginePeer(peer), authorOfMessage: self.messageReference, overrideImage: nil, emptyColor: .black, synchronousLoad: false, displayDimensions: CGSize(width: 38.0, height: 38.0))
} else {
self.avatarNode.setPeer(context: self.context, theme: self.presentationData.theme.theme, peer: EnginePeer(peer), authorOfMessage: self.messageReference, overrideImage: nil, emptyColor: .black, synchronousLoad: false, displayDimensions: CGSize(width: 38.0, height: 38.0))
}
}
}
@ -561,7 +565,11 @@ public final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode, Chat
if peer.isDeleted {
overrideImage = .deletedIcon
}
self.avatarNode.setPeer(context: context, theme: theme, peer: EnginePeer(peer), authorOfMessage: authorOfMessage, overrideImage: overrideImage, emptyColor: emptyColor, synchronousLoad: synchronousLoad, displayDimensions: CGSize(width: 38.0, height: 38.0))
if peer.smallProfileImage != nil {
self.avatarNode.setPeerV2(context: context, theme: theme, peer: EnginePeer(peer), authorOfMessage: authorOfMessage, overrideImage: overrideImage, emptyColor: emptyColor, synchronousLoad: synchronousLoad, displayDimensions: CGSize(width: 38.0, height: 38.0))
} else {
self.avatarNode.setPeer(context: context, theme: theme, peer: EnginePeer(peer), authorOfMessage: authorOfMessage, overrideImage: overrideImage, emptyColor: emptyColor, synchronousLoad: synchronousLoad, displayDimensions: CGSize(width: 38.0, height: 38.0))
}
if peer.isPremium && context.sharedContext.energyUsageSettings.autoplayVideo {
self.cachedDataDisposable.set((context.account.postbox.peerView(id: peer.id)

View File

@ -787,7 +787,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
if let strongSelf = self {
strongSelf.scheduledContentAnimationHint = EmojiPagerContentComponent.ContentAnimation(type: .groupInstalled(id: collectionId, scrollToGroup: scrollToGroup))
}
let _ = context.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info, items: featuredEmojiPack.topItems).start()
let _ = context.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info._parse(), items: featuredEmojiPack.topItems).start()
break
}
@ -1300,7 +1300,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
if installed {
return .complete()
} else {
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
return context.engine.stickers.addStickerPackInteractively(info: info._parse(), items: items)
}
case .fetching:
break

View File

@ -95,7 +95,7 @@ private enum StickerSearchEntry: Identifiable, Comparable {
case let .global(_, info, topItems, installed, topSeparator):
let itemContext = StickerPaneSearchGlobalItemContext()
itemContext.canPlayMedia = true
return StickerPaneSearchGlobalItem(context: context, theme: theme, strings: strings, listAppearance: false, info: info, topItems: topItems, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: {
return StickerPaneSearchGlobalItem(context: context, theme: theme, strings: strings, listAppearance: false, info: StickerPackCollectionInfo.Accessor(info), topItems: topItems, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: {
interaction.open(info)
}, install: {
interaction.install(info, topItems, !installed)
@ -255,10 +255,11 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|> mapToSignal { result -> Signal<(StickerPackCollectionInfo, [StickerPackItem]), NoError> in
switch result {
case let .result(info, items, installed):
let info = info._parse()
if installed {
return .complete()
} else {
return preloadedStickerPackThumbnail(account: context.account, info: info, items: items)
return preloadedStickerPackThumbnail(account: context.account, info: StickerPackCollectionInfo.Accessor(info), items: items)
|> filter { $0 }
|> ignoreValues
|> then(

View File

@ -452,7 +452,7 @@ public final class EmojiStatusSelectionController: ViewController {
if let strongSelf = self {
strongSelf.scheduledEmojiContentAnimationHint = EmojiPagerContentComponent.ContentAnimation(type: .groupInstalled(id: collectionId, scrollToGroup: true))
}
let _ = strongSelf.context.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info, items: featuredEmojiPack.topItems).start()
let _ = strongSelf.context.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info._parse(), items: featuredEmojiPack.topItems).start()
break
}

View File

@ -62,12 +62,15 @@ public final class EntityKeyboardAnimationData: Equatable {
public enum Resource: Equatable {
case resource(MediaResourceReference)
case stickerPackThumbnail(id: Int64, accessHash: Int64, info: StickerPackCollectionInfo.Accessor)
case file(PartialMediaReference?, TelegramMediaFile.Accessor)
func _parse() -> MediaResourceReference {
switch self {
case let .resource(resource):
return resource
case let .stickerPackThumbnail(id, accessHash, info):
return .stickerPackThumbnail(stickerPack: .id(id: id, accessHash: accessHash), resource: info._parse().thumbnail!.resource)
case let .file(partialReference, file):
let file = file._parse()
if let partialReference {

View File

@ -73,7 +73,7 @@ public extension EmojiPagerContentComponent {
let strings = context.sharedContext.currentPresentationData.with({ $0 }).strings
struct PeerSpecificPackData: Equatable {
var info: StickerPackCollectionInfo
var info: StickerPackCollectionInfo.Accessor
var items: [StickerPackItem]
var peer: EnginePeer
@ -282,7 +282,7 @@ public extension EmojiPagerContentComponent {
let animationData: EntityKeyboardAnimationData
if let thumbnail = featuredEmojiPack.info.thumbnail {
if let thumbnailDimensions = featuredEmojiPack.info.thumbnailDimensions {
let type: EntityKeyboardAnimationData.ItemType
if item.file.isAnimatedSticker {
type = .lottie
@ -295,8 +295,8 @@ public extension EmojiPagerContentComponent {
animationData = EntityKeyboardAnimationData(
id: .stickerPackThumbnail(featuredEmojiPack.info.id),
type: type,
resource: .resource(.stickerPackThumbnail(stickerPack: .id(id: featuredEmojiPack.info.id.id, accessHash: featuredEmojiPack.info.accessHash), resource: thumbnail.resource)),
dimensions: thumbnail.dimensions.cgSize,
resource: .stickerPackThumbnail(id: featuredEmojiPack.info.id.id, accessHash: featuredEmojiPack.info.accessHash, info: featuredEmojiPack.info),
dimensions: thumbnailDimensions.cgSize,
immediateThumbnailData: featuredEmojiPack.info.immediateThumbnailData,
isReaction: false,
isTemplate: false
@ -1471,7 +1471,7 @@ public extension EmojiPagerContentComponent {
var headerItem: EntityKeyboardAnimationData?
if let thumbnailFileId = featuredEmojiPack.info.thumbnailFileId, let file = featuredEmojiPack.topItems.first(where: { $0.file.fileId.id == thumbnailFileId }) {
headerItem = EntityKeyboardAnimationData(file: file.file)
} else if let thumbnail = featuredEmojiPack.info.thumbnail {
} else if let thumbnailDimensions = featuredEmojiPack.info.thumbnailDimensions {
let info = featuredEmojiPack.info
let type: EntityKeyboardAnimationData.ItemType
if item.file.isAnimatedSticker {
@ -1485,8 +1485,8 @@ public extension EmojiPagerContentComponent {
headerItem = EntityKeyboardAnimationData(
id: .stickerPackThumbnail(info.id),
type: type,
resource: .resource(.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)),
dimensions: thumbnail.dimensions.cgSize,
resource: .stickerPackThumbnail(id: featuredEmojiPack.info.id.id, accessHash: featuredEmojiPack.info.accessHash, info: featuredEmojiPack.info),
dimensions: thumbnailDimensions.cgSize,
immediateThumbnailData: info.immediateThumbnailData,
isReaction: false,
isTemplate: false
@ -1632,7 +1632,7 @@ public extension EmojiPagerContentComponent {
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
struct PeerSpecificPackData: Equatable {
var info: StickerPackCollectionInfo
var info: StickerPackCollectionInfo.Accessor
var items: [StickerPackItem]
var peer: EnginePeer
@ -1769,7 +1769,7 @@ public extension EmojiPagerContentComponent {
let animationData: EntityKeyboardAnimationData
if let thumbnail = featuredStickerPack.info.thumbnail {
if let thumbnailDimensions = featuredStickerPack.info.thumbnailDimensions {
let type: EntityKeyboardAnimationData.ItemType
if item.file.isAnimatedSticker {
type = .lottie
@ -1782,8 +1782,8 @@ public extension EmojiPagerContentComponent {
animationData = EntityKeyboardAnimationData(
id: .stickerPackThumbnail(featuredStickerPack.info.id),
type: type,
resource: .resource(.stickerPackThumbnail(stickerPack: .id(id: featuredStickerPack.info.id.id, accessHash: featuredStickerPack.info.accessHash), resource: thumbnail.resource)),
dimensions: thumbnail.dimensions.cgSize,
resource: .stickerPackThumbnail(id: featuredStickerPack.info.id.id, accessHash: featuredStickerPack.info.accessHash, info: featuredStickerPack.info),
dimensions: thumbnailDimensions.cgSize,
immediateThumbnailData: featuredStickerPack.info.immediateThumbnailData,
isReaction: false,
isTemplate: false
@ -2084,7 +2084,7 @@ public extension EmojiPagerContentComponent {
if let thumbnailFileId = featuredStickerPack.info.thumbnailFileId, let file = featuredStickerPack.topItems.first(where: { $0.file.fileId.id == thumbnailFileId }) {
headerItem = EntityKeyboardAnimationData(file: file.file)
} else if let thumbnail = featuredStickerPack.info.thumbnail {
} else if let thumbnailDimensions = featuredStickerPack.info.thumbnailDimensions {
let info = featuredStickerPack.info
let type: EntityKeyboardAnimationData.ItemType
if item.file.isAnimatedSticker {
@ -2098,8 +2098,8 @@ public extension EmojiPagerContentComponent {
headerItem = EntityKeyboardAnimationData(
id: .stickerPackThumbnail(info.id),
type: type,
resource: .resource(.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)),
dimensions: thumbnail.dimensions.cgSize,
resource: .stickerPackThumbnail(id: info.id.id, accessHash: info.accessHash, info: info),
dimensions: thumbnailDimensions.cgSize,
immediateThumbnailData: info.immediateThumbnailData,
isReaction: false,
isTemplate: false

View File

@ -910,7 +910,7 @@ private final class ForumCreateTopicScreenComponent: CombinedComponent {
}
for featuredEmojiPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) {
if featuredEmojiPack.info.id == collectionId {
let _ = accountContext.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info, items: featuredEmojiPack.topItems).start()
let _ = accountContext.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info._parse(), items: featuredEmojiPack.topItems).start()
break
}

View File

@ -220,7 +220,7 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
case let .packsTitle(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .pack(_, _, _, info, topItem, count, playAnimatedStickers, selected):
return ItemListStickerPackItem(presentationData: presentationData, context: arguments.context, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: selected ? .selection : .none, editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false, selectable: false), enabled: true, playAnimatedStickers: playAnimatedStickers, sectionId: self.section, action: {
return ItemListStickerPackItem(presentationData: presentationData, context: arguments.context, packInfo: StickerPackCollectionInfo.Accessor(info), itemCount: count, topItem: topItem, unread: false, control: selected ? .selection : .none, editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false, selectable: false), enabled: true, playAnimatedStickers: playAnimatedStickers, sectionId: self.section, action: {
if selected {
arguments.openStickerPack(info)
} else {
@ -337,7 +337,7 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres
case .fetching:
return nil
case let .result(info, items, _):
return InitialStickerPackData.data(StickerPackData(info: info, item: items.first))
return InitialStickerPackData.data(StickerPackData(info: info._parse(), item: items.first))
}
})
} else {
@ -389,7 +389,7 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres
case .none:
return .single((searchText, .notFound))
case let .result(info, items, _):
return .single((searchText, .found(StickerPackData(info: info, item: items.first))))
return .single((searchText, .found(StickerPackData(info: info._parse(), item: items.first))))
}
}
|> afterNext { value in

View File

@ -48,7 +48,7 @@ private final class GroupStickerSearchEntry: Comparable, Identifiable {
let pack = self.pack
let count = presentationData.strings.StickerPack_EmojiCount(pack.count)
return ItemListStickerPackItem(presentationData: ItemListPresentationData(presentationData), context: context, packInfo: pack, itemCount: count, topItem: self.topItem as? StickerPackItem, unread: false, control: .none, editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false, selectable: false), enabled: true, playAnimatedStickers: true, style: .plain, sectionId: 0, action: {
return ItemListStickerPackItem(presentationData: ItemListPresentationData(presentationData), context: context, packInfo: StickerPackCollectionInfo.Accessor(pack), itemCount: count, topItem: self.topItem as? StickerPackItem, unread: false, control: .none, editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false, selectable: false), enabled: true, playAnimatedStickers: true, style: .plain, sectionId: 0, action: {
interaction.packSelected(pack)
}, setPackIdWithRevealedOptions: { _, _ in
}, addPack: {

View File

@ -955,7 +955,7 @@ public class StickerPickerScreen: ViewController {
if installed {
return .complete()
} else {
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
return context.engine.stickers.addStickerPackInteractively(info: info._parse(), items: items)
}
case .fetching:
break
@ -1370,7 +1370,7 @@ public class StickerPickerScreen: ViewController {
if installed {
return .complete()
} else {
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
return context.engine.stickers.addStickerPackInteractively(info: info._parse(), items: items)
}
case .fetching:
break

View File

@ -1901,6 +1901,14 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
extendNow = false
}
sharedApplicationContext.wakeupManager.allowBackgroundTimeExtension(timeout: 2.0, extendNow: extendNow)
let _ = (sharedApplicationContext.sharedContext.activeAccountContexts
|> take(1)
|> deliverOnMainQueue).start(next: { activeAccounts in
for (_, context, _) in activeAccounts.accounts {
context.account.postbox.clearCaches()
}
})
})
self.isInForegroundValue = false

View File

@ -552,7 +552,6 @@ extension ChatControllerImpl {
return .single(true)
} else {
return .single(false)
|> delay(0.1, queue: .mainQueue())
}
}
|> distinctUntilChanged
@ -717,15 +716,15 @@ extension ChatControllerImpl {
}
)
self.cachedDataDisposable = combineLatest(queue: .mainQueue(), self.chatDisplayNode.historyNode.cachedPeerDataAndMessages,
hasPendingMessages,
isTopReplyThreadMessageShown,
topPinnedMessage,
customEmojiAvailable,
isForum,
threadData,
forumTopicData,
premiumGiftOptions
self.cachedDataDisposable = combineLatest(queue: .mainQueue(), self.chatDisplayNode.historyNode.cachedPeerDataAndMessages |> debug_measureTimeToFirstEvent(label: "cachedData_cachedPeerDataAndMessages"),
hasPendingMessages |> debug_measureTimeToFirstEvent(label: "cachedData_hasPendingMessages"),
isTopReplyThreadMessageShown |> debug_measureTimeToFirstEvent(label: "cachedData_isTopReplyThreadMessageShown"),
topPinnedMessage |> debug_measureTimeToFirstEvent(label: "cachedData_topPinnedMessage"),
customEmojiAvailable |> debug_measureTimeToFirstEvent(label: "cachedData_customEmojiAvailable"),
isForum |> debug_measureTimeToFirstEvent(label: "cachedData_isForum"),
threadData |> debug_measureTimeToFirstEvent(label: "cachedData_threadData"),
forumTopicData |> debug_measureTimeToFirstEvent(label: "cachedData_forumTopicData"),
premiumGiftOptions |> debug_measureTimeToFirstEvent(label: "cachedData_premiumGiftOptions")
).startStrict(next: { [weak self] cachedDataAndMessages, hasPendingMessages, isTopReplyThreadMessageShown, topPinnedMessage, customEmojiAvailable, isForum, threadData, forumTopicData, premiumGiftOptions in
if let strongSelf = self {
let (cachedData, messages) = cachedDataAndMessages
@ -990,21 +989,26 @@ extension ChatControllerImpl {
if case .replyThread = self.chatLocation {
effectiveCachedDataReady = self.cachedDataReady.get()
} else {
//effectiveCachedDataReady = .single(true)
effectiveCachedDataReady = self.cachedDataReady.get()
}
var measure_isFirstTime = true
let initTimestamp = self.initTimestamp
let mapped_chatLocationInfoReady = self._chatLocationInfoReady.get() |> filter { $0 } |> debug_measureTimeToFirstEvent(label: "chatLocationInfoReady")
let mapped_effectiveCachedDataReady = effectiveCachedDataReady |> filter { $0 } |> debug_measureTimeToFirstEvent(label: "effectiveCachedDataReady")
let mapped_initialDataReady = initialData |> map { $0 != nil } |> filter { $0 } |> debug_measureTimeToFirstEvent(label: "initialDataReady")
let mapped_wallpaperReady = self.wallpaperReady.get() |> filter { $0 } |> debug_measureTimeToFirstEvent(label: "wallpaperReady")
let mapped_presentationReady = self.presentationReady.get() |> filter { $0 } |> debug_measureTimeToFirstEvent(label: "presentationReady")
self.ready.set(combineLatest(queue: .mainQueue(),
self.chatDisplayNode.historyNode.historyState.get(),
self._chatLocationInfoReady.get(),
effectiveCachedDataReady,
initialData,
self.wallpaperReady.get(),
self.presentationReady.get()
mapped_chatLocationInfoReady,
mapped_effectiveCachedDataReady,
mapped_initialDataReady,
mapped_wallpaperReady,
mapped_presentationReady
)
|> map { _, chatLocationInfoReady, cachedDataReady, _, wallpaperReady, presentationReady in
return chatLocationInfoReady && cachedDataReady && wallpaperReady && presentationReady
|> map { chatLocationInfoReady, cachedDataReady, initialData, wallpaperReady, presentationReady in
return chatLocationInfoReady && cachedDataReady && initialData && wallpaperReady && presentationReady
}
|> distinctUntilChanged
|> beforeNext { value in
@ -1016,6 +1020,9 @@ extension ChatControllerImpl {
#endif
}
})
#if DEBUG
//self.ready.set(.single(true))
#endif
if self.context.sharedContext.immediateExperimentalUISettings.crashOnLongQueries {
let _ = (self.ready.get()

View File

@ -1720,8 +1720,8 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
let startTime = CFAbsoluteTimeGetCurrent()
var measure_isFirstTime = true
let messageViewQueue = Queue.mainQueue()
let historyViewTransitionDisposable = combineLatest(queue: messageViewQueue,
historyViewUpdate,
let historyViewTransitionDisposable = (combineLatest(queue: messageViewQueue,
historyViewUpdate |> debug_measureTimeToFirstEvent(label: "historyViewUpdate"),
self.chatPresentationDataPromise.get(),
selectedMessages,
updatingMedia,
@ -1746,7 +1746,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
chatThemes,
deviceContactsNumbers,
contentSettings
).startStrict(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, preferredStoryHighQuality, animatedEmojiStickers, additionalAnimatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState, availableReactions, availableMessageEffects, savedMessageTags, defaultReaction, accountPeer, suggestAudioTranscription, promises, topicAuthorId, translationState, maxReadStoryId, recommendedChannels, audioTranscriptionTrial, chatThemes, deviceContactsNumbers, contentSettings in
) |> debug_measureTimeToFirstEvent(label: "firstChatHistoryTransition")).startStrict(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, preferredStoryHighQuality, animatedEmojiStickers, additionalAnimatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState, availableReactions, availableMessageEffects, savedMessageTags, defaultReaction, accountPeer, suggestAudioTranscription, promises, topicAuthorId, translationState, maxReadStoryId, recommendedChannels, audioTranscriptionTrial, chatThemes, deviceContactsNumbers, contentSettings in
let (historyAppearsCleared, pendingUnpinnedAllMessages, pendingRemovedMessages, currentlyPlayingMessageIdAndType, scrollToMessageId, chatHasBots, allAdMessages) = promises
if measure_isFirstTime {

View File

@ -2853,7 +2853,7 @@ private final class ChatReadReportContextItemNode: ASDisplayNode, ContextMenuCus
}
|> map { result -> StickerPackCollectionInfo? in
if case let .result(info, _, _) = result {
return info
return info._parse()
} else {
return nil
}