This commit is contained in:
Ilya Laktyushin
2022-12-03 21:57:32 +04:00
parent 9c1c901a97
commit 02e06779ef
135 changed files with 19521 additions and 711 deletions

View File

@@ -83,10 +83,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
return hasPremium
}
static func inputData(context: AccountContext, interfaceInteraction: ChatPanelInterfaceInteraction, controllerInteraction: ChatControllerInteraction?, chatPeerId: PeerId?, areCustomEmojiEnabled: Bool) -> Signal<InputData, NoError> {
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
static func inputData(context: AccountContext, interfaceInteraction: ChatPanelInterfaceInteraction, controllerInteraction: ChatControllerInteraction?, chatPeerId: PeerId?, areCustomEmojiEnabled: Bool) -> Signal<InputData, NoError> {
let animationCache = context.animationCache
let animationRenderer = context.animationRenderer
@@ -94,458 +91,10 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
let stickerNamespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks]
let stickerOrderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.CloudAllPremiumStickers]
struct PeerSpecificPackData: Equatable {
var info: StickerPackCollectionInfo
var items: [StickerPackItem]
var peer: EnginePeer
static func ==(lhs: PeerSpecificPackData, rhs: PeerSpecificPackData) -> Bool {
if lhs.info.id != rhs.info.id {
return false
}
if lhs.items != rhs.items {
return false
}
if lhs.peer != rhs.peer {
return false
}
return true
}
}
let peerSpecificPack: Signal<PeerSpecificPackData?, NoError>
if let chatPeerId = chatPeerId {
peerSpecificPack = combineLatest(
context.engine.peers.peerSpecificStickerPack(peerId: chatPeerId),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: chatPeerId))
)
|> map { packData, peer -> PeerSpecificPackData? in
guard let peer = peer else {
return nil
}
guard let (info, items) = packData.packInfo else {
return nil
}
return PeerSpecificPackData(info: info, items: items.compactMap { $0 as? StickerPackItem }, peer: peer)
}
|> distinctUntilChanged
} else {
peerSpecificPack = .single(nil)
}
let strings = context.sharedContext.currentPresentationData.with({ $0 }).strings
let stickerItems: Signal<EmojiPagerContentComponent, NoError> = combineLatest(
context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: stickerOrderedItemListCollectionIds, namespaces: stickerNamespaces, aroundIndex: nil, count: 10000000),
ChatEntityKeyboardInputNode.hasPremium(context: context, chatPeerId: chatPeerId, premiumIfSavedMessages: false),
context.account.viewTracker.featuredStickerPacks(),
context.engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: Namespaces.CachedItemCollection.featuredStickersConfiguration, id: ValueBoxKey(length: 0))),
ApplicationSpecificNotice.dismissedTrendingStickerPacks(accountManager: context.sharedContext.accountManager),
peerSpecificPack
)
|> map { view, hasPremium, featuredStickerPacks, featuredStickersConfiguration, dismissedTrendingStickerPacks, peerSpecificPack -> EmojiPagerContentComponent in
struct ItemGroup {
var supergroupId: AnyHashable
var id: AnyHashable
var title: String
var subtitle: String?
var actionButtonTitle: String?
var isPremiumLocked: Bool
var isFeatured: Bool
var displayPremiumBadges: Bool
var headerItem: EntityKeyboardAnimationData?
var items: [EmojiPagerContentComponent.Item]
}
var itemGroups: [ItemGroup] = []
var itemGroupIndexById: [AnyHashable: Int] = [:]
var savedStickers: OrderedItemListView?
var recentStickers: OrderedItemListView?
var cloudPremiumStickers: OrderedItemListView?
for orderedView in view.orderedItemListsViews {
if orderedView.collectionId == Namespaces.OrderedItemList.CloudRecentStickers {
recentStickers = orderedView
} else if orderedView.collectionId == Namespaces.OrderedItemList.CloudSavedStickers {
savedStickers = orderedView
} else if orderedView.collectionId == Namespaces.OrderedItemList.CloudAllPremiumStickers {
cloudPremiumStickers = orderedView
}
}
var installedCollectionIds = Set<ItemCollectionId>()
for (id, _, _) in view.collectionInfos {
installedCollectionIds.insert(id)
}
let dismissedTrendingStickerPacksSet = Set(dismissedTrendingStickerPacks ?? [])
let featuredStickerPacksSet = Set(featuredStickerPacks.map(\.info.id.id))
if dismissedTrendingStickerPacksSet != featuredStickerPacksSet {
let featuredStickersConfiguration = featuredStickersConfiguration?.get(FeaturedStickersConfiguration.self)
for featuredStickerPack in featuredStickerPacks {
if installedCollectionIds.contains(featuredStickerPack.info.id) {
continue
}
guard let item = featuredStickerPack.topItems.first else {
continue
}
let animationData: EntityKeyboardAnimationData
if let thumbnail = featuredStickerPack.info.thumbnail {
let type: EntityKeyboardAnimationData.ItemType
if item.file.isAnimatedSticker {
type = .lottie
} else if item.file.isVideoEmoji || item.file.isVideoSticker {
type = .video
} else {
type = .still
}
animationData = EntityKeyboardAnimationData(
id: .stickerPackThumbnail(featuredStickerPack.info.id),
type: type,
resource: .stickerPackThumbnail(stickerPack: .id(id: featuredStickerPack.info.id.id, accessHash: featuredStickerPack.info.accessHash), resource: thumbnail.resource),
dimensions: thumbnail.dimensions.cgSize,
immediateThumbnailData: featuredStickerPack.info.immediateThumbnailData,
isReaction: false
)
} else {
animationData = EntityKeyboardAnimationData(file: item.file)
}
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: item.file,
subgroupId: nil,
icon: .none,
accentTint: false
)
let supergroupId = "featuredTop"
let groupId: AnyHashable = supergroupId
let isPremiumLocked: Bool = item.file.isPremiumSticker && !hasPremium
if isPremiumLocked && isPremiumDisabled {
continue
}
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
let trendingIsPremium = featuredStickersConfiguration?.isPremium ?? false
let title = trendingIsPremium ? strings.Stickers_TrendingPremiumStickers : strings.StickerPacksSettings_FeaturedPacks
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: title, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, headerItem: nil, items: [resultItem]))
}
}
}
if let savedStickers = savedStickers {
for item in savedStickers.items {
guard let item = item.contents.get(SavedStickerItem.self) else {
continue
}
if isPremiumDisabled && item.file.isPremiumSticker {
continue
}
let animationData = EntityKeyboardAnimationData(file: item.file)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: item.file,
subgroupId: nil,
icon: .none,
accentTint: false
)
let groupId = "saved"
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleFavoriteStickers, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, headerItem: nil, items: [resultItem]))
}
}
}
if let recentStickers = recentStickers {
for item in recentStickers.items {
guard let item = item.contents.get(RecentMediaItem.self) else {
continue
}
if isPremiumDisabled && item.media.isPremiumSticker {
continue
}
let animationData = EntityKeyboardAnimationData(file: item.media)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: item.media,
subgroupId: nil,
icon: .none,
accentTint: false
)
let groupId = "recent"
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Stickers_FrequentlyUsed, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, headerItem: nil, items: [resultItem]))
}
}
}
var premiumStickers: [StickerPackItem] = []
if hasPremium {
for entry in view.entries {
guard let item = entry.item as? StickerPackItem else {
continue
}
if item.file.isPremiumSticker {
premiumStickers.append(item)
}
}
if let cloudPremiumStickers = cloudPremiumStickers, !cloudPremiumStickers.items.isEmpty {
premiumStickers.append(contentsOf: cloudPremiumStickers.items.compactMap { item -> StickerPackItem? in guard let item = item.contents.get(RecentMediaItem.self) else {
return nil
}
return StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: 0), file: item.media, indexKeys: [])
})
}
}
if !premiumStickers.isEmpty {
var processedIds = Set<MediaId>()
for item in premiumStickers {
if isPremiumDisabled && item.file.isPremiumSticker {
continue
}
if processedIds.contains(item.file.fileId) {
continue
}
processedIds.insert(item.file.fileId)
let animationData = EntityKeyboardAnimationData(file: item.file)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: item.file,
subgroupId: nil,
icon: .none,
accentTint: false
)
let groupId = "premium"
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitlePremiumStickers, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, headerItem: nil, items: [resultItem]))
}
}
}
var avatarPeer: EnginePeer?
if let peerSpecificPack = peerSpecificPack {
avatarPeer = peerSpecificPack.peer
var processedIds = Set<MediaId>()
for item in peerSpecificPack.items {
if isPremiumDisabled && item.file.isPremiumSticker {
continue
}
if processedIds.contains(item.file.fileId) {
continue
}
processedIds.insert(item.file.fileId)
let animationData = EntityKeyboardAnimationData(file: item.file)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: item.file,
subgroupId: nil,
icon: .none,
accentTint: false
)
let groupId = "peerSpecific"
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: peerSpecificPack.peer.compactDisplayTitle, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, headerItem: nil, items: [resultItem]))
}
}
}
for entry in view.entries {
guard let item = entry.item as? StickerPackItem else {
continue
}
let animationData = EntityKeyboardAnimationData(file: item.file)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: item.file,
subgroupId: nil,
icon: .none,
accentTint: false
)
let groupId = entry.index.collectionId
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
var title = ""
var headerItem: EntityKeyboardAnimationData?
inner: for (id, info, _) in view.collectionInfos {
if id == groupId, let info = info as? StickerPackCollectionInfo {
title = info.title
if let thumbnail = info.thumbnail {
let type: EntityKeyboardAnimationData.ItemType
if item.file.isAnimatedSticker {
type = .lottie
} else if item.file.isVideoEmoji || item.file.isVideoSticker {
type = .video
} else {
type = .still
}
headerItem = EntityKeyboardAnimationData(
id: .stickerPackThumbnail(info.id),
type: type,
resource: .stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource),
dimensions: thumbnail.dimensions.cgSize,
immediateThumbnailData: info.immediateThumbnailData,
isReaction: false
)
}
break inner
}
}
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: title, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: true, headerItem: headerItem, items: [resultItem]))
}
}
for featuredStickerPack in featuredStickerPacks {
if installedCollectionIds.contains(featuredStickerPack.info.id) {
continue
}
for item in featuredStickerPack.topItems {
let animationData = EntityKeyboardAnimationData(file: item.file)
let resultItem = EmojiPagerContentComponent.Item(
animationData: animationData,
content: .animation(animationData),
itemFile: item.file,
subgroupId: nil,
icon: .none,
accentTint: false
)
let supergroupId = featuredStickerPack.info.id
let groupId: AnyHashable = supergroupId
let isPremiumLocked: Bool = item.file.isPremiumSticker && !hasPremium
if isPremiumLocked && isPremiumDisabled {
continue
}
if let groupIndex = itemGroupIndexById[groupId] {
itemGroups[groupIndex].items.append(resultItem)
} else {
itemGroupIndexById[groupId] = itemGroups.count
let subtitle: String = strings.StickerPack_StickerCount(Int32(featuredStickerPack.info.count))
var headerItem: EntityKeyboardAnimationData?
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 {
let info = featuredStickerPack.info
let type: EntityKeyboardAnimationData.ItemType
if item.file.isAnimatedSticker {
type = .lottie
} else if item.file.isVideoEmoji || item.file.isVideoSticker {
type = .video
} else {
type = .still
}
headerItem = EntityKeyboardAnimationData(
id: .stickerPackThumbnail(info.id),
type: type,
resource: .stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource),
dimensions: thumbnail.dimensions.cgSize,
immediateThumbnailData: info.immediateThumbnailData,
isReaction: false
)
}
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: featuredStickerPack.info.title, subtitle: subtitle, actionButtonTitle: strings.Stickers_Install, isPremiumLocked: isPremiumLocked, isFeatured: true, displayPremiumBadges: false, headerItem: headerItem, items: [resultItem]))
}
}
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
return EmojiPagerContentComponent(
id: "stickers",
context: context,
avatarPeer: avatarPeer,
animationCache: animationCache,
animationRenderer: animationRenderer,
inputInteractionHolder: EmojiPagerContentComponent.InputInteractionHolder(),
itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in
var hasClear = false
var isEmbedded = false
if group.id == AnyHashable("recent") {
hasClear = true
} else if group.id == AnyHashable("featuredTop") {
hasClear = true
isEmbedded = true
}
return EmojiPagerContentComponent.ItemGroup(
supergroupId: group.supergroupId,
groupId: group.id,
title: group.title,
subtitle: group.subtitle,
actionButtonTitle: group.actionButtonTitle,
isFeatured: group.isFeatured,
isPremiumLocked: group.isPremiumLocked,
isEmbedded: isEmbedded,
hasClear: hasClear,
collapsedLineCount: nil,
displayPremiumBadges: group.displayPremiumBadges,
headerItem: group.headerItem,
items: group.items
)
},
itemLayoutType: .detailed,
itemContentUniqueId: nil,
warpContentsOnEdges: false,
displaySearchWithPlaceholder: presentationData.strings.StickersSearch_SearchStickersPlaceholder,
searchInitiallyHidden: false,
searchIsPlaceholderOnly: true,
emptySearchResults: nil,
enableLongPress: false,
selectedItems: Set()
)
}
let stickerItems = EmojiPagerContentComponent.stickerInputData(context: context, animationCache: animationCache, animationRenderer: animationRenderer, stickerNamespaces: stickerNamespaces, stickerOrderedItemListCollectionIds: stickerOrderedItemListCollectionIds, chatPeerId: chatPeerId)
let reactions: Signal<[String], NoError> = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App())
|> map { appConfiguration -> [String] in