From 6c4070eb5290ae9eba3476f86fed4c5372fe71e9 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 14 Feb 2025 19:11:58 +0400 Subject: [PATCH] Serialization update --- .../Sources/AvatarVideoNode.swift | 6 +- .../Sources/ReactionImageComponent.swift | 4 +- .../ReactionListContextMenuContent.swift | 8 +- .../Sources/DebugController.swift | 15 +- .../Sources/DrawingReactionView.swift | 4 +- .../Sources/FeaturedStickersScreen.swift | 14 +- .../Sources/MediaInputPaneTrendingItem.swift | 15 +- .../Sources/ItemListStickerPackItem.swift | 13 +- .../Sources/AvatarEditorPreviewView.swift | 2 +- .../Postbox/Sources/ItemCollectionsView.swift | 32 +- .../PremiumUI/Sources/PremiumDemoScreen.swift | 18 +- .../PremiumUI/Sources/PremiumGiftScreen.swift | 2 +- .../Sources/PremiumIntroScreen.swift | 2 +- .../Sources/PremiumLimitsListScreen.swift | 38 +- .../Sources/ReactionContextNode.swift | 142 +++-- .../Sources/ReactionSelectionNode.swift | 28 +- .../Sources/ThemePickerGridItem.swift | 2 +- .../Sources/StickerPackEmojisItem.swift | 4 +- .../StickerPackPreviewController.swift | 7 +- .../StickerPackPreviewControllerNode.swift | 8 +- .../Sources/StickerPackPreviewGridItem.swift | 20 +- .../Sources/StickerPackScreen.swift | 16 +- .../StickerPreviewControllerNode.swift | 6 +- .../Sources/StickerResources.swift | 16 +- .../Sources/CallControllerNodeV2.swift | 2 +- .../Sources/PresentationCall.swift | 4 +- .../Network/FetchedMediaResource.swift | 51 +- .../Sources/State/AvailableReactions.swift | 159 ++++-- .../Sources/State/ManagedRecentStickers.swift | 6 +- ...onizeInstalledStickerPacksOperations.swift | 4 +- .../Sources/State/MessageReactions.swift | 2 +- .../State/SynchronizeSavedGifsOperation.swift | 2 +- .../SynchronizeSavedStickersOperation.swift | 6 +- .../SyncCore_CloudFileMediaResource.swift | 2 +- .../SyncCore/SyncCore_RecentMediaItem.swift | 58 +- .../SyncCore/SyncCore_SavedStickerItem.swift | 30 +- .../SyncCore/SyncCore_StickerPackItem.swift | 51 +- .../SyncCore/SyncCore_TelegramMediaFile.swift | 494 +++++++++++++++++- .../Stickers/SearchStickers.swift | 62 +-- .../StickerPackInteractiveOperations.swift | 3 +- .../Sources/AvatarEditorScreen.swift | 36 +- .../ChatEmptyNode/Sources/ChatEmptyNode.swift | 4 +- .../ChatMediaInputStickerGridItem.swift | 16 +- .../ChatMessageAnimatedStickerItemNode.swift | 8 +- .../ChatMessageDateAndStatusNode.swift | 2 +- ...hatMessageReactionsFooterContentNode.swift | 4 +- .../ChatMessageTextBubbleContentNode.swift | 4 +- .../Sources/ChatQrCodeScreen.swift | 4 +- .../Sources/ChatShareMessageTagView.swift | 4 +- .../Sources/ManagedDiceAnimationNode.swift | 2 +- .../Sources/TopMessageReactions.swift | 12 +- .../Sources/ChatEntityKeyboardInputNode.swift | 23 +- .../StickerPaneSearchContentNode.swift | 4 +- .../EmojiStatusSelectionComponent.swift | 95 ++-- .../Sources/EmojiSuggestionsComponent.swift | 19 +- .../Sources/EmojiKeyboardItemLayer.swift | 10 +- .../Sources/EmojiPagerContentComponent.swift | 52 +- .../Sources/EmojiPagerContentSignals.swift | 168 +++--- .../Sources/EmojiSearchContent.swift | 16 +- .../Sources/GifContext.swift | 2 +- .../Sources/GroupStickerPackCurrentItem.swift | 4 +- .../Sources/MediaEditorScreen.swift | 11 +- .../Sources/StickerPackListContextItem.swift | 5 +- .../MediaEditorScreen/Sources/Weather.swift | 2 +- .../Sources/InputContextQueries.swift | 4 +- .../Sources/EmojiListInputComponent.swift | 1 + .../Sources/PeerAllowedReactionsScreen.swift | 32 +- .../PeerInfoScreenLabeledValueItem.swift | 2 +- .../Sources/PeerInfoBirthdayOverlay.swift | 10 +- .../Sources/PeerInfoHeaderNode.swift | 2 +- .../Sources/BusinessIntroSetupScreen.swift | 11 +- .../Sources/ItemListReactionItem.swift | 4 +- .../Sources/ReactionChatPreviewItem.swift | 1 + .../Sources/ThemeCarouselItem.swift | 2 +- .../Sources/ThemeGridControllerNode.swift | 4 +- .../Sources/StickerPickerScreen.swift | 20 +- .../Sources/StoryChatContent.swift | 4 +- .../Sources/StoryItemOverlaysView.swift | 8 +- .../StoryItemSetContainerComponent.swift | 12 +- ...StoryItemSetContainerViewSendMessage.swift | 1 + .../StoryItemSetViewListComponent.swift | 4 +- .../Chat/ChatControllerLoadDisplayNode.swift | 1 + ...ChatControllerOpenMessageContextMenu.swift | 2 +- .../TelegramUI/Sources/ChatController.swift | 4 +- ...rollerOpenMessageReactionContextMenu.swift | 6 +- .../Sources/ChatHistoryListNode.swift | 1 + .../ChatInterfaceStateContextQueries.swift | 4 +- .../ChatSearchTitleAccessoryPanelNode.swift | 4 +- .../TelegramUI/Sources/ChatThemeScreen.swift | 2 +- ...rizontalStickersChatContextPanelNode.swift | 12 +- .../Sources/InlineReactionSearchPanel.swift | 18 +- .../TelegramUI/Sources/PrefetchManager.swift | 5 +- .../Sources/ExperimentalUISettings.swift | 6 - .../Sources/UndoOverlayControllerNode.swift | 13 +- .../Sources/WatchRequestHandlers.swift | 12 +- .../WebUI/Sources/WebAppController.swift | 2 +- .../WebAppEmojiStatusAlertController.swift | 10 +- third-party/webp/BUILD | 2 +- 98 files changed, 1332 insertions(+), 759 deletions(-) diff --git a/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift b/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift index 425a5f2b75..9cdfac6a64 100644 --- a/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift +++ b/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift @@ -100,12 +100,12 @@ public final class AvatarVideoNode: ASDisplayNode { } else { let itemNativeFitSize = self.internalSize.width > 100.0 ? CGSize(width: 192.0, height: 192.0) : CGSize(width: 64.0, height: 64.0) - let animationData = EntityKeyboardAnimationData(file: animationFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(animationFile)) let itemLayer = EmojiKeyboardItemLayer( item: EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: animationFile, + itemFile: TelegramMediaFile.Accessor(animationFile), subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none @@ -185,7 +185,7 @@ public final class AvatarVideoNode: ASDisplayNode { self.fileDisposable.set((self.context.engine.stickers.loadedStickerPack(reference: packReference, forceActualized: false) |> map { pack -> TelegramMediaFile? in if case let .result(_, items, _) = pack, let item = items.first(where: { $0.file.fileId.id == fileId }) { - return item.file + return item.file._parse() } return nil } diff --git a/submodules/Components/ReactionImageComponent/Sources/ReactionImageComponent.swift b/submodules/Components/ReactionImageComponent/Sources/ReactionImageComponent.swift index 659bc02ddf..9c4dc38f91 100644 --- a/submodules/Components/ReactionImageComponent/Sources/ReactionImageComponent.swift +++ b/submodules/Components/ReactionImageComponent/Sources/ReactionImageComponent.swift @@ -125,8 +125,8 @@ public final class ReactionImageNode: ASDisplayNode { if let availableReactions = availableReactions { for availableReaction in availableReactions.reactions { if availableReaction.value == reaction { - file = availableReaction.staticIcon - animationFile = availableReaction.centerAnimation + file = availableReaction.staticIcon._parse() + animationFile = availableReaction.centerAnimation?._parse() break } } diff --git a/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift b/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift index af576c9cd2..d6922664cd 100644 --- a/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift +++ b/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift @@ -149,7 +149,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent if let availableReactions = availableReactions { for availableReaction in availableReactions.reactions { if availableReaction.value == reaction { - self.file = availableReaction.centerAnimation + self.file = availableReaction.centerAnimation?._parse() self.updateReactionLayer() break } @@ -168,7 +168,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent if let availableReactions = availableReactions { for availableReaction in availableReactions.reactions { if availableReaction.value == reaction { - self.file = availableReaction.centerAnimation + self.file = availableReaction.centerAnimation?._parse() self.updateReactionLayer() break } @@ -567,7 +567,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent if let availableReactions = self.availableReactions { for availableReaction in availableReactions.reactions { if availableReaction.value == reaction { - self.file = availableReaction.centerAnimation + self.file = availableReaction.centerAnimation?._parse() self.updateReactionLayer() self.updateReactionAccentColor(theme: presentationData.theme) break @@ -588,7 +588,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent if let availableReactions = self.availableReactions { for availableReaction in availableReactions.reactions { if availableReaction.value == reaction { - self.file = availableReaction.centerAnimation + self.file = availableReaction.centerAnimation?._parse() self.updateReactionLayer() self.updateReactionAccentColor(theme: presentationData.theme) break diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index 9c945ab2be..bedb2ac608 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -134,7 +134,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return DebugControllerSection.web.rawValue case .keepChatNavigationStack, .skipReadHistory, .dustEffect, .crashOnSlowQueries, .crashOnMemoryPressure: return DebugControllerSection.experiments.rawValue - case .clearTips, .resetNotifications, .crash, .fillLocalSavedMessageCache, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .resetTagHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .storiesExperiment, .storiesJpegExperiment, .playlistPlayback, .enableQuickReactionSwitch, .experimentalCompatibility, .enableDebugDataDisplay, .rippleEffect, .browserExperiment, .localTranscription, .enableReactionOverrides, .restorePurchases, .disableReloginTokens, .liveStreamV2, .experimentalCallMute, .conferenceCalls, .playerV2, .devRequests, .fakeAds, .enableLocalTranslation: + case .clearTips, .resetNotifications, .crash, .fillLocalSavedMessageCache, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .resetTagHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .storiesExperiment, .storiesJpegExperiment, .playlistPlayback, .enableQuickReactionSwitch, .experimentalCompatibility, .enableDebugDataDisplay, .rippleEffect, .browserExperiment, .localTranscription, .enableReactionOverrides, .restorePurchases, .disableReloginTokens, .liveStreamV2, .experimentalCallMute, .playerV2, .devRequests, .fakeAds, .enableLocalTranslation: return DebugControllerSection.experiments.rawValue case .logTranslationRecognition, .resetTranslationStates: return DebugControllerSection.translation.rawValue @@ -251,8 +251,6 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 51 case .experimentalCallMute: return 52 - case .conferenceCalls: - return 53 case .playerV2: return 54 case .devRequests: @@ -1351,16 +1349,6 @@ private enum DebugControllerEntry: ItemListNodeEntry { }) }).start() }) - case let .conferenceCalls(value): - return ItemListSwitchItem(presentationData: presentationData, title: "Conference [WIP]", value: value, sectionId: self.section, style: .blocks, updated: { value in - let _ = arguments.sharedContext.accountManager.transaction ({ transaction in - transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in - var settings = settings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings - settings.conferenceCalls = value - return PreferencesEntry(settings) - }) - }).start() - }) case let .playerV2(value): return ItemListSwitchItem(presentationData: presentationData, title: "PlayerV2", value: value, sectionId: self.section, style: .blocks, updated: { value in let _ = arguments.sharedContext.accountManager.transaction ({ transaction in @@ -1558,7 +1546,6 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present entries.append(.liveStreamV2(experimentalSettings.liveStreamV2)) entries.append(.experimentalCallMute(experimentalSettings.experimentalCallMute)) - entries.append(.conferenceCalls(experimentalSettings.conferenceCalls)) entries.append(.playerV2(experimentalSettings.playerV2)) entries.append(.devRequests(experimentalSettings.devRequests)) diff --git a/submodules/DrawingUI/Sources/DrawingReactionView.swift b/submodules/DrawingUI/Sources/DrawingReactionView.swift index f74f56c512..e33a6da4b8 100644 --- a/submodules/DrawingUI/Sources/DrawingReactionView.swift +++ b/submodules/DrawingUI/Sources/DrawingReactionView.swift @@ -245,7 +245,7 @@ public class DrawingReactionEntityView: DrawingStickerEntityView { var animation: TelegramMediaFile? for reaction in availableReactions.reactions { if reaction.value == updateReaction.reaction { - animation = reaction.selectAnimation + animation = reaction.selectAnimation._parse() break } } @@ -274,7 +274,7 @@ public class DrawingReactionEntityView: DrawingStickerEntityView { var animation: TelegramMediaFile? for reaction in availableReactions.reactions { if reaction.value == updateReaction.reaction { - animation = reaction.selectAnimation + animation = reaction.selectAnimation._parse() break } } diff --git a/submodules/FeaturedStickersScreen/Sources/FeaturedStickersScreen.swift b/submodules/FeaturedStickersScreen/Sources/FeaturedStickersScreen.swift index 9dc397a850..32ccedd180 100644 --- a/submodules/FeaturedStickersScreen/Sources/FeaturedStickersScreen.swift +++ b/submodules/FeaturedStickersScreen/Sources/FeaturedStickersScreen.swift @@ -619,7 +619,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { menuItems = [ .action(ContextMenuActionItem(text: strongSelf.presentationData.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController, let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode.view, animationNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file._parse()), animationNode.view, animationNode.bounds) } f(.default) })), @@ -627,11 +627,11 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { f(.default) if let strongSelf = self { - let _ = (strongSelf.context.engine.stickers.toggleStickerSaved(file: item.file, saved: !isStarred) + let _ = (strongSelf.context.engine.stickers.toggleStickerSaved(file: item.file._parse(), saved: !isStarred) |> deliverOnMainQueue).start(next: { result in switch result { case .generic: - strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, loop: true, title: nil, text: !isStarred ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), with: nil) + strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file._parse(), loop: true, title: nil, text: !isStarred ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), with: nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) let text: String @@ -640,7 +640,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { } else { text = strongSelf.presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, loop: true, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in + strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file._parse(), loop: true, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -658,7 +658,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { f(.default) if let strongSelf = self { - loop: for attribute in item.file.attributes { + loop: for attribute in item.file._parse().attributes { switch attribute { case let .Sticker(_, packReference, _): if let packReference = packReference { @@ -692,7 +692,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { } })) ] - return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(context: strongSelf.context, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item.file), menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(context: strongSelf.context, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item.file._parse()), menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } @@ -1508,7 +1508,7 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode { return (itemNode, StickerPreviewPeekItem.found(stickerItem)) } else if let itemNode = itemNode as? StickerPaneSearchGlobalItemNode { if let (node, item) = itemNode.itemAt(point: self.view.convert(point, to: itemNode.view)) { - return (node, StickerPreviewPeekItem.pack(item.file)) + return (node, StickerPreviewPeekItem.pack(item.file._parse())) } } } diff --git a/submodules/FeaturedStickersScreen/Sources/MediaInputPaneTrendingItem.swift b/submodules/FeaturedStickersScreen/Sources/MediaInputPaneTrendingItem.swift index 5e45fc03fc..59228b5fff 100644 --- a/submodules/FeaturedStickersScreen/Sources/MediaInputPaneTrendingItem.swift +++ b/submodules/FeaturedStickersScreen/Sources/MediaInputPaneTrendingItem.swift @@ -112,7 +112,8 @@ final class TrendingTopItemNode: ASDisplayNode { } func setup(account: Account, item: StickerPackItem, itemSize: CGSize, synchronousLoads: Bool) { - self.file = item.file + let file = item.file._parse() + self.file = file self.itemSize = itemSize if item.file.isAnimatedSticker || item.file.isVideoSticker { @@ -134,23 +135,23 @@ final class TrendingTopItemNode: ASDisplayNode { let dimensions = item.file.dimensions ?? PixelDimensions(width: 512, height: 512) let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)) if item.file.isVideoSticker { - self.imageNode.setSignal(chatMessageSticker(postbox: account.postbox, userLocation: .other, file: item.file, small: false, synchronousLoad: synchronousLoads)) + self.imageNode.setSignal(chatMessageSticker(postbox: account.postbox, userLocation: .other, file: file, small: false, synchronousLoad: synchronousLoads)) } else { - self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: account.postbox, userLocation: .other, file: item.file, small: false, size: fittedDimensions, synchronousLoad: synchronousLoads), attemptSynchronously: synchronousLoads) + self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: account.postbox, userLocation: .other, file: file, small: false, size: fittedDimensions, synchronousLoad: synchronousLoads), attemptSynchronously: synchronousLoads) } animationNode.started = { [weak self] in self?.imageNode.alpha = 0.0 } - animationNode.setup(source: AnimatedStickerResourceSource(account: account, resource: item.file.resource, isVideo: item.file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .cached) - self.loadDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, userLocation: .other, fileReference: stickerPackFileReference(item.file), resource: item.file.resource).start()) + animationNode.setup(source: AnimatedStickerResourceSource(account: account, resource: file.resource, isVideo: file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .cached) + self.loadDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, userLocation: .other, fileReference: stickerPackFileReference(file), resource: file.resource).start()) } else { - self.imageNode.setSignal(chatMessageSticker(account: account, userLocation: .other, file: item.file, small: true, synchronousLoad: synchronousLoads), attemptSynchronously: synchronousLoads) + self.imageNode.setSignal(chatMessageSticker(account: account, userLocation: .other, file: file, small: true, synchronousLoad: synchronousLoads), attemptSynchronously: synchronousLoads) if let currentAnimationNode = self.animationNode { self.animationNode = nil currentAnimationNode.removeFromSupernode() } - self.loadDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, userLocation: .other, fileReference: stickerPackFileReference(item.file), resource: chatMessageStickerResource(file: item.file, small: true)).start()) + self.loadDisposable.set(freeMediaFileResourceInteractiveFetched(account: account, userLocation: .other, fileReference: stickerPackFileReference(file), resource: chatMessageStickerResource(file: file, small: true)).start()) } } diff --git a/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift b/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift index 8c7b1a1b83..55beb7bc22 100644 --- a/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift +++ b/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift @@ -495,12 +495,13 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { } resourceReference = MediaResourceReference.stickerPackThumbnail(stickerPack: .id(id: item.packInfo.id.id, accessHash: item.packInfo.accessHash), resource: thumbnail.resource) } else if let item = item.topItem { - if item.file.isAnimatedSticker || item.file.isVideoSticker { - thumbnailItem = .animated(item.file.resource, item.file.dimensions ?? PixelDimensions(width: 100, height: 100), item.file.isVideoSticker, item.file.isCustomTemplateEmoji) - resourceReference = MediaResourceReference.media(media: .standalone(media: item.file), resource: item.file.resource) - } else if let dimensions = item.file.dimensions, let resource = chatMessageStickerResource(file: item.file, small: true) as? TelegramMediaResource { + let itemFile = item.file._parse() + if itemFile.isAnimatedSticker || itemFile.isVideoSticker { + thumbnailItem = .animated(itemFile.resource, itemFile.dimensions ?? PixelDimensions(width: 100, height: 100), itemFile.isVideoSticker, itemFile.isCustomTemplateEmoji) + resourceReference = MediaResourceReference.media(media: .standalone(media: itemFile), resource: itemFile.resource) + } else if let dimensions = itemFile.dimensions, let resource = chatMessageStickerResource(file: itemFile, small: true) as? TelegramMediaResource { thumbnailItem = .still(TelegramMediaImageRepresentation(dimensions: dimensions, resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)) - resourceReference = MediaResourceReference.media(media: .standalone(media: item.file), resource: resource) + resourceReference = MediaResourceReference.media(media: .standalone(media: itemFile), resource: resource) } } @@ -848,7 +849,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { imageSize = PixelDimensions(width: 100, height: 100) } immediateThumbnailData = data - } else if let data = item.topItem?.file.immediateThumbnailData { + } else if let data = item.topItem?.file._parse().immediateThumbnailData { immediateThumbnailData = data } diff --git a/submodules/MediaPickerUI/Sources/AvatarEditorPreviewView.swift b/submodules/MediaPickerUI/Sources/AvatarEditorPreviewView.swift index f6650028f5..b65ab55594 100644 --- a/submodules/MediaPickerUI/Sources/AvatarEditorPreviewView.swift +++ b/submodules/MediaPickerUI/Sources/AvatarEditorPreviewView.swift @@ -48,7 +48,7 @@ final class AvatarEditorPreviewView: UIView { var files: [TelegramMediaFile] = [] for item in view.items.prefix(8) { if let mediaItem = item.contents.get(RecentMediaItem.self) { - let file = mediaItem.media + let file = mediaItem.media._parse() files.append(file) self.preloadDisposableSet.add(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) diff --git a/submodules/Postbox/Sources/ItemCollectionsView.swift b/submodules/Postbox/Sources/ItemCollectionsView.swift index ffae1c60f2..1c6c6bfee3 100644 --- a/submodules/Postbox/Sources/ItemCollectionsView.swift +++ b/submodules/Postbox/Sources/ItemCollectionsView.swift @@ -42,19 +42,9 @@ public struct ItemCollectionViewEntry { } } -public struct RawItemCollectionViewEntry { - public let index: ItemCollectionViewEntryIndex - public let data: Data +private func fetchLowerEntries(namespaces: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, collectionIndex: Int32, itemIndex: ItemCollectionItemIndex, count: Int, lowerCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, lowerItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> [ItemCollectionViewEntry] { - public init(index: ItemCollectionViewEntryIndex, data: Data) { - self.index = index - self.data = data - } -} - -private func fetchLowerEntries(namespaces: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, collectionIndex: Int32, itemIndex: ItemCollectionItemIndex, count: Int, lowerCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, lowerItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> [RawItemCollectionViewEntry] { - - var entries: [RawItemCollectionViewEntry] = [] + var entries: [ItemCollectionViewEntry] = [] var currentCollectionIndex = collectionIndex var currentCollectionId = collectionId @@ -85,9 +75,9 @@ private func fetchLowerEntries(namespaces: [ItemCollectionId.Namespace], collect return entries } -private func fetchHigherEntries(namespaces: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, collectionIndex: Int32, itemIndex: ItemCollectionItemIndex, count: Int, higherCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, higherItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> [RawItemCollectionViewEntry] { +private func fetchHigherEntries(namespaces: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, collectionIndex: Int32, itemIndex: ItemCollectionItemIndex, count: Int, higherCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, higherItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> [ItemCollectionViewEntry] { - var entries: [RawItemCollectionViewEntry] = [] + var entries: [ItemCollectionViewEntry] = [] var currentCollectionIndex = collectionIndex var currentCollectionId = collectionId @@ -125,11 +115,11 @@ private func aroundEntries(namespaces: [ItemCollectionId.Namespace], lowerCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, fetchLowerItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem], higherCollectionId: (_ namespaceList: [ItemCollectionId.Namespace], _ collectionId: ItemCollectionId, _ collectionIndex: Int32) -> (ItemCollectionId, Int32)?, - fetchHigherItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> ([RawItemCollectionViewEntry], RawItemCollectionViewEntry?, RawItemCollectionViewEntry?) { - var lowerEntries: [RawItemCollectionViewEntry] = [] - var upperEntries: [RawItemCollectionViewEntry] = [] - var lower: RawItemCollectionViewEntry? - var upper: RawItemCollectionViewEntry? + fetchHigherItems: (_ collectionId: ItemCollectionId, _ itemIndex: ItemCollectionItemIndex, _ count: Int) -> [ItemCollectionItem]) -> ([ItemCollectionViewEntry], ItemCollectionViewEntry?, ItemCollectionViewEntry?) { + var lowerEntries: [ItemCollectionViewEntry] = [] + var upperEntries: [ItemCollectionViewEntry] = [] + var lower: ItemCollectionViewEntry? + var upper: ItemCollectionViewEntry? let selectedAroundIndex: ItemCollectionViewEntryIndex if let aroundIndex = aroundIndex, let aroundCollectionIndex = collectionIndexById(aroundIndex.collectionId) { @@ -163,7 +153,7 @@ private func aroundEntries(namespaces: [ItemCollectionId.Namespace], } if lowerEntries.count != 0 && lowerEntries.count + upperEntries.count < count { - var additionalLowerEntries: [RawItemCollectionViewEntry] = fetchLowerEntries(namespaces: namespaces, collectionId: lowerEntries.last!.index.collectionId, collectionIndex: lowerEntries.last!.index.collectionIndex, itemIndex: lowerEntries.last!.index.itemIndex, count: count - lowerEntries.count - upperEntries.count + 1, lowerCollectionId: lowerCollectionId, lowerItems: fetchLowerItems) + var additionalLowerEntries: [ItemCollectionViewEntry] = fetchLowerEntries(namespaces: namespaces, collectionId: lowerEntries.last!.index.collectionId, collectionIndex: lowerEntries.last!.index.collectionIndex, itemIndex: lowerEntries.last!.index.itemIndex, count: count - lowerEntries.count - upperEntries.count + 1, lowerCollectionId: lowerCollectionId, lowerItems: fetchLowerItems) if additionalLowerEntries.count >= count - lowerEntries.count + upperEntries.count + 1 { lower = additionalLowerEntries.last @@ -172,7 +162,7 @@ private func aroundEntries(namespaces: [ItemCollectionId.Namespace], lowerEntries.append(contentsOf: additionalLowerEntries) } - var entries: [RawItemCollectionViewEntry] = [] + var entries: [ItemCollectionViewEntry] = [] entries.append(contentsOf: lowerEntries.reversed()) entries.append(contentsOf: upperEntries) return (entries: entries, lower: lower, upper: upper) diff --git a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift index cee87200d2..b488cd4d3b 100644 --- a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift @@ -607,14 +607,14 @@ private final class DemoSheetContent: CombinedComponent { if let items = items { for item in items { if let mediaItem = item.contents.get(RecentMediaItem.self) { - result.append(mediaItem.media) + result.append(mediaItem.media._parse()) } } } return (reactions.reactions.filter({ $0.isPremium }).map { reaction -> AvailableReactions.Reaction in var aroundAnimation = reaction.aroundAnimation if let replacementFile = reactionOverrides[reaction.value] { - aroundAnimation = replacementFile + aroundAnimation = TelegramMediaFile.Accessor(replacementFile) } return AvailableReactions.Reaction( @@ -622,13 +622,13 @@ private final class DemoSheetContent: CombinedComponent { isPremium: reaction.isPremium, value: reaction.value, title: reaction.title, - staticIcon: reaction.staticIcon, - appearAnimation: reaction.appearAnimation, - selectAnimation: reaction.selectAnimation, - activateAnimation: reaction.activateAnimation, - effectAnimation: reaction.effectAnimation, - aroundAnimation: aroundAnimation, - centerAnimation: reaction.centerAnimation + staticIcon: reaction.staticIcon._parse(), + appearAnimation: reaction.appearAnimation._parse(), + selectAnimation: reaction.selectAnimation._parse(), + activateAnimation: reaction.activateAnimation._parse(), + effectAnimation: reaction.effectAnimation._parse(), + aroundAnimation: aroundAnimation?._parse(), + centerAnimation: reaction.centerAnimation?._parse() ) }, result.map { file -> TelegramMediaFile in for attribute in file.attributes { diff --git a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index 6d377a0795..99de9f72af 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -163,7 +163,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { if let view = views.views[stickersKey] as? OrderedItemListView { for item in view.items { if let mediaItem = item.contents.get(RecentMediaItem.self) { - let file = mediaItem.media + let file = mediaItem.media._parse() strongSelf.preloadDisposableSet.add(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) if let effect = file.videoThumbnails.first { strongSelf.preloadDisposableSet.add(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: .standalone(media: file), resource: effect.resource).start()) diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 83b6a6eb2f..4b4d8d2593 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -1577,7 +1577,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { if let view = views.views[stickersKey] as? OrderedItemListView { for item in view.items { if let mediaItem = item.contents.get(RecentMediaItem.self) { - let file = mediaItem.media + let file = mediaItem.media._parse() strongSelf.preloadDisposableSet.add(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start()) if let effect = file.videoThumbnails.first { strongSelf.preloadDisposableSet.add(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: .standalone(media: file), resource: effect.resource).start()) diff --git a/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift b/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift index 77609c80f6..5fd01d8666 100644 --- a/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift @@ -135,7 +135,7 @@ public class PremiumLimitsListScreen: ViewController { } } - var result: [TelegramMediaFile] = [] + var result: [TelegramMediaFile.Accessor] = [] if let items = items { for item in items { if let mediaItem = item.contents.get(RecentMediaItem.self) { @@ -144,26 +144,22 @@ public class PremiumLimitsListScreen: ViewController { } } return (result.map { file -> TelegramMediaFile in - for attribute in file.attributes { - switch attribute { - case let .Sticker(displayText, _, _): - if let replacementFile = stickerOverrides[.builtin(displayText)], let dimensions = replacementFile.dimensions { - let _ = dimensions - return TelegramMediaFile( - fileId: file.fileId, - partialReference: file.partialReference, - resource: file.resource, - previewRepresentations: file.previewRepresentations, - videoThumbnails: [TelegramMediaFile.VideoThumbnail(dimensions: dimensions, resource: replacementFile.resource)], - immediateThumbnailData: file.immediateThumbnailData, - mimeType: file.mimeType, - size: file.size, - attributes: file.attributes, - alternativeRepresentations: file.alternativeRepresentations - ) - } - default: - break + let file = file._parse() + if let displayText = TelegramMediaFile.Accessor(file).stickerDisplayText { + if let replacementFile = stickerOverrides[.builtin(displayText)], let dimensions = replacementFile.dimensions { + let _ = dimensions + return TelegramMediaFile( + fileId: file.fileId, + partialReference: file.partialReference, + resource: file.resource, + previewRepresentations: file.previewRepresentations, + videoThumbnails: [TelegramMediaFile.VideoThumbnail(dimensions: dimensions, resource: replacementFile.resource)], + immediateThumbnailData: file.immediateThumbnailData, + mimeType: file.mimeType, + size: file.size, + attributes: file.attributes, + alternativeRepresentations: file.alternativeRepresentations + ) } } return file diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index 8d7d08e591..03f86e7a05 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -36,22 +36,22 @@ public final class ReactionItem { } public let reaction: ReactionItem.Reaction - public let appearAnimation: TelegramMediaFile - public let stillAnimation: TelegramMediaFile - public let listAnimation: TelegramMediaFile - public let largeListAnimation: TelegramMediaFile - public let applicationAnimation: TelegramMediaFile? - public let largeApplicationAnimation: TelegramMediaFile? + public let appearAnimation: TelegramMediaFile.Accessor + public let stillAnimation: TelegramMediaFile.Accessor + public let listAnimation: TelegramMediaFile.Accessor + public let largeListAnimation: TelegramMediaFile.Accessor + public let applicationAnimation: TelegramMediaFile.Accessor? + public let largeApplicationAnimation: TelegramMediaFile.Accessor? public let isCustom: Bool public init( reaction: ReactionItem.Reaction, - appearAnimation: TelegramMediaFile, - stillAnimation: TelegramMediaFile, - listAnimation: TelegramMediaFile, - largeListAnimation: TelegramMediaFile, - applicationAnimation: TelegramMediaFile?, - largeApplicationAnimation: TelegramMediaFile?, + appearAnimation: TelegramMediaFile.Accessor, + stillAnimation: TelegramMediaFile.Accessor, + listAnimation: TelegramMediaFile.Accessor, + largeListAnimation: TelegramMediaFile.Accessor, + applicationAnimation: TelegramMediaFile.Accessor?, + largeApplicationAnimation: TelegramMediaFile.Accessor?, isCustom: Bool ) { self.reaction = reaction @@ -69,7 +69,7 @@ public final class ReactionItem { case let .builtin(value): return .builtin(value) case let .custom(fileId): - return .custom(fileId: fileId, file: self.listAnimation) + return .custom(fileId: fileId, file: self.listAnimation._parse()) case .stars: return .stars } @@ -455,21 +455,18 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { public static func randomGenericReactionEffect(context: AccountContext) -> Signal { return context.engine.stickers.loadedStickerPack(reference: .emojiGenericAnimations, forceActualized: false) - |> map { result -> [TelegramMediaFile]? in + |> map { result -> TelegramMediaFile? in switch result { case let .result(_, items, _): - return items.map(\.file) + return items.randomElement()?.file._parse() default: return nil } } |> filter { $0 != nil } |> take(1) - |> mapToSignal { items -> Signal in - guard let items = items else { - return .single(nil) - } - guard let file = items.randomElement() else { + |> mapToSignal { file -> Signal in + guard let file else { return .single(nil) } return Signal { subscriber in @@ -643,14 +640,9 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { let filterList: [String] = ["😖", "😫", "🫠", "😨", "❓"] for featuredEmojiPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { for item in featuredEmojiPack.topItems { - for attribute in item.file.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - if filterList.contains(alt) { - filteredFiles.append(item.file) - } - default: - break + if let alt = item.file.customEmojiAlt { + if filterList.contains(alt) { + filteredFiles.append(item.file._parse()) } } } @@ -1687,9 +1679,9 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { ) if case .locked = item.icon { - strongSelf.premiumReactionsSelected?(reactionItem.stillAnimation) + strongSelf.premiumReactionsSelected?(reactionItem.stillAnimation._parse()) } else if strongSelf.reactionsLocked { - strongSelf.premiumReactionsSelected?(reactionItem.stillAnimation) + strongSelf.premiumReactionsSelected?(reactionItem.stillAnimation._parse()) } else { strongSelf.customReactionSource = (sourceView, sourceRect, sourceLayer, reactionItem) strongSelf.reactionSelected?(updateReaction, isLongPress) @@ -1711,9 +1703,9 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { ) strongSelf.customReactionSource = (sourceView, sourceRect, sourceLayer, reactionItem) if case .locked = item.icon { - strongSelf.premiumReactionsSelected?(reactionItem.stillAnimation) + strongSelf.premiumReactionsSelected?(reactionItem.stillAnimation._parse()) } else if strongSelf.reactionsLocked { - strongSelf.premiumReactionsSelected?(reactionItem.stillAnimation) + strongSelf.premiumReactionsSelected?(reactionItem.stillAnimation._parse()) } else { strongSelf.reactionSelected?(reactionItem.updateMessageReaction, isLongPress) } @@ -1925,11 +1917,11 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { } } - let animationData = EntityKeyboardAnimationData(file: itemFile, partialReference: .none) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile), partialReference: .none) let resultItem = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, + itemFile: TelegramMediaFile.Accessor(itemFile), subgroupId: nil, icon: icon, tintMode: tintMode @@ -2037,7 +2029,7 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { localPacksSignal ) |> map { view, availableReactions, hasPremium, foundPacks, foundEmoji, foundLocalPacks -> [EmojiPagerContentComponent.ItemGroup] in - var result: [(String, TelegramMediaFile?, String)] = [] + var result: [(String, TelegramMediaFile.Accessor?, String)] = [] var allEmoticons: [String: String] = [:] for keyword in keywords { @@ -2051,9 +2043,9 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { switch attribute { case let .CustomEmoji(_, _, alt, _): if !alt.isEmpty, let keyword = allEmoticons[alt] { - result.append((alt, itemFile, keyword)) + result.append((alt, TelegramMediaFile.Accessor(itemFile), keyword)) } else if alt == query { - result.append((alt, itemFile, alt)) + result.append((alt, TelegramMediaFile.Accessor(itemFile), alt)) } default: break @@ -2065,18 +2057,13 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { guard let item = entry.item as? StickerPackItem else { continue } - for attribute in item.file.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - if !item.file.isPremiumEmoji { - if !alt.isEmpty, let keyword = allEmoticons[alt] { - result.append((alt, item.file, keyword)) - } else if alt == query { - result.append((alt, item.file, alt)) - } + if !item.file.isPremiumEmoji { + if let alt = item.file.customEmojiAlt { + if !alt.isEmpty, let keyword = allEmoticons[alt] { + result.append((alt, item.file, keyword)) + } else if alt == query { + result.append((alt, item.file, alt)) } - default: - break } } } @@ -2294,11 +2281,11 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { } } - let animationData = EntityKeyboardAnimationData(file: itemFile, partialReference: .none) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile), partialReference: .none) let resultItem = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, + itemFile: TelegramMediaFile.Accessor(itemFile), subgroupId: nil, icon: icon, tintMode: tintMode @@ -2351,11 +2338,12 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { continue } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, subgroupId: nil, + itemFile: TelegramMediaFile.Accessor(itemFile), + subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none ) @@ -2729,25 +2717,20 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { let additionalAnimationNode: DefaultAnimatedStickerNodeImpl? var genericAnimationView: AnimationView? - var additionalAnimation: TelegramMediaFile? + var additionalAnimation: TelegramMediaFile.Accessor? if self.didTriggerExpandedReaction { additionalAnimation = itemNode.item.largeApplicationAnimation } else { additionalAnimation = itemNode.item.applicationAnimation if additionalAnimation == nil && itemNode.item.isCustom { - outer: for attribute in itemNode.item.stillAnimation.attributes { - if case let .CustomEmoji(_, _, alt, _) = attribute { - if let availableReactions = self.availableReactions { - for availableReaction in availableReactions.reactions { - if availableReaction.value == .builtin(alt) { - additionalAnimation = availableReaction.aroundAnimation - break outer - } + if let alt = itemNode.item.stillAnimation.customEmojiAlt { + if let availableReactions = self.availableReactions { + for availableReaction in availableReactions.reactions { + if availableReaction.value == .builtin(alt) { + additionalAnimation = availableReaction.aroundAnimation } } - - break } } } @@ -2762,7 +2745,8 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { } } - additionalAnimationNodeValue.setup(source: AnimatedStickerResourceSource(account: itemNode.context.account, resource: additionalAnimation.resource), width: Int(effectFrame.width * 2.0), height: Int(effectFrame.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(additionalAnimation.resource.id))) + let additionalAnimationFile = additionalAnimation._parse() + additionalAnimationNodeValue.setup(source: AnimatedStickerResourceSource(account: itemNode.context.account, resource: additionalAnimationFile.resource), width: Int(effectFrame.width * 2.0), height: Int(effectFrame.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(additionalAnimationFile.resource.id))) additionalAnimationNodeValue.frame = effectFrame additionalAnimationNodeValue.updateLayout(size: effectFrame.size) self.addSubnode(additionalAnimationNodeValue) @@ -2799,13 +2783,14 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { for i in 1 ... 32 { let allLayers = view.allLayers(forKeypath: AnimationKeypath(keypath: "placeholder_\(i)")) + let itemNodeListAnimationFile = itemNode.item.listAnimation._parse() for animationLayer in allLayers { let baseItemLayer = InlineStickerItemLayer( context: itemNode.context, userLocation: .other, attemptSynchronousLoad: false, - emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: itemNode.item.listAnimation.fileId.id, file: itemNode.item.listAnimation), - file: itemNode.item.listAnimation, + emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: itemNode.item.listAnimation.fileId.id, file: itemNodeListAnimationFile), + file: itemNodeListAnimationFile, cache: animationCache, renderer: animationRenderer, placeholderColor: UIColor(white: 0.0, alpha: 0.0), @@ -3083,11 +3068,11 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { switch reaction { case let .reaction(reactionItem, icon): if case .custom = reactionItem.updateMessageReaction, let hasPremium = self.hasPremium, !hasPremium, !self.allPresetReactionsAreAvailable { - self.premiumReactionsSelected?(reactionItem.stillAnimation) + self.premiumReactionsSelected?(reactionItem.stillAnimation._parse()) } else if self.reactionsLocked { - self.premiumReactionsSelected?(reactionItem.stillAnimation) + self.premiumReactionsSelected?(reactionItem.stillAnimation._parse()) } else if case .locked = icon { - self.premiumReactionsSelected?(reactionItem.stillAnimation) + self.premiumReactionsSelected?(reactionItem.stillAnimation._parse()) } else { self.reactionSelected?(reactionItem.updateMessageReaction, false) } @@ -3274,9 +3259,9 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { for (_, itemNode) in self.visibleItemNodes { if let itemNode = itemNode as? ReactionNode, itemNode.item.reaction == reaction { if case .custom = itemNode.item.updateMessageReaction, let hasPremium = self.hasPremium, !hasPremium { - self.premiumReactionsSelected?(itemNode.item.stillAnimation) + self.premiumReactionsSelected?(itemNode.item.stillAnimation._parse()) } else if self.reactionsLocked { - self.premiumReactionsSelected?(itemNode.item.stillAnimation) + self.premiumReactionsSelected?(itemNode.item.stillAnimation._parse()) } else { self.reactionSelected?(itemNode.item.updateMessageReaction, isLarge) } @@ -3450,11 +3435,11 @@ public final class StandaloneReactionAnimation: ASDisplayNode { var additionalAnimationResource: MediaResource? if isLarge && !forceSmallEffectAnimation { - additionalAnimationResource = reaction.largeApplicationAnimation?.resource + additionalAnimationResource = reaction.largeApplicationAnimation?._parse().resource } else if case .stars = reaction.reaction.rawValue { - additionalAnimationResource = reaction.largeApplicationAnimation?.resource ?? reaction.applicationAnimation?.resource + additionalAnimationResource = reaction.largeApplicationAnimation?._parse().resource ?? reaction.applicationAnimation?._parse().resource } else { - additionalAnimationResource = reaction.applicationAnimation?.resource + additionalAnimationResource = reaction.applicationAnimation?._parse().resource } if additionalAnimationResource == nil, let customEffectResource { additionalAnimationResource = customEffectResource @@ -3540,12 +3525,13 @@ public final class StandaloneReactionAnimation: ASDisplayNode { for i in 1 ... 7 { let allLayers = view.allLayers(forKeypath: AnimationKeypath(keypath: "placeholder_\(i)")) for animationLayer in allLayers { + let itemListAnimationFile = reaction.listAnimation._parse() let baseItemLayer = InlineStickerItemLayer( context: context, userLocation: .other, attemptSynchronousLoad: false, - emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: reaction.listAnimation.fileId.id, file: reaction.listAnimation), - file: reaction.listAnimation, + emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: reaction.listAnimation.fileId.id, file: itemListAnimationFile), + file: itemListAnimationFile, cache: animationCache, renderer: animationRenderer, placeholderColor: UIColor(white: 0.0, alpha: 0.0), @@ -3898,9 +3884,9 @@ public final class StandaloneReactionAnimation: ASDisplayNode { var additionalAnimation: TelegramMediaFile? if didTriggerExpandedReaction { - additionalAnimation = item.largeApplicationAnimation + additionalAnimation = item.largeApplicationAnimation?._parse() } else { - additionalAnimation = item.applicationAnimation + additionalAnimation = item.applicationAnimation?._parse() } if let additionalAnimation = additionalAnimation { diff --git a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift index b58c216f43..bc4ae9b5e8 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift @@ -238,11 +238,11 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode { strongSelf.animateInAnimationNode = nil } - self.fetchStickerDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: .standalone(resource: item.appearAnimation.resource)).start() - self.fetchStickerDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: .standalone(resource: item.stillAnimation.resource)).start() - self.fetchStickerDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: .standalone(resource: item.listAnimation.resource)).start() + self.fetchStickerDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: .standalone(resource: item.appearAnimation._parse().resource)).start() + self.fetchStickerDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: .standalone(resource: item.stillAnimation._parse().resource)).start() + self.fetchStickerDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: .standalone(resource: item.listAnimation._parse().resource)).start() if let applicationAnimation = item.applicationAnimation { - self.fetchFullAnimationDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: .standalone(resource: applicationAnimation.resource)).start() + self.fetchFullAnimationDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: .standalone(resource: applicationAnimation._parse().resource)).start() } if self.isLocked { @@ -357,12 +357,12 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode { } if largeExpanded { - let source = AnimatedStickerResourceSource(account: self.context.account, resource: self.item.largeListAnimation.resource, isVideo: self.item.largeListAnimation.isVideoSticker || self.item.largeListAnimation.isVideoEmoji || self.item.largeListAnimation.isStaticSticker || self.item.largeListAnimation.isStaticEmoji) + let source = AnimatedStickerResourceSource(account: self.context.account, resource: self.item.largeListAnimation._parse().resource, isVideo: self.item.largeListAnimation.isVideoSticker || self.item.largeListAnimation.isVideoEmoji || self.item.largeListAnimation.isStaticSticker || self.item.largeListAnimation.isStaticEmoji) - animationNode.setup(source: source, width: Int(expandedAnimationFrame.width * 2.0), height: Int(expandedAnimationFrame.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.largeListAnimation.resource.id))) + animationNode.setup(source: source, width: Int(expandedAnimationFrame.width * 2.0), height: Int(expandedAnimationFrame.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.largeListAnimation._parse().resource.id))) } else { - let source = AnimatedStickerResourceSource(account: self.context.account, resource: self.item.listAnimation.resource, isVideo: self.item.listAnimation.isVideoSticker || self.item.listAnimation.isVideoEmoji || self.item.listAnimation.isVideoSticker || self.item.listAnimation.isStaticSticker || self.item.listAnimation.isStaticEmoji) - animationNode.setup(source: source, width: Int(expandedAnimationFrame.width * 2.0), height: Int(expandedAnimationFrame.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.listAnimation.resource.id))) + let source = AnimatedStickerResourceSource(account: self.context.account, resource: self.item.listAnimation._parse().resource, isVideo: self.item.listAnimation.isVideoSticker || self.item.listAnimation.isVideoEmoji || self.item.listAnimation.isVideoSticker || self.item.listAnimation.isStaticSticker || self.item.listAnimation.isStaticEmoji) + animationNode.setup(source: source, width: Int(expandedAnimationFrame.width * 2.0), height: Int(expandedAnimationFrame.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.listAnimation._parse().resource.id))) } animationNode.frame = expandedAnimationFrame animationNode.updateLayout(size: expandedAnimationFrame.size) @@ -446,7 +446,7 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode { self.stillAnimationNode = stillAnimationNode self.addSubnode(stillAnimationNode) - stillAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation.resource, isVideo: self.item.stillAnimation.isVideoEmoji || self.item.stillAnimation.isVideoSticker || self.item.stillAnimation.isStaticSticker || self.item.stillAnimation.isStaticEmoji), width: Int(animationDisplaySize.width * 2.0), height: Int(animationDisplaySize.height * 2.0), playbackMode: self.loopIdle ? .loop : .still(.start), mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation.resource.id))) + stillAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation._parse().resource, isVideo: self.item.stillAnimation.isVideoEmoji || self.item.stillAnimation.isVideoSticker || self.item.stillAnimation.isStaticSticker || self.item.stillAnimation.isStaticEmoji), width: Int(animationDisplaySize.width * 2.0), height: Int(animationDisplaySize.height * 2.0), playbackMode: self.loopIdle ? .loop : .still(.start), mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation._parse().resource.id))) stillAnimationNode.position = animationFrame.center stillAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size) stillAnimationNode.updateLayout(size: animationFrame.size) @@ -504,9 +504,9 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode { let staticFile: TelegramMediaFile if !self.hasAppearAnimation { - staticFile = self.item.largeListAnimation + staticFile = self.item.largeListAnimation._parse() } else { - staticFile = self.item.stillAnimation + staticFile = self.item.stillAnimation._parse() } if self.staticAnimationPlaceholderView == nil, let immediateThumbnailData = staticFile.immediateThumbnailData { @@ -531,9 +531,9 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode { self.staticAnimationNode.automaticallyLoadFirstFrame = true if !self.hasAppearAnimation { - self.staticAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.largeListAnimation.resource, isVideo: self.item.largeListAnimation.isVideoEmoji || self.item.largeListAnimation.isVideoSticker || self.item.largeListAnimation.isStaticSticker || self.item.largeListAnimation.isStaticEmoji), width: Int(expandedAnimationFrame.width * 2.0), height: Int(expandedAnimationFrame.height * 2.0), playbackMode: .still(.start), mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.largeListAnimation.resource.id))) + self.staticAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.largeListAnimation._parse().resource, isVideo: self.item.largeListAnimation.isVideoEmoji || self.item.largeListAnimation.isVideoSticker || self.item.largeListAnimation.isStaticSticker || self.item.largeListAnimation.isStaticEmoji), width: Int(expandedAnimationFrame.width * 2.0), height: Int(expandedAnimationFrame.height * 2.0), playbackMode: .still(.start), mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.largeListAnimation._parse().resource.id))) } else { - self.staticAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation.resource, isVideo: self.item.stillAnimation.isVideoEmoji || self.item.stillAnimation.isVideoSticker || self.item.stillAnimation.isStaticSticker || self.item.stillAnimation.isStaticEmoji), width: Int(animationDisplaySize.width * 2.0), height: Int(animationDisplaySize.height * 2.0), playbackMode: .still(.start), mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation.resource.id))) + self.staticAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.stillAnimation._parse().resource, isVideo: self.item.stillAnimation.isVideoEmoji || self.item.stillAnimation.isVideoSticker || self.item.stillAnimation.isStaticSticker || self.item.stillAnimation.isStaticEmoji), width: Int(animationDisplaySize.width * 2.0), height: Int(animationDisplaySize.height * 2.0), playbackMode: .still(.start), mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.stillAnimation._parse().resource.id))) } self.staticAnimationNode.position = animationFrame.center self.staticAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size) @@ -546,7 +546,7 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode { } if let animateInAnimationNode = self.animateInAnimationNode { - animateInAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.appearAnimation.resource, isVideo: self.item.appearAnimation.isVideoEmoji || self.item.appearAnimation.isVideoSticker || self.item.appearAnimation.isStaticSticker || self.item.appearAnimation.isStaticEmoji), width: Int(animationDisplaySize.width * 2.0), height: Int(animationDisplaySize.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.appearAnimation.resource.id))) + animateInAnimationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: self.item.appearAnimation._parse().resource, isVideo: self.item.appearAnimation.isVideoEmoji || self.item.appearAnimation.isVideoSticker || self.item.appearAnimation.isStaticSticker || self.item.appearAnimation.isStaticEmoji), width: Int(animationDisplaySize.width * 2.0), height: Int(animationDisplaySize.height * 2.0), playbackMode: .once, mode: .direct(cachePathPrefix: self.context.account.postbox.mediaBox.shortLivedResourceCachePathPrefix(self.item.appearAnimation._parse().resource.id))) animateInAnimationNode.position = animationFrame.center animateInAnimationNode.bounds = CGRect(origin: CGPoint(), size: animationFrame.size) animateInAnimationNode.updateLayout(size: animationFrame.size) diff --git a/submodules/SettingsUI/Sources/ThemePickerGridItem.swift b/submodules/SettingsUI/Sources/ThemePickerGridItem.swift index 96485c5eb6..5504d02664 100644 --- a/submodules/SettingsUI/Sources/ThemePickerGridItem.swift +++ b/submodules/SettingsUI/Sources/ThemePickerGridItem.swift @@ -505,7 +505,7 @@ class ThemeGridThemeItemNode: ListViewItemNode, ItemListItemNode { for theme in item.themes { let selected = item.currentTheme.index == theme.index - let iconItem = ThemeCarouselThemeIconItem(context: item.context, emojiFile: theme.emoticon.flatMap { item.animatedEmojiStickers[$0]?.first?.file }, themeReference: theme, nightMode: item.nightMode, channelMode: false, themeSpecificAccentColors: item.themeSpecificAccentColors, themeSpecificChatWallpapers: item.themeSpecificChatWallpapers, selected: selected, theme: item.theme, strings: item.strings, wallpaper: nil, action: { theme in + let iconItem = ThemeCarouselThemeIconItem(context: item.context, emojiFile: theme.emoticon.flatMap { item.animatedEmojiStickers[$0]?.first?.file._parse() }, themeReference: theme, nightMode: item.nightMode, channelMode: false, themeSpecificAccentColors: item.themeSpecificAccentColors, themeSpecificChatWallpapers: item.themeSpecificChatWallpapers, selected: selected, theme: item.theme, strings: item.strings, wallpaper: nil, action: { theme in if let theme { item.updatedTheme(theme) } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift index 1d50c9f753..62b02b164a 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift @@ -200,7 +200,7 @@ final class StickerPackEmojisItemNode: GridItemNode { itemId: .animation(.file(file.fileId)) ) if let itemLayer = self.visibleItemLayers[itemId] { - return (file, itemLayer) + return (file._parse(), itemLayer) } } return nil @@ -209,7 +209,7 @@ final class StickerPackEmojisItemNode: GridItemNode { @objc private func tapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) { switch recognizer.state { case .ended: - if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation, let (item, _) = self.item(atPoint: location), let file = item.itemFile { + if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation, let (item, _) = self.item(atPoint: location), let file = item.itemFile?._parse() { if case .tap = gesture { var text = "." var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift index 8acbcb2030..41d2a1e7e2 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift @@ -218,11 +218,12 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese let topItems = items.prefix(16) for item in topItems { if item.file.isAnimatedSticker { + let itemFile = item.file._parse() let signal = Signal { subscriber in - let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: FileMediaReference.standalone(media: item.file).resourceReference(item.file.resource)).start() - let data = account.postbox.mediaBox.resourceData(item.file.resource).start() + let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: FileMediaReference.standalone(media: itemFile).resourceReference(itemFile.resource)).start() + let data = account.postbox.mediaBox.resourceData(itemFile.resource).start() let dimensions = item.file.dimensions ?? PixelDimensions(width: 512, height: 512) - let fetchedRepresentation = chatMessageAnimatedStickerDatas(postbox: account.postbox, userLocation: .other, file: item.file, small: false, size: dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)), fetched: true, onlyFullSize: false, synchronousLoad: false).start(next: { next in + let fetchedRepresentation = chatMessageAnimatedStickerDatas(postbox: account.postbox, userLocation: .other, file: itemFile, small: false, size: dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)), fetched: true, onlyFullSize: false, synchronousLoad: false).start(next: { next in let hasContent = next._0 != nil || next._1 != nil subscriber.putNext(hasContent) if hasContent { diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift index f9f5a76427..95620529f1 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift @@ -222,9 +222,9 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, ASScrol menuItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode.view, animationNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file._parse()), animationNode.view, animationNode.bounds) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), imageNode.view, imageNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file._parse()), imageNode.view, imageNode.bounds) } } f(.default) @@ -234,13 +234,13 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, ASScrol f(.default) if let strongSelf = self { - let _ = strongSelf.context.engine.stickers.toggleStickerSaved(file: item.file, saved: !isStarred).start(next: { result in + let _ = strongSelf.context.engine.stickers.toggleStickerSaved(file: item.file._parse(), saved: !isStarred).start(next: { result in }) } }))) } - return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(context: strongSelf.context, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item.file), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(context: strongSelf.context, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item.file._parse()), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { })) } else { diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift index 475962b539..2ff682e76c 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift @@ -310,12 +310,14 @@ final class StickerPackPreviewGridItemNode: GridItemNode { self.setupTimestamp = CACurrentMediaTime() } + let stickerItemFile = stickerItem.file._parse() + if stickerItem.file.isAnimatedSticker || stickerItem.file.isVideoSticker { let dimensions = stickerItem.file.dimensions ?? PixelDimensions(width: 512, height: 512) if stickerItem.file.isVideoSticker { - self.imageNode.setSignal(chatMessageSticker(account: context.account, userLocation: .other, file: stickerItem.file, small: true, fetched: true)) + self.imageNode.setSignal(chatMessageSticker(account: context.account, userLocation: .other, file: stickerItemFile, small: true, fetched: true)) } else { - self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: context.account.postbox, userLocation: .other, file: stickerItem.file, small: false, size: dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)))) + self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: context.account.postbox, userLocation: .other, file: stickerItemFile, small: false, size: dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)))) } if self.animationNode == nil { @@ -339,14 +341,14 @@ final class StickerPackPreviewGridItemNode: GridItemNode { } } let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)) - self.animationNode?.setup(source: AnimatedStickerResourceSource(account: context.account, resource: stickerItem.file.resource, isVideo: stickerItem.file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .cached) + self.animationNode?.setup(source: AnimatedStickerResourceSource(account: context.account, resource: stickerItemFile.resource, isVideo: stickerItem.file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .cached) self.animationNode?.visibility = visibility - self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: stickerPackFileReference(stickerItem.file), resource: stickerItem.file.resource).start()) + self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: stickerPackFileReference(stickerItemFile), resource: stickerItemFile.resource).start()) - if stickerItem.file.isPremiumSticker, let effect = stickerItem.file.videoThumbnails.first { - self.effectFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: stickerPackFileReference(stickerItem.file), resource: effect.resource).start()) + if stickerItem.file.isPremiumSticker, let effect = stickerItemFile.videoThumbnails.first { + self.effectFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: stickerPackFileReference(stickerItemFile), resource: effect.resource).start()) } } else { if let animationNode = self.animationNode { @@ -354,8 +356,8 @@ final class StickerPackPreviewGridItemNode: GridItemNode { self.animationNode = nil animationNode.removeFromSupernode() } - self.imageNode.setSignal(chatMessageSticker(account: context.account, userLocation: .other, file: stickerItem.file, small: true)) - self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: stickerPackFileReference(stickerItem.file), resource: chatMessageStickerResource(file: stickerItem.file, small: true)).start()) + self.imageNode.setSignal(chatMessageSticker(account: context.account, userLocation: .other, file: stickerItemFile, small: true)) + self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: stickerPackFileReference(stickerItemFile), resource: chatMessageStickerResource(file: stickerItemFile, small: true)).start()) } } else { if isEmpty { @@ -516,7 +518,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode { if isAdd { return } - isPreviewing = interaction.previewedItem == .pack(item.file) + isPreviewing = interaction.previewedItem == .pack(item.file._parse()) } if self.currentIsPreviewing != isPreviewing { self.currentIsPreviewing = isPreviewing diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index ff097a6e60..568778913c 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -543,9 +543,9 @@ private final class StickerPackContainer: ASDisplayNode { menuItems.append(.action(ContextMenuActionItem(text: actionTitle, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: iconName), color: theme.contextMenu.primaryColor) }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode.view, animationNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file._parse()), animationNode.view, animationNode.bounds) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), imageNode.view, imageNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file._parse()), imageNode.view, imageNode.bounds) } } f(.default) @@ -555,10 +555,10 @@ private final class StickerPackContainer: ASDisplayNode { f(.default) if let strongSelf = self { - let _ = (strongSelf.context.engine.stickers.toggleStickerSaved(file: item.file, saved: !isStarred) + let _ = (strongSelf.context.engine.stickers.toggleStickerSaved(file: item.file._parse(), saved: !isStarred) |> deliverOnMainQueue).start(next: { [weak self] result in if let self, let contorller = self.controller { - contorller.present(UndoOverlayController(presentationData: self.presentationData, content: .sticker(context: context, file: item.file, loop: true, title: nil, text: !isStarred ? self.presentationData.strings.Conversation_StickerAddedToFavorites : self.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), in: .window(.root)) + contorller.present(UndoOverlayController(presentationData: self.presentationData, content: .sticker(context: context, file: item.file._parse(), loop: true, title: nil, text: !isStarred ? self.presentationData.strings.Conversation_StickerAddedToFavorites : self.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), in: .window(.root)) } }) } @@ -568,7 +568,7 @@ private final class StickerPackContainer: ASDisplayNode { menuItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Stickers_EditSticker, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Draw"), color: theme.contextMenu.primaryColor) }, action: { _, f in f(.default) if let self { - self.openEditSticker(item.file) + self.openEditSticker(item.file._parse()) } }))) if !strongSelf.isEditing { @@ -601,7 +601,7 @@ private final class StickerPackContainer: ASDisplayNode { } else { self.currentStickerPack = (info, updatedItems, installed) self.reorderAndUpdateEntries() - let _ = self.context.engine.stickers.deleteStickerFromStickerSet(sticker: .stickerPack(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), media: item.file)).startStandalone() + let _ = self.context.engine.stickers.deleteStickerFromStickerSet(sticker: .stickerPack(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), media: item.file._parse())).startStandalone() } } })) @@ -611,7 +611,7 @@ private final class StickerPackContainer: ASDisplayNode { }))) } } - return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(context: strongSelf.context, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item.file), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(context: strongSelf.context, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item.file._parse()), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } @@ -752,7 +752,7 @@ private final class StickerPackContainer: ASDisplayNode { self.reorderFeedback?.tap() if let reorderPosition = self.reorderPosition, let file = itemNode.stickerPackItem?.file { - let _ = self.context.engine.stickers.reorderSticker(sticker: .standalone(media: file), position: reorderPosition).startStandalone() + let _ = self.context.engine.stickers.reorderSticker(sticker: .standalone(media: file._parse()), position: reorderPosition).startStandalone() if let (info, items, isInstalled) = self.currentStickerPack { var updatedItems = items diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPreviewControllerNode.swift b/submodules/StickerPackPreviewUI/Sources/StickerPreviewControllerNode.swift index ff1ee5e255..526ea1281c 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPreviewControllerNode.swift @@ -133,11 +133,13 @@ final class StickerPreviewControllerNode: ASDisplayNode, ASScrollViewDelegate { self.item = item - for case let .Sticker(text, _, _) in item.file.attributes { + let itemFile = item.file._parse() + + for case let .Sticker(text, _, _) in itemFile.attributes { self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(32.0), textColor: .black) break } - self.imageNode.setSignal(chatMessageSticker(account: context.account, userLocation: .other, file: item.file, small: false, onlyFullSize: false)) + self.imageNode.setSignal(chatMessageSticker(account: context.account, userLocation: .other, file: itemFile, small: false, onlyFullSize: false)) if let (layout, navigationBarHeight) = self.containerLayout { self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate) diff --git a/submodules/StickerResources/Sources/StickerResources.swift b/submodules/StickerResources/Sources/StickerResources.swift index 572611db40..5307aadce8 100644 --- a/submodules/StickerResources/Sources/StickerResources.swift +++ b/submodules/StickerResources/Sources/StickerResources.swift @@ -622,10 +622,11 @@ public func preloadedStickerPackThumbnail(account: Account, info: StickerPackCol if let item = items.first as? StickerPackItem { if item.file.isAnimatedSticker { let signal = Signal { subscriber in - let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: FileMediaReference.standalone(media: item.file).resourceReference(item.file.resource)).start() - let data = account.postbox.mediaBox.resourceData(item.file.resource).start() - let dimensions = item.file.dimensions ?? PixelDimensions(width: 512, height: 512) - let fetchedRepresentation = chatMessageAnimatedStickerDatas(postbox: account.postbox, userLocation: .other, file: item.file, small: false, size: dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)), fetched: true, onlyFullSize: false, synchronousLoad: false).start(next: { next in + let itemFile = item.file._parse() + let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .sticker, reference: FileMediaReference.standalone(media: itemFile).resourceReference(itemFile.resource)).start() + let data = account.postbox.mediaBox.resourceData(itemFile.resource).start() + let dimensions = itemFile.dimensions ?? PixelDimensions(width: 512, height: 512) + let fetchedRepresentation = chatMessageAnimatedStickerDatas(postbox: account.postbox, userLocation: .other, file: itemFile, small: false, size: dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)), fetched: true, onlyFullSize: false, synchronousLoad: false).start(next: { next in let hasContent = next._0 != nil || next._1 != nil subscriber.putNext(hasContent) if hasContent { @@ -641,9 +642,10 @@ public func preloadedStickerPackThumbnail(account: Account, info: StickerPackCol return signal } else { let signal = Signal { subscriber in - let data = account.postbox.mediaBox.resourceData(item.file.resource).start() - let dimensions = item.file.dimensions ?? PixelDimensions(width: 512, height: 512) - let fetchedRepresentation = chatMessageAnimatedStickerDatas(postbox: account.postbox, userLocation: .other, file: item.file, small: true, size: dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)), fetched: true, onlyFullSize: false, synchronousLoad: false).start(next: { next in + let itemFile = item.file._parse() + let data = account.postbox.mediaBox.resourceData(itemFile.resource).start() + let dimensions = itemFile.dimensions ?? PixelDimensions(width: 512, height: 512) + let fetchedRepresentation = chatMessageAnimatedStickerDatas(postbox: account.postbox, userLocation: .other, file: itemFile, small: true, size: dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)), fetched: true, onlyFullSize: false, synchronousLoad: false).start(next: { next in let hasContent = next._0 != nil || next._1 != nil subscriber.putNext(hasContent) if hasContent { diff --git a/submodules/TelegramCallsUI/Sources/CallControllerNodeV2.swift b/submodules/TelegramCallsUI/Sources/CallControllerNodeV2.swift index 73d57e9c3c..7ccc395be3 100644 --- a/submodules/TelegramCallsUI/Sources/CallControllerNodeV2.swift +++ b/submodules/TelegramCallsUI/Sources/CallControllerNodeV2.swift @@ -180,7 +180,7 @@ final class CallControllerNodeV2: ViewControllerTracingNode, CallControllerNodeP remoteVideo: nil, isRemoteBatteryLow: false, isEnergySavingEnabled: !self.sharedContext.energyUsageSettings.fullTranslucency, - isConferencePossible: self.sharedContext.immediateExperimentalUISettings.conferenceCalls + isConferencePossible: true ) self.isMicrophoneMutedDisposable = (call.isMuted diff --git a/submodules/TelegramCallsUI/Sources/PresentationCall.swift b/submodules/TelegramCallsUI/Sources/PresentationCall.swift index ba2670c36c..a4532da6f5 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationCall.swift @@ -413,10 +413,8 @@ public final class PresentationCallImpl: PresentationCall { if let data = context.currentAppConfiguration.with({ $0 }).data, let _ = data["ios_killswitch_disable_call_device"] { self.sharedAudioContext = nil - } else if context.sharedContext.immediateExperimentalUISettings.conferenceCalls { - self.sharedAudioContext = SharedCallAudioContext(audioSession: audioSession, callKitIntegration: callKitIntegration) } else { - self.sharedAudioContext = nil + self.sharedAudioContext = SharedCallAudioContext(audioSession: audioSession, callKitIntegration: callKitIntegration) } if let _ = self.sharedAudioContext { diff --git a/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift b/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift index 47255cf012..fbaabb7969 100644 --- a/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift +++ b/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift @@ -540,10 +540,10 @@ final class MediaReferenceRevalidationContext { } } - func savedGifs(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> { + func savedGifs(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramMediaFile.Accessor], RevalidateMediaReferenceError> { return self.genericItem(key: .savedGifs, background: background, request: { next, error in - let loadRecentGifs: Signal<[TelegramMediaFile], NoError> = postbox.transaction { transaction -> [TelegramMediaFile] in - return transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs).compactMap({ item -> TelegramMediaFile? in + let loadRecentGifs: Signal<[TelegramMediaFile.Accessor], NoError> = postbox.transaction { transaction -> [TelegramMediaFile.Accessor] in + return transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs).compactMap({ item -> TelegramMediaFile.Accessor? in if let contents = item.contents.get(RecentMediaItem.self) { let file = contents.media return file @@ -552,7 +552,7 @@ final class MediaReferenceRevalidationContext { }) } return (managedRecentGifs(postbox: postbox, network: network, forceFetch: true) - |> mapToSignal { _ -> Signal<[TelegramMediaFile], NoError> in + |> mapToSignal { _ -> Signal<[TelegramMediaFile.Accessor], NoError> in return .complete() } |> then(loadRecentGifs) @@ -561,8 +561,8 @@ final class MediaReferenceRevalidationContext { }, error: { _ in error(.generic) }) - }) |> mapToSignal { next -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> in - if let next = next as? [TelegramMediaFile] { + }) |> mapToSignal { next -> Signal<[TelegramMediaFile.Accessor], RevalidateMediaReferenceError> in + if let next = next as? [TelegramMediaFile.Accessor] { return .single(next) } else { return .fail(.generic) @@ -570,10 +570,10 @@ final class MediaReferenceRevalidationContext { } } - func savedStickers(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> { + func savedStickers(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramMediaFile.Accessor], RevalidateMediaReferenceError> { return self.genericItem(key: .savedStickers, background: background, request: { next, error in - let loadSavedStickers: Signal<[TelegramMediaFile], NoError> = postbox.transaction { transaction -> [TelegramMediaFile] in - return transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudSavedStickers).compactMap({ item -> TelegramMediaFile? in + let loadSavedStickers: Signal<[TelegramMediaFile.Accessor], NoError> = postbox.transaction { transaction -> [TelegramMediaFile.Accessor] in + return transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudSavedStickers).compactMap({ item -> TelegramMediaFile.Accessor? in if let contents = item.contents.get(SavedStickerItem.self) { let file = contents.file return file @@ -582,7 +582,7 @@ final class MediaReferenceRevalidationContext { }) } return (managedSavedStickers(postbox: postbox, network: network, forceFetch: true) - |> mapToSignal { _ -> Signal<[TelegramMediaFile], NoError> in + |> mapToSignal { _ -> Signal<[TelegramMediaFile.Accessor], NoError> in return .complete() } |> then(loadSavedStickers) @@ -591,8 +591,8 @@ final class MediaReferenceRevalidationContext { }, error: { _ in error(.generic) }) - }) |> mapToSignal { next -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> in - if let next = next as? [TelegramMediaFile] { + }) |> mapToSignal { next -> Signal<[TelegramMediaFile.Accessor], RevalidateMediaReferenceError> in + if let next = next as? [TelegramMediaFile.Accessor] { return .single(next) } else { return .fail(.generic) @@ -600,10 +600,10 @@ final class MediaReferenceRevalidationContext { } } - func recentStickers(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> { + func recentStickers(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramMediaFile.Accessor], RevalidateMediaReferenceError> { return self.genericItem(key: .recentStickers, background: background, request: { next, error in - let loadRecentStickers: Signal<[TelegramMediaFile], NoError> = postbox.transaction { transaction -> [TelegramMediaFile] in - return transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudRecentStickers).compactMap({ item -> TelegramMediaFile? in + let loadRecentStickers: Signal<[TelegramMediaFile.Accessor], NoError> = postbox.transaction { transaction -> [TelegramMediaFile.Accessor] in + return transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudRecentStickers).compactMap({ item -> TelegramMediaFile.Accessor? in if let contents = item.contents.get(RecentMediaItem.self) { let file = contents.media return file @@ -612,7 +612,7 @@ final class MediaReferenceRevalidationContext { }) } return (managedRecentStickers(postbox: postbox, network: network, forceFetch: true) - |> mapToSignal { _ -> Signal<[TelegramMediaFile], NoError> in + |> mapToSignal { _ -> Signal<[TelegramMediaFile.Accessor], NoError> in return .complete() } |> then(loadRecentStickers) @@ -621,8 +621,8 @@ final class MediaReferenceRevalidationContext { }, error: { _ in error(.generic) }) - }) |> mapToSignal { next -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> in - if let next = next as? [TelegramMediaFile] { + }) |> mapToSignal { next -> Signal<[TelegramMediaFile.Accessor], RevalidateMediaReferenceError> in + if let next = next as? [TelegramMediaFile.Accessor] { return .single(next) } else { return .fail(.generic) @@ -876,10 +876,11 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n for item in result.1 { if let item = item as? StickerPackItem { if media.id != nil && item.file.id == media.id { - if let updatedResource = findUpdatedMediaResource(media: item.file, previousMedia: media, resource: resource) { + let itemFile = item.file._parse() + if let updatedResource = findUpdatedMediaResource(media: itemFile, previousMedia: media, resource: resource) { return postbox.transaction { transaction -> RevalidatedMediaResource in if let id = media.id { - var attributes = item.file.attributes + var attributes = itemFile.attributes if !attributes.contains(where: { attribute in if case .hintIsValidated = attribute { return true @@ -889,7 +890,7 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n }) { attributes.append(.hintIsValidated) } - let file = item.file.withUpdatedAttributes(attributes) + let file = itemFile.withUpdatedAttributes(attributes) updateMessageMedia(transaction: transaction, id: id, media: file) } return RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil) @@ -914,7 +915,7 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n |> mapToSignal { result -> Signal in for file in result { if media.id != nil && file.id == media.id { - if let updatedResource = findUpdatedMediaResource(media: file, previousMedia: media, resource: resource) { + if let updatedResource = findUpdatedMediaResource(media: file._parse(), previousMedia: media, resource: resource) { return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil)) } } @@ -926,7 +927,7 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n |> mapToSignal { result -> Signal in for file in result { if media.id != nil && file.id == media.id { - if let updatedResource = findUpdatedMediaResource(media: file, previousMedia: media, resource: resource) { + if let updatedResource = findUpdatedMediaResource(media: file._parse(), previousMedia: media, resource: resource) { return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil)) } } @@ -938,7 +939,7 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n |> mapToSignal { result -> Signal in for file in result { if media.id != nil && file.id == media.id { - if let updatedResource = findUpdatedMediaResource(media: file, previousMedia: media, resource: resource) { + if let updatedResource = findUpdatedMediaResource(media: file._parse(), previousMedia: media, resource: resource) { return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil)) } } @@ -1001,7 +1002,7 @@ func revalidateMediaResourceReference(accountPeerId: PeerId, postbox: Postbox, n for item in result.1 { if let item = item as? StickerPackItem { if media.id != nil && item.file.id == media.id { - if let updatedResource = findUpdatedMediaResource(media: item.file, previousMedia: media, resource: resource) { + if let updatedResource = findUpdatedMediaResource(media: item.file._parse(), previousMedia: media, resource: resource) { return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil)) } } diff --git a/submodules/TelegramCore/Sources/State/AvailableReactions.swift b/submodules/TelegramCore/Sources/State/AvailableReactions.swift index 743c030556..b8dac0ad33 100644 --- a/submodules/TelegramCore/Sources/State/AvailableReactions.swift +++ b/submodules/TelegramCore/Sources/State/AvailableReactions.swift @@ -2,6 +2,8 @@ import Foundation import TelegramApi import Postbox import SwiftSignalKit +import FlatBuffers +import FlatSerialization private func generateStarsReactionFile(kind: Int, isAnimatedSticker: Bool) -> TelegramMediaFile { let baseId: Int64 = 52343278047832950 + 10 @@ -27,7 +29,7 @@ private func generateStarsReactionFile(kind: Int, isAnimatedSticker: Bool) -> Te ) } -private func generateStarsReaction() -> AvailableReactions.Reaction { +private let sharedStarsReaction: AvailableReactions.Reaction = { return AvailableReactions.Reaction( isEnabled: false, isPremium: false, @@ -41,7 +43,7 @@ private func generateStarsReaction() -> AvailableReactions.Reaction { aroundAnimation: generateStarsReactionFile(kind: 5, isAnimatedSticker: true), centerAnimation: generateStarsReactionFile(kind: 6, isAnimatedSticker: true) ) -} +}() public final class AvailableReactions: Equatable, Codable { public final class Reaction: Equatable, Codable { @@ -51,12 +53,19 @@ public final class AvailableReactions: Equatable, Codable { case value case title case staticIcon + case staticIconData case appearAnimation + case appearAnimationData case selectAnimation + case selectAnimationData case activateAnimation + case activateAnimationData case effectAnimation + case effectAnimationData case aroundAnimation + case aroundAnimationData case centerAnimation + case centerAnimationData case isStars } @@ -64,13 +73,13 @@ public final class AvailableReactions: Equatable, Codable { public let isPremium: Bool public let value: MessageReaction.Reaction public let title: String - public let staticIcon: TelegramMediaFile - public let appearAnimation: TelegramMediaFile - public let selectAnimation: TelegramMediaFile - public let activateAnimation: TelegramMediaFile - public let effectAnimation: TelegramMediaFile - public let aroundAnimation: TelegramMediaFile? - public let centerAnimation: TelegramMediaFile? + public let staticIcon: TelegramMediaFile.Accessor + public let appearAnimation: TelegramMediaFile.Accessor + public let selectAnimation: TelegramMediaFile.Accessor + public let activateAnimation: TelegramMediaFile.Accessor + public let effectAnimation: TelegramMediaFile.Accessor + public let aroundAnimation: TelegramMediaFile.Accessor? + public let centerAnimation: TelegramMediaFile.Accessor? public init( isEnabled: Bool, @@ -89,13 +98,13 @@ public final class AvailableReactions: Equatable, Codable { self.isPremium = isPremium self.value = value self.title = title - self.staticIcon = staticIcon - self.appearAnimation = appearAnimation - self.selectAnimation = selectAnimation - self.activateAnimation = activateAnimation - self.effectAnimation = effectAnimation - self.aroundAnimation = aroundAnimation - self.centerAnimation = centerAnimation + self.staticIcon = TelegramMediaFile.Accessor(staticIcon) + self.appearAnimation = TelegramMediaFile.Accessor(appearAnimation) + self.selectAnimation = TelegramMediaFile.Accessor(selectAnimation) + self.activateAnimation = TelegramMediaFile.Accessor(activateAnimation) + self.effectAnimation = TelegramMediaFile.Accessor(effectAnimation) + self.aroundAnimation = aroundAnimation.flatMap(TelegramMediaFile.Accessor.init) + self.centerAnimation = centerAnimation.flatMap(TelegramMediaFile.Accessor.init) } public static func ==(lhs: Reaction, rhs: Reaction) -> Bool { @@ -149,29 +158,60 @@ public final class AvailableReactions: Equatable, Codable { } self.title = try container.decode(String.self, forKey: .title) - let staticIconData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .staticIcon) - self.staticIcon = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: staticIconData.data))) + if let staticIconData = try container.decodeIfPresent(Data.self, forKey: .staticIconData) { + var byteBuffer = ByteBuffer(data: staticIconData) + self.staticIcon = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, staticIconData) + } else { + let staticIconData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .staticIcon) + self.staticIcon = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: staticIconData.data)))) + } - let appearAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .appearAnimation) - self.appearAnimation = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: appearAnimationData.data))) + if let appearAnimationData = try container.decodeIfPresent(Data.self, forKey: .appearAnimationData) { + var byteBuffer = ByteBuffer(data: appearAnimationData) + self.appearAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, appearAnimationData) + } else { + let appearAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .appearAnimation) + self.appearAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: appearAnimationData.data)))) + } - let selectAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .selectAnimation) - self.selectAnimation = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: selectAnimationData.data))) + if let selectAnimationData = try container.decodeIfPresent(Data.self, forKey: .selectAnimationData) { + var byteBuffer = ByteBuffer(data: selectAnimationData) + self.selectAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, selectAnimationData) + } else { + let selectAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .selectAnimation) + self.selectAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: selectAnimationData.data)))) + } - let activateAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .activateAnimation) - self.activateAnimation = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: activateAnimationData.data))) + if let activateAnimationData = try container.decodeIfPresent(Data.self, forKey: .activateAnimationData) { + var byteBuffer = ByteBuffer(data: activateAnimationData) + self.activateAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, activateAnimationData) + } else { + let activateAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .activateAnimation) + self.activateAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: activateAnimationData.data)))) + } - let effectAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .effectAnimation) - self.effectAnimation = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: effectAnimationData.data))) + if let effectAnimationData = try container.decodeIfPresent(Data.self, forKey: .effectAnimationData) { + var byteBuffer = ByteBuffer(data: effectAnimationData) + self.effectAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, effectAnimationData) + } else { + let effectAnimationData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .effectAnimation) + self.effectAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: effectAnimationData.data)))) + } - if let aroundAnimationData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .aroundAnimation) { - self.aroundAnimation = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: aroundAnimationData.data))) + if let aroundAnimationData = try container.decodeIfPresent(Data.self, forKey: .aroundAnimationData) { + var byteBuffer = ByteBuffer(data: aroundAnimationData) + self.aroundAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, aroundAnimationData) + } else if let aroundAnimationData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .aroundAnimation) { + self.aroundAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: aroundAnimationData.data)))) } else { self.aroundAnimation = nil } - - if let centerAnimationData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .centerAnimation) { - self.centerAnimation = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: centerAnimationData.data))) + + if let centerAnimationData = try container.decodeIfPresent(Data.self, forKey: .centerAnimationData) { + var byteBuffer = ByteBuffer(data: centerAnimationData) + self.centerAnimation = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, centerAnimationData) + } else if let centerAnimationData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .centerAnimation) { + self.centerAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: centerAnimationData.data)))) } else { self.centerAnimation = nil } @@ -193,16 +233,31 @@ public final class AvailableReactions: Equatable, Codable { } try container.encode(self.title, forKey: .title) - try container.encode(PostboxEncoder().encodeObjectToRawData(self.staticIcon), forKey: .staticIcon) - try container.encode(PostboxEncoder().encodeObjectToRawData(self.appearAnimation), forKey: .appearAnimation) - try container.encode(PostboxEncoder().encodeObjectToRawData(self.selectAnimation), forKey: .selectAnimation) - try container.encode(PostboxEncoder().encodeObjectToRawData(self.activateAnimation), forKey: .activateAnimation) - try container.encode(PostboxEncoder().encodeObjectToRawData(self.effectAnimation), forKey: .effectAnimation) + let encodeFileItem: (TelegramMediaFile.Accessor, CodingKeys) throws -> Void = { file, key in + if let serializedFile = file._wrappedData { + try container.encode(serializedFile, forKey: key) + } else if let file = file._wrappedFile { + var builder = FlatBufferBuilder(initialSize: 1024) + let value = file.encodeToFlatBuffers(builder: &builder) + builder.finish(offset: value) + let serializedFile = builder.data + try container.encode(serializedFile, forKey: key) + } else { + preconditionFailure() + } + } + + try encodeFileItem(self.staticIcon, .staticIconData) + try encodeFileItem(self.appearAnimation, .appearAnimationData) + try encodeFileItem(self.selectAnimation, .selectAnimationData) + try encodeFileItem(self.activateAnimation, .activateAnimationData) + try encodeFileItem(self.effectAnimation, .effectAnimationData) + if let aroundAnimation = self.aroundAnimation { - try container.encode(PostboxEncoder().encodeObjectToRawData(aroundAnimation), forKey: .aroundAnimation) + try encodeFileItem(aroundAnimation, .aroundAnimationData) } if let centerAnimation = self.centerAnimation { - try container.encode(PostboxEncoder().encodeObjectToRawData(centerAnimation), forKey: .centerAnimation) + try encodeFileItem(centerAnimation, .centerAnimationData) } } } @@ -223,7 +278,7 @@ public final class AvailableReactions: Equatable, Codable { var reactions = reactions reactions.removeAll(where: { if case .stars = $0.value { return true } else { return false } }) - reactions.append(generateStarsReaction()) + reactions.append(sharedStarsReaction) self.reactions = reactions } @@ -244,7 +299,7 @@ public final class AvailableReactions: Equatable, Codable { var reactions = try container.decode([Reaction].self, forKey: .reactions) reactions.removeAll(where: { if case .stars = $0.value { return true } else { return false } }) - reactions.append(generateStarsReaction()) + reactions.append(sharedStarsReaction) self.reactions = reactions } @@ -324,27 +379,27 @@ func _internal_setCachedAvailableReactions(transaction: Transaction, availableRe } func managedSynchronizeAvailableReactions(postbox: Postbox, network: Network) -> Signal { - let starsReaction = generateStarsReaction() - let mapping: [String: KeyPath] = [ + let starsReaction = sharedStarsReaction + let mapping: [String: KeyPath] = [ "star_reaction_activate.tgs": \.activateAnimation, "star_reaction_appear.tgs": \.appearAnimation, "star_reaction_effect.tgs": \.effectAnimation, "star_reaction_select.tgs": \.selectAnimation, "star_reaction_static_icon.webp": \.staticIcon ] - let optionalMapping: [String: KeyPath] = [ + let optionalMapping: [String: KeyPath] = [ "star_reaction_center.tgs": \.centerAnimation, "star_reaction_effect.tgs": \.aroundAnimation ] for (key, path) in mapping { if let filePath = Bundle.main.path(forResource: key, ofType: nil), let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)) { - postbox.mediaBox.storeResourceData(starsReaction[keyPath: path].resource.id, data: data) + postbox.mediaBox.storeResourceData(starsReaction[keyPath: path]._parse().resource.id, data: data) } } for (key, path) in optionalMapping { if let filePath = Bundle.main.path(forResource: key, ofType: nil), let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)) { if let file = starsReaction[keyPath: path] { - postbox.mediaBox.storeResourceData(file.resource.id, data: data) + postbox.mediaBox.storeResourceData(file._parse().resource.id, data: data) } } } @@ -380,16 +435,16 @@ func managedSynchronizeAvailableReactions(postbox: Postbox, network: Network) -> var resources: [MediaResource] = [] for reaction in availableReactions.reactions { - resources.append(reaction.staticIcon.resource) - resources.append(reaction.appearAnimation.resource) - resources.append(reaction.selectAnimation.resource) - resources.append(reaction.activateAnimation.resource) - resources.append(reaction.effectAnimation.resource) + resources.append(reaction.staticIcon._parse().resource) + resources.append(reaction.appearAnimation._parse().resource) + resources.append(reaction.selectAnimation._parse().resource) + resources.append(reaction.activateAnimation._parse().resource) + resources.append(reaction.effectAnimation._parse().resource) if let centerAnimation = reaction.centerAnimation { - resources.append(centerAnimation.resource) + resources.append(centerAnimation._parse().resource) } if let aroundAnimation = reaction.aroundAnimation { - resources.append(aroundAnimation.resource) + resources.append(aroundAnimation._parse().resource) } } diff --git a/submodules/TelegramCore/Sources/State/ManagedRecentStickers.swift b/submodules/TelegramCore/Sources/State/ManagedRecentStickers.swift index 476f7b4306..8676963fc7 100644 --- a/submodules/TelegramCore/Sources/State/ManagedRecentStickers.swift +++ b/submodules/TelegramCore/Sources/State/ManagedRecentStickers.swift @@ -495,7 +495,7 @@ func managedRecentReactions(postbox: Postbox, network: Network) -> Signal Signal Signal Signal Void in if let entry = transaction.getOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentGifs, itemId: RecentMediaItemId(mediaId).rawValue), let item = entry.contents.get(RecentMediaItem.self) { let file = item.media - if let resource = file.resource as? CloudDocumentMediaResource { + if let resource = file._parse().resource as? CloudDocumentMediaResource { transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentGifs, itemId: entry.id) addSynchronizeSavedGifsOperation(transaction: transaction, operation: .remove(id: resource.fileId, accessHash: resource.accessHash)) } diff --git a/submodules/TelegramCore/Sources/State/SynchronizeSavedStickersOperation.swift b/submodules/TelegramCore/Sources/State/SynchronizeSavedStickersOperation.swift index fc2c881026..e81d831848 100644 --- a/submodules/TelegramCore/Sources/State/SynchronizeSavedStickersOperation.swift +++ b/submodules/TelegramCore/Sources/State/SynchronizeSavedStickersOperation.swift @@ -54,7 +54,7 @@ public func addSavedSticker(postbox: Postbox, network: Network, file: TelegramMe if stickerItem.file.fileId == file.fileId { let stringRepresentations = stickerItem.getStringRepresentationsOfIndexKeys() found = true - addSavedSticker(transaction: transaction, file: stickerItem.file, stringRepresentations: stringRepresentations) + addSavedSticker(transaction: transaction, file: stickerItem.file._parse(), stringRepresentations: stringRepresentations) break inner } } @@ -124,7 +124,7 @@ public func addSavedSticker(transaction: Transaction, file: TelegramMediaFile, s public func removeSavedSticker(transaction: Transaction, mediaId: MediaId) { if let entry = transaction.getOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudSavedStickers, itemId: RecentMediaItemId(mediaId).rawValue), let item = entry.contents.get(SavedStickerItem.self) { - if let resource = item.file.resource as? CloudDocumentMediaResource { + if let resource = item.file._parse().resource as? CloudDocumentMediaResource { transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudSavedStickers, itemId: entry.id) addSynchronizeSavedStickersOperation(transaction: transaction, operation: .remove(id: resource.fileId, accessHash: resource.accessHash)) } @@ -134,7 +134,7 @@ public func removeSavedSticker(transaction: Transaction, mediaId: MediaId) { public func removeSavedSticker(postbox: Postbox, mediaId: MediaId) -> Signal { return postbox.transaction { transaction in if let entry = transaction.getOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudSavedStickers, itemId: RecentMediaItemId(mediaId).rawValue), let item = entry.contents.get(SavedStickerItem.self) { - if let resource = item.file.resource as? CloudDocumentMediaResource { + if let resource = item.file._parse().resource as? CloudDocumentMediaResource { transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudSavedStickers, itemId: entry.id) addSynchronizeSavedStickersOperation(transaction: transaction, operation: .remove(id: resource.fileId, accessHash: resource.accessHash)) } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CloudFileMediaResource.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CloudFileMediaResource.swift index 87a9eddab0..b6bb7d1da7 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CloudFileMediaResource.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CloudFileMediaResource.swift @@ -961,7 +961,7 @@ public final class WallpaperDataResource: TelegramMediaResource { public func TelegramMediaResource_parse(flatBuffersData data: Data) throws -> TelegramMediaResource { var byteBuffer = ByteBuffer(data: data) - let flatBuffersObject: TelegramCore_TelegramMediaResource = try getCheckedRoot(byteBuffer: &byteBuffer) + let flatBuffersObject: TelegramCore_TelegramMediaResource = getRoot(byteBuffer: &byteBuffer) return try TelegramMediaResource_parse(flatBuffersObject: flatBuffersObject) } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift index 9bdd6e3078..bcaa443e06 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift @@ -1,5 +1,7 @@ import Foundation import Postbox +import FlatBuffers +import FlatSerialization public struct RecentMediaItemId { public let rawValue: MemoryBuffer @@ -26,27 +28,47 @@ public struct RecentMediaItemId { } public final class RecentMediaItem: Codable, Equatable { - public let media: TelegramMediaFile + public let media: TelegramMediaFile.Accessor + private let serializedFile: Data? public init(_ media: TelegramMediaFile) { - self.media = media + self.media = TelegramMediaFile.Accessor(media) + self.serializedFile = nil } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: StringCodingKey.self) - let mediaData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "m") - self.media = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: mediaData.data))) + if let serializedFileData = try container.decodeIfPresent(Data.self, forKey: "md") { + self.serializedFile = serializedFileData + var byteBuffer = ByteBuffer(data: serializedFileData) + self.media = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, serializedFileData) + } else { + let mediaData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "m") + let media = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: mediaData.data))) + self.media = TelegramMediaFile.Accessor(media) + self.serializedFile = nil + } } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: StringCodingKey.self) - try container.encode(PostboxEncoder().encodeObjectToRawData(self.media), forKey: "m") + if let serializedFile = self.serializedFile { + try container.encode(serializedFile, forKey: "md") + } else if let file = self.media._wrappedFile { + var builder = FlatBufferBuilder(initialSize: 1024) + let value = file.encodeToFlatBuffers(builder: &builder) + builder.finish(offset: value) + let serializedFile = builder.data + try container.encode(serializedFile, forKey: "md") + } else { + preconditionFailure() + } } public static func ==(lhs: RecentMediaItem, rhs: RecentMediaItem) -> Bool { - return lhs.media.isEqual(to: rhs.media) + return lhs.media == rhs.media } } @@ -233,7 +255,7 @@ public struct RecentReactionItemId { public final class RecentReactionItem: Codable, Equatable { public enum Content: Equatable { - case custom(TelegramMediaFile) + case custom(TelegramMediaFile.Accessor) case builtin(String) case stars } @@ -257,9 +279,13 @@ public final class RecentReactionItem: Codable, Equatable { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: StringCodingKey.self) - - if let mediaData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: "m") { - self.content = .custom(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: mediaData.data)))) + + if let mediaData = try container.decodeIfPresent(Data.self, forKey: "md") { + var byteBuffer = ByteBuffer(data: mediaData) + let file = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, mediaData) + self.content = .custom(file) + } else if let mediaData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: "m") { + self.content = .custom(TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: mediaData.data))))) } else if let _ = try container.decodeIfPresent(Int64.self, forKey: "star") { self.content = .stars } else { @@ -272,7 +298,17 @@ public final class RecentReactionItem: Codable, Equatable { switch self.content { case let .custom(file): - try container.encode(PostboxEncoder().encodeObjectToRawData(file), forKey: "m") + if let serializedFile = file._wrappedData { + try container.encode(serializedFile, forKey: "md") + } else if let file = file._wrappedFile { + var builder = FlatBufferBuilder(initialSize: 1024) + let value = file.encodeToFlatBuffers(builder: &builder) + builder.finish(offset: value) + let serializedFile = builder.data + try container.encode(serializedFile, forKey: "md") + } else { + preconditionFailure() + } case let .builtin(string): try container.encode(string, forKey: "s") case .stars: diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_SavedStickerItem.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_SavedStickerItem.swift index 6c5c40ab1f..a359117cd3 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_SavedStickerItem.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_SavedStickerItem.swift @@ -1,30 +1,50 @@ import Foundation import Postbox +import FlatBuffers +import FlatSerialization public final class SavedStickerItem: Codable, Equatable { - public let file: TelegramMediaFile + public let file: TelegramMediaFile.Accessor public let stringRepresentations: [String] public init(file: TelegramMediaFile, stringRepresentations: [String]) { - self.file = file + self.file = TelegramMediaFile.Accessor(file) self.stringRepresentations = stringRepresentations } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: StringCodingKey.self) - self.file = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: (try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "f")).data))) + if let serializedFileData = try container.decodeIfPresent(Data.self, forKey: "fd") { + var byteBuffer = ByteBuffer(data: serializedFileData) + self.file = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, serializedFileData) + } else { + let file = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: (try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: "f")).data))) + self.file = TelegramMediaFile.Accessor(file) + } + self.stringRepresentations = try container.decode([String].self, forKey: "sr") } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: StringCodingKey.self) - try container.encode(PostboxEncoder().encodeObjectToRawData(self.file), forKey: "f") + if let serializedFile = self.file._wrappedData { + try container.encode(serializedFile, forKey: "fd") + } else if let file = self.file._wrappedFile { + var builder = FlatBufferBuilder(initialSize: 1024) + let value = file.encodeToFlatBuffers(builder: &builder) + builder.finish(offset: value) + let serializedFile = builder.data + try container.encode(serializedFile, forKey: "fd") + } else { + preconditionFailure() + } + try container.encode(self.stringRepresentations, forKey: "sr") } public static func ==(lhs: SavedStickerItem, rhs: SavedStickerItem) -> Bool { - return lhs.file.isEqual(to: rhs.file) && lhs.stringRepresentations == rhs.stringRepresentations + return lhs.file == rhs.file && lhs.stringRepresentations == rhs.stringRepresentations } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackItem.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackItem.swift index 3ce9e09bbc..1988b491dd 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackItem.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackItem.swift @@ -5,34 +5,67 @@ import FlatSerialization public final class StickerPackItem: ItemCollectionItem, Equatable { public let index: ItemCollectionItemIndex - public let file: TelegramMediaFile - public let serializedFile: Data + public let file: TelegramMediaFile.Accessor public let indexKeys: [MemoryBuffer] public init(index: ItemCollectionItemIndex, file: TelegramMediaFile, indexKeys: [MemoryBuffer]) { self.index = index - self.file = file - self.serializedFile = file.encodeToFlatBuffersData() + self.file = TelegramMediaFile.Accessor(file) + self.indexKeys = indexKeys + } + + public init?(index: ItemCollectionItemIndex, serializedFile: Data, indexKeys: [MemoryBuffer]) { + self.index = index + + var byteBuffer = ByteBuffer(data: serializedFile) + let accessor = getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile + self.file = TelegramMediaFile.Accessor(accessor, serializedFile) + self.indexKeys = indexKeys } public init(decoder: PostboxDecoder) { self.index = ItemCollectionItemIndex(index: decoder.decodeInt32ForKey("i.n", orElse: 0), id: decoder.decodeInt64ForKey("i.i", orElse: 0)) - self.file = decoder.decodeObjectForKey("f") as! TelegramMediaFile - self.serializedFile = decoder.decodeDataForKey("fd") ?? self.file.encodeToFlatBuffersData() + + if let serializedFileData = decoder.decodeDataForKey("fd") { + var byteBuffer = ByteBuffer(data: serializedFileData) + self.file = TelegramMediaFile.Accessor(getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, serializedFileData) + } else { + let file = decoder.decodeObjectForKey("f") as! TelegramMediaFile + self.file = TelegramMediaFile.Accessor(file) + } + self.indexKeys = decoder.decodeBytesArrayForKey("s") } public func encode(_ encoder: PostboxEncoder) { encoder.encodeInt32(self.index.index, forKey: "i.n") encoder.encodeInt64(self.index.id, forKey: "i.i") - encoder.encodeObject(self.file, forKey: "f") - encoder.encodeData(self.serializedFile, forKey: "fd") + if let serializedFile = self.file._wrappedData { + encoder.encodeData(serializedFile, forKey: "fd") + } else if let file = self.file._wrappedFile { + var builder = FlatBufferBuilder(initialSize: 1024) + let value = file.encodeToFlatBuffers(builder: &builder) + builder.finish(offset: value) + let serializedFile = builder.data + encoder.encodeData(serializedFile, forKey: "fd") + } else { + preconditionFailure() + } encoder.encodeBytesArray(self.indexKeys, forKey: "s") } public static func ==(lhs: StickerPackItem, rhs: StickerPackItem) -> Bool { - return lhs.index == rhs.index && lhs.file == rhs.file && lhs.indexKeys == rhs.indexKeys + if lhs.index != rhs.index { + return false + } + if lhs.indexKeys != rhs.indexKeys { + return false + } + if lhs.file != rhs.file { + return false + } + return true } public func getStringRepresentationsOfIndexKeys() -> [String] { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index 069c95b6f5..7612f74e87 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -475,7 +475,7 @@ public enum TelegramMediaFileAttribute: PostboxCoding, Equatable { init(flatBuffersData data: Data) throws { var byteBuffer = ByteBuffer(data: data) - let flatBuffersObject: TelegramCore_TelegramMediaFileAttribute = try getCheckedRoot(byteBuffer: &byteBuffer) + let flatBuffersObject: TelegramCore_TelegramMediaFileAttribute = getRoot(byteBuffer: &byteBuffer) try self.init(flatBuffersObject: flatBuffersObject) } @@ -672,6 +672,43 @@ public enum TelegramMediaFileDecodingError: Error { } public final class TelegramMediaFile: Media, Equatable, Codable { + public struct Accessor: Equatable { + let _wrappedFile: TelegramMediaFile? + let _wrapped: TelegramCore_TelegramMediaFile? + let _wrappedData: Data? + + public init(_ wrapped: TelegramCore_TelegramMediaFile, _ _wrappedData: Data) { + self._wrapped = wrapped + self._wrappedData = _wrappedData + self._wrappedFile = nil + } + + public init(_ wrapped: TelegramMediaFile) { + self._wrapped = nil + self._wrappedData = nil + self._wrappedFile = wrapped + } + + public func _parse() -> TelegramMediaFile { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile + } else { + return try! TelegramMediaFile(flatBuffersObject: self._wrapped!) + } + } + + public static func ==(lhs: TelegramMediaFile.Accessor, rhs: TelegramMediaFile.Accessor) -> Bool { + if let lhsWrappedFile = lhs._wrappedFile, let rhsWrappedFile = rhs._wrappedFile { + return lhsWrappedFile === rhsWrappedFile + } else if let lhsWrappedData = lhs._wrappedData, let rhsWrappedData = rhs._wrappedData { + return lhsWrappedData == rhsWrappedData + } else { + assertionFailure() + return false + } + } + } + enum CodingKeys: String, CodingKey { case data } @@ -807,14 +844,6 @@ public final class TelegramMediaFile: Media, Equatable, Codable { } else { self.alternativeRepresentations = [] } - - /*#if DEBUG - let fbData = self.encodeToFlatBuffersData() - var byteBuffer = ByteBuffer(data: fbData) - let flatBuffersObject: TelegramCore_TelegramMediaFile = try! getCheckedRoot(byteBuffer: &byteBuffer) - let fbObject = try! TelegramMediaFile(flatBuffersObject: flatBuffersObject) - assert(self == fbObject) - #endif*/ } public func encode(_ encoder: PostboxEncoder) { @@ -1313,3 +1342,450 @@ public final class TelegramMediaFile: Media, Equatable, Codable { public func ==(lhs: TelegramMediaFile, rhs: TelegramMediaFile) -> Bool { return lhs.isEqual(to: rhs) } + +public extension TelegramMediaFile.Accessor { + var fileId: MediaId { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.fileId + } + return MediaId(namespace: self._wrapped!.fileId.namespace, id: self._wrapped!.fileId.id) + } + + var id: MediaId { + return self.fileId + } + + var fileName: String? { + get { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.fileName + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeFilename { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_FileName.self) { + return value.fileName + } + } + } + return nil + } + } + + var isSticker: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isSticker + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeSticker { + return true + } + } + return false + } + + var isStaticSticker: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isStaticSticker + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeSticker { + if self._wrapped!.size != Int64.min, self._wrapped!.size < 300 * 1024 { + return !isAnimatedSticker + } else if self._wrapped!.size == Int64.min { + return !isAnimatedSticker + } + return false + } + } + return false + } + + var isStaticEmoji: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isStaticEmoji + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeCustomemoji { + return self._wrapped!.mimeType == "image/webp" + } + } + return false + } + + var isVideo: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isVideo + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeVideo { + return true + } + } + return false + } + + var isInstantVideo: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isInstantVideo + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeVideo { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_Video.self) { + return TelegramMediaVideoFlags(rawValue: value.flags).contains(.instantRoundVideo) + } + } + } + return false + } + + var preloadSize: Int32? { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.preloadSize + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeVideo { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_Video.self) { + return value.preloadSize == 0 ? nil : value.preloadSize + } + } + } + return nil + } + + var isAnimated: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isAnimated + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeAnimated { + return true + } + } + return false + } + + var isAnimatedSticker: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isAnimatedSticker + } + if self._wrapped!.mimeType == "application/x-tgsticker" && self.fileName != nil { + return true + } + return false + } + + var isPremiumSticker: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isPremiumSticker + } + for i in 0 ..< self._wrapped!.videoThumbnailsCount { + let thumbnail = self._wrapped!.videoThumbnails(at: i)! + if thumbnail.resource.valueType == .telegrammediaresourceClouddocumentsizemediaresource { + if let value = thumbnail.resource.value(type: TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.self) { + if value.sizeSpec == "f" { + return true + } + } + } + } + return false + } + + var noPremium: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.noPremium + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeNopremium { + return true + } + } + return false + } + + var premiumEffect: TelegramMediaFile.VideoThumbnail? { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.premiumEffect + } + for i in 0 ..< self._wrapped!.videoThumbnailsCount { + let thumbnail = self._wrapped!.videoThumbnails(at: i)! + if thumbnail.resource.valueType == .telegrammediaresourceClouddocumentsizemediaresource { + if let value = thumbnail.resource.value(type: TelegramCore_TelegramMediaResource_CloudDocumentSizeMediaResource.self) { + if value.sizeSpec == "f" { + return try! TelegramMediaFile.VideoThumbnail(flatBuffersObject: thumbnail) + } + } + } + } + return nil + } + + var isVideoSticker: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isVideoSticker + } + if self._wrapped!.mimeType == "video/webm" { + var hasSticker = false + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeSticker { + hasSticker = true + break + } else if attribute.valueType == .telegrammediafileattributeCustomemoji { + hasSticker = true + break + } + } + return hasSticker + } + return false + } + + var isCustomEmoji: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isCustomEmoji + } + var hasSticker = false + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeCustomemoji { + hasSticker = true + break + } + } + return hasSticker + } + + var customEmojiAlt: String? { + if let _wrappedFile = self._wrappedFile { + for attribute in _wrappedFile.attributes { + if case let .CustomEmoji(_, _, alt, _) = attribute { + return alt + } + } + return nil + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeCustomemoji { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_CustomEmoji.self) { + return value.alt + } + break + } + } + return nil + } + + var stickerDisplayText: String? { + if let _wrappedFile = self._wrappedFile { + for attribute in _wrappedFile.attributes { + if case let .Sticker(displayText, _, _) = attribute { + return displayText + } + } + return nil + } + + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeSticker { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_Sticker.self) { + return value.displayText + } + } + } + + return nil + } + + var isCustomTemplateEmoji: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isCustomTemplateEmoji + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeCustomemoji { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_CustomEmoji.self) { + let isSingleColor = value.isSingleColor + if isSingleColor { + return true + } + + if let packReference = value.packReference { + if packReference.valueType == .stickerpackreferenceId { + if let value = packReference.value(type: TelegramCore_StickerPackReference_Id.self) { + if value.id == 1269403972611866647 { + return true + } + } + } + } + } + } + } + return false + } + + var internal_isHardcodedTemplateEmoji: Bool { + if let _wrappedFile = self._wrappedFile { + for attribute in _wrappedFile.attributes { + if case let .CustomEmoji(_, _, _, packReference) = attribute { + switch packReference { + case let .id(id, _): + if id == 773947703670341676 || id == 2964141614563343 { + return true + } + default: + break + } + } + } + return false + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeCustomemoji { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_CustomEmoji.self) { + if let packReference = value.packReference { + if packReference.valueType == .stickerpackreferenceId { + if let value = packReference.value(type: TelegramCore_StickerPackReference_Id.self) { + if value.id == 773947703670341676 || value.id == 2964141614563343 { + return true + } + } + } + } + } + } + } + return false + } + + var isPremiumEmoji: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isPremiumEmoji + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeCustomemoji { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_CustomEmoji.self) { + return value.isPremium + } + } + } + return false + } + + var isVideoEmoji: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isVideoEmoji + } + if self._wrapped!.mimeType == "video/webm" { + var hasSticker = false + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeCustomemoji { + hasSticker = true + break + } + } + return hasSticker + } + return false + } + + var hasLinkedStickers: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.hasLinkedStickers + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeHaslinkedstickers { + return true + } + } + return false + } + + var isMusic: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isMusic + } + + var hasNonVoiceAudio = false + var hasVideo = false + + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeAudio { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_Audio.self) { + if !value.isVoice { + hasNonVoiceAudio = true + } + } + } else if attribute.valueType == .telegrammediafileattributeVideo { + hasVideo = true + } + } + return hasNonVoiceAudio && !hasVideo + } + + var isVoice: Bool { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.isVoice + } + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeAudio { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_Audio.self) { + return value.isVoice + } + } + } + return false + } + + var dimensions: PixelDimensions? { + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.dimensions + } + + for i in 0 ..< self._wrapped!.attributesCount { + let attribute = self._wrapped!.attributes(at: i)! + if attribute.valueType == .telegrammediafileattributeVideo { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_Video.self) { + return PixelDimensions(width: value.width, height: value.height) + } + } else if attribute.valueType == .telegrammediafileattributeImagesize { + if let value = attribute.value(type: TelegramCore_TelegramMediaFileAttribute_ImageSize.self) { + return PixelDimensions(width: value.width, height: value.height) + } + } + } + + if self.isAnimatedSticker { + return PixelDimensions(width: 512, height: 512) + } else { + return nil + } + } + + var immediateThumbnailData: Data? { + //TODO:release defer parsing + if let _wrappedFile = self._wrappedFile { + return _wrappedFile.immediateThumbnailData + } + + return _wrapped!.immediateThumbnailData.isEmpty ? nil : Data(_wrapped!.immediateThumbnailData) + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift index 3902ca3b17..450fcc4406 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift @@ -75,7 +75,7 @@ func _internal_randomGreetingSticker(account: Account) -> Signal map { items -> FoundStickerItem? in if let randomItem = items?.randomElement(), let item = randomItem.contents.get(RecentMediaItem.self) { let file = item.media - return FoundStickerItem(file: file, stringRepresentations: []) + return FoundStickerItem(file: file._parse(), stringRepresentations: []) } return nil } @@ -107,7 +107,7 @@ func _internal_searchStickers(account: Account, query: String?, emoticon: [Strin for representation in item.stringRepresentations { for queryItem in emoticon { if representation.hasPrefix(queryItem) { - result.append(FoundStickerItem(file: item.file, stringRepresentations: item.stringRepresentations)) + result.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: item.stringRepresentations)) break } } @@ -131,7 +131,7 @@ func _internal_searchStickers(account: Account, query: String?, emoticon: [Strin if !currentItems.contains(file.fileId) { currentItems.insert(file.fileId) - for case let .Sticker(displayText, _, _) in file.attributes { + if let displayText = file.stickerDisplayText { for queryItem in emoticon { if displayText.hasPrefix(queryItem) { matchingRecentItemsIds.insert(file.fileId) @@ -140,9 +140,9 @@ func _internal_searchStickers(account: Account, query: String?, emoticon: [Strin } recentItemsIds.insert(file.fileId) if file.isAnimatedSticker || file.isVideoSticker { - recentAnimatedItems.append(file) + recentAnimatedItems.append(file._parse()) } else { - recentItems.append(file) + recentItems.append(file._parse()) } break } @@ -167,18 +167,18 @@ func _internal_searchStickers(account: Account, query: String?, emoticon: [Strin let stringRepresentations = item.getStringRepresentationsOfIndexKeys() if !recentItemsIds.contains(item.file.fileId) { if item.file.isPremiumSticker { - installedPremiumItems.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations)) + installedPremiumItems.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: stringRepresentations)) } else if item.file.isAnimatedSticker || item.file.isVideoSticker { - installedAnimatedItems.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations)) + installedAnimatedItems.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: stringRepresentations)) } else { - installedItems.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations)) + installedItems.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: stringRepresentations)) } } else { matchingRecentItemsIds.insert(item.file.fileId) if item.file.isAnimatedSticker || item.file.isVideoSticker { - recentAnimatedItems.append(item.file) + recentAnimatedItems.append(item.file._parse()) } else { - recentItems.append(item.file) + recentItems.append(item.file._parse()) } } } @@ -504,13 +504,13 @@ func _internal_searchStickers(account: Account, category: EmojiSearchCategories. if let item = entry.contents.get(SavedStickerItem.self) { if case .premium = category.kind { if item.file.isPremiumSticker { - result.append(FoundStickerItem(file: item.file, stringRepresentations: item.stringRepresentations)) + result.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: item.stringRepresentations)) } } else { for representation in item.stringRepresentations { for queryItem in query { if representation.hasPrefix(queryItem) { - result.append(FoundStickerItem(file: item.file, stringRepresentations: item.stringRepresentations)) + result.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: item.stringRepresentations)) break } } @@ -535,7 +535,7 @@ func _internal_searchStickers(account: Account, category: EmojiSearchCategories. if !currentItems.contains(file.fileId) { currentItems.insert(file.fileId) - for case let .Sticker(displayText, _, _) in file.attributes { + if let displayText = file.stickerDisplayText { if case .premium = category.kind { if file.isPremiumSticker { matchingRecentItemsIds.insert(file.fileId) @@ -550,9 +550,9 @@ func _internal_searchStickers(account: Account, category: EmojiSearchCategories. } recentItemsIds.insert(file.fileId) if file.isAnimatedSticker || file.isVideoSticker { - recentAnimatedItems.append(file) + recentAnimatedItems.append(file._parse()) } else { - recentItems.append(file) + recentItems.append(file._parse()) } break } @@ -585,18 +585,18 @@ func _internal_searchStickers(account: Account, category: EmojiSearchCategories. if !recentItemsIds.contains(item.file.fileId) { if item.file.isPremiumSticker { - installedPremiumItems.append(FoundStickerItem(file: item.file, stringRepresentations: [])) + installedPremiumItems.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: [])) } else if item.file.isAnimatedSticker || item.file.isVideoSticker { - installedAnimatedItems.append(FoundStickerItem(file: item.file, stringRepresentations: [])) + installedAnimatedItems.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: [])) } else { - installedItems.append(FoundStickerItem(file: item.file, stringRepresentations: [])) + installedItems.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: [])) } } else { matchingRecentItemsIds.insert(item.file.fileId) if item.file.isAnimatedSticker || item.file.isVideoSticker { - recentAnimatedItems.append(item.file) + recentAnimatedItems.append(item.file._parse()) } else { - recentItems.append(item.file) + recentItems.append(item.file._parse()) } } } @@ -614,18 +614,18 @@ func _internal_searchStickers(account: Account, category: EmojiSearchCategories. if !recentItemsIds.contains(item.media.fileId) { if item.media.isPremiumSticker { - installedPremiumItems.append(FoundStickerItem(file: item.media, stringRepresentations: [])) + installedPremiumItems.append(FoundStickerItem(file: item.media._parse(), stringRepresentations: [])) } else if item.media.isAnimatedSticker || item.media.isVideoSticker { - installedAnimatedItems.append(FoundStickerItem(file: item.media, stringRepresentations: [])) + installedAnimatedItems.append(FoundStickerItem(file: item.media._parse(), stringRepresentations: [])) } else { - installedItems.append(FoundStickerItem(file: item.media, stringRepresentations: [])) + installedItems.append(FoundStickerItem(file: item.media._parse(), stringRepresentations: [])) } } else { matchingRecentItemsIds.insert(item.media.fileId) if item.media.isAnimatedSticker || item.media.isVideoSticker { - recentAnimatedItems.append(item.media) + recentAnimatedItems.append(item.media._parse()) } else { - recentItems.append(item.media) + recentItems.append(item.media._parse()) } } } @@ -639,18 +639,18 @@ func _internal_searchStickers(account: Account, category: EmojiSearchCategories. let stringRepresentations = item.getStringRepresentationsOfIndexKeys() if !recentItemsIds.contains(item.file.fileId) { if item.file.isPremiumSticker { - installedPremiumItems.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations)) + installedPremiumItems.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: stringRepresentations)) } else if item.file.isAnimatedSticker || item.file.isVideoSticker { - installedAnimatedItems.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations)) + installedAnimatedItems.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: stringRepresentations)) } else { - installedItems.append(FoundStickerItem(file: item.file, stringRepresentations: stringRepresentations)) + installedItems.append(FoundStickerItem(file: item.file._parse(), stringRepresentations: stringRepresentations)) } } else { matchingRecentItemsIds.insert(item.file.fileId) if item.file.isAnimatedSticker || item.file.isVideoSticker { - recentAnimatedItems.append(item.file) + recentAnimatedItems.append(item.file._parse()) } else { - recentItems.append(item.file) + recentItems.append(item.file._parse()) } } } @@ -908,7 +908,7 @@ func _internal_searchEmoji(account: Account, query: String?, emoticon: [String], let stringRepresentations = item.getStringRepresentationsOfIndexKeys() for stringRepresentation in stringRepresentations { if querySet.contains(stringRepresentation) { - installedItems.append(FoundStickerItem(file: file, stringRepresentations: stringRepresentations)) + installedItems.append(FoundStickerItem(file: file._parse(), stringRepresentations: stringRepresentations)) break } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift index 2c6df997f7..359a1a6a58 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift @@ -36,7 +36,8 @@ func _internal_addStickerPackInteractively(postbox: Postbox, info: StickerPackCo var indexedItems: [ItemCollectionItem] = [] for item in items { - indexedItems.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(indexedItems.count), id: item.index.id), file: item.file, indexKeys: item.indexKeys)) + let item = StickerPackItem(index: ItemCollectionItemIndex(index: Int32(indexedItems.count), id: item.index.id), file: item.file._parse(), indexKeys: item.indexKeys) + indexedItems.append(item) } transaction.replaceItemCollectionItems(collectionId: mappedInfo.id, items: indexedItems) } diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift index 7c1bd6a3c2..bfbcbd9d71 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift @@ -114,7 +114,7 @@ final class AvatarEditorScreenComponent: Component { self.fileDisposable = (context.engine.stickers.loadedStickerPack(reference: packReference, forceActualized: false) |> map { pack -> TelegramMediaFile? in if case let .result(_, items, _) = pack, let item = items.first(where: { $0.file.fileId.id == fileId }) { - return item.file + return item.file._parse() } return nil } @@ -249,7 +249,7 @@ final class AvatarEditorScreenComponent: Component { self.data = data if wasEmpty && self.state?.selectedFile == nil { - self.state?.selectedFile = data.emoji.panelItemGroups.first?.items.first?.itemFile + self.state?.selectedFile = data.emoji.panelItemGroups.first?.items.first?.itemFile?._parse() } let updateSearchQuery: (EmojiPagerContentComponent.SearchQuery?) -> Void = { [weak self] query in @@ -295,7 +295,7 @@ final class AvatarEditorScreenComponent: Component { |> map { view, stickers -> [EmojiPagerContentComponent.ItemGroup] in let hasPremium = true - var emoji: [(String, TelegramMediaFile?, String)] = [] + var emoji: [(String, TelegramMediaFile.Accessor?, String)] = [] var existingEmoticons = Set() var allEmoticons: [String: String] = [:] @@ -310,18 +310,13 @@ final class AvatarEditorScreenComponent: Component { guard let item = entry.item as? StickerPackItem else { continue } - for attribute in item.file.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - if !item.file.isPremiumEmoji || hasPremium { - if !alt.isEmpty, let keyword = allEmoticons[alt] { - emoji.append((alt, item.file, keyword)) - } else if alt == query { - emoji.append((alt, item.file, alt)) - } + if let alt = item.file.customEmojiAlt { + if !item.file.isPremiumEmoji || hasPremium { + if !alt.isEmpty, let keyword = allEmoticons[alt] { + emoji.append((alt, item.file, keyword)) + } else if alt == query { + emoji.append((alt, item.file, alt)) } - default: - break } } } @@ -355,11 +350,11 @@ final class AvatarEditorScreenComponent: Component { } existingIds.insert(sticker.file.fileId) - let animationData = EntityKeyboardAnimationData(file: sticker.file) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(sticker.file)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: sticker.file, + itemFile: TelegramMediaFile.Accessor(sticker.file), subgroupId: nil, icon: .none, tintMode: .none @@ -441,11 +436,12 @@ final class AvatarEditorScreenComponent: Component { continue } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, subgroupId: nil, + itemFile: TelegramMediaFile.Accessor(itemFile), + subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none ) @@ -520,7 +516,7 @@ final class AvatarEditorScreenComponent: Component { guard let self, let _ = item.itemFile else { return } - self.state?.selectedFile = item.itemFile + self.state?.selectedFile = item.itemFile?._parse() self.state?.updated(transition: .easeInOut(duration: 0.2)) }, deleteBackwards: nil, @@ -655,7 +651,7 @@ final class AvatarEditorScreenComponent: Component { guard let self, let _ = item.itemFile else { return } - self.state?.selectedFile = item.itemFile + self.state?.selectedFile = item.itemFile?._parse() self.state?.updated(transition: .easeInOut(duration: 0.2)) }, deleteBackwards: nil, diff --git a/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift index e60b4375c6..80ab042fb2 100644 --- a/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift @@ -151,7 +151,7 @@ public final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNod guard let stickerItem = self.stickerItem else { return } - let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self.view, self.stickerNode.bounds, nil, []) + let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file._parse()), false, self.view, self.stickerNode.bounds, nil, []) } public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { @@ -359,7 +359,7 @@ public final class ChatEmptyNodeNearbyChatContent: ASDisplayNode, ChatEmptyNodeS guard let stickerItem = self.stickerItem else { return } - let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self.view, self.stickerNode.bounds, nil, []) + let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file._parse()), false, self.view, self.stickerNode.bounds, nil, []) } public func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { diff --git a/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/Sources/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/Sources/ChatMediaInputStickerGridItem.swift index 3d2a80eea9..8a888df6a5 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/Sources/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/Sources/ChatMediaInputStickerGridItem.swift @@ -266,6 +266,8 @@ public final class ChatMediaInputStickerGridItemNode: GridItemNode { } if let dimensions = item.stickerItem.file.dimensions { + let parsedStickerItemFile = item.stickerItem.file._parse() + if item.stickerItem.file.isAnimatedSticker || item.stickerItem.file.isVideoSticker { if self.animationNode == nil { let animationNode = DefaultAnimatedStickerNodeImpl() @@ -283,12 +285,12 @@ public final class ChatMediaInputStickerGridItemNode: GridItemNode { let dimensions = item.stickerItem.file.dimensions ?? PixelDimensions(width: 512, height: 512) let fittedSize = item.large ? CGSize(width: 384.0, height: 384.0) : CGSize(width: 160.0, height: 160.0) if item.stickerItem.file.isVideoSticker { - self.imageNode.setSignal(chatMessageSticker(account: item.context.account, userLocation: .other, file: item.stickerItem.file, small: false, synchronousLoad: synchronousLoads && isVisible)) + self.imageNode.setSignal(chatMessageSticker(account: item.context.account, userLocation: .other, file: parsedStickerItemFile, small: false, synchronousLoad: synchronousLoads && isVisible)) } else { - self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.context.account.postbox, userLocation: .other, file: item.stickerItem.file, small: false, size: dimensions.cgSize.aspectFitted(fittedSize))) + self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: item.context.account.postbox, userLocation: .other, file: parsedStickerItemFile, small: false, size: dimensions.cgSize.aspectFitted(fittedSize))) } self.updateVisibility() - self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.context.account, userLocation: .other, fileReference: stickerPackFileReference(item.stickerItem.file), resource: item.stickerItem.file.resource).startStrict()) + self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.context.account, userLocation: .other, fileReference: stickerPackFileReference(parsedStickerItemFile), resource: parsedStickerItemFile.resource).startStrict()) } else { if let animationNode = self.animationNode { animationNode.visibility = false @@ -297,8 +299,8 @@ public final class ChatMediaInputStickerGridItemNode: GridItemNode { self.imageNode.isHidden = false self.didSetUpAnimationNode = false } - self.imageNode.setSignal(chatMessageSticker(account: item.context.account, userLocation: .other, file: item.stickerItem.file, small: !item.large, synchronousLoad: synchronousLoads && isVisible)) - self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.context.account, userLocation: .other, fileReference: stickerPackFileReference(item.stickerItem.file), resource: chatMessageStickerResource(file: item.stickerItem.file, small: !item.large)).startStrict()) + self.imageNode.setSignal(chatMessageSticker(account: item.context.account, userLocation: .other, file: parsedStickerItemFile, small: !item.large, synchronousLoad: synchronousLoads && isVisible)) + self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.context.account, userLocation: .other, fileReference: stickerPackFileReference(parsedStickerItemFile), resource: chatMessageStickerResource(file: parsedStickerItemFile, small: !item.large)).startStrict()) } self.currentState = (item.context, item.stickerItem, dimensions.cgSize) @@ -405,7 +407,7 @@ public final class ChatMediaInputStickerGridItemNode: GridItemNode { if let interfaceInteraction = self.interfaceInteraction, let (_, item, _) = self.currentState, case .ended = recognizer.state { if let isLocked = self.isLocked, isLocked { } else { - let _ = interfaceInteraction.sendSticker(.standalone(media: item.file), false, false, nil, false, self.view, self.bounds, nil, []) + let _ = interfaceInteraction.sendSticker(.standalone(media: item.file._parse()), false, false, nil, false, self.view, self.bounds, nil, []) self.imageNode.layer.animateAlpha(from: 0.5, to: 1.0, duration: 1.0) } } @@ -438,7 +440,7 @@ public final class ChatMediaInputStickerGridItemNode: GridItemNode { let dimensions = item.stickerItem.file.dimensions ?? PixelDimensions(width: 512, height: 512) let fitSize = item.large ? CGSize(width: 384.0, height: 384.0) : CGSize(width: 160.0, height: 160.0) let fittedDimensions = dimensions.cgSize.aspectFitted(fitSize) - animationNode.setup(source: AnimatedStickerResourceSource(account: item.context.account, resource: item.stickerItem.file.resource, isVideo: item.stickerItem.file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) + animationNode.setup(source: AnimatedStickerResourceSource(account: item.context.account, resource: item.stickerItem.file._parse().resource, isVideo: item.stickerItem.file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) } } } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift index 8fbe4f0d91..1064b9d35a 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -480,10 +480,10 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } if emojiFile == nil { - emojiFile = item.associatedData.animatedEmojiStickers[emoji]?.first?.file + emojiFile = item.associatedData.animatedEmojiStickers[emoji]?.first?.file._parse() } if emojiFile == nil { - emojiFile = item.associatedData.animatedEmojiStickers[emoji.strippedEmoji]?.first?.file + emojiFile = item.associatedData.animatedEmojiStickers[emoji.strippedEmoji]?.first?.file._parse() } if item.message.text.count == 1, (item.message.textEntitiesAttribute?.entities ?? []).isEmpty && emojiFile != nil { @@ -544,7 +544,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if let animationItems = animationItems { for (_, animationItem) in animationItems { - self.disposables.add(freeMediaFileInteractiveFetched(account: item.context.account, userLocation: .peer(item.message.id.peerId), fileReference: .standalone(media: animationItem.file)).startStrict()) + self.disposables.add(freeMediaFileInteractiveFetched(account: item.context.account, userLocation: .peer(item.message.id.peerId), fileReference: .standalone(media: animationItem.file._parse())).startStrict()) } } } @@ -1965,7 +1965,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { return } - self.playEffectAnimation(resource: file.resource) + self.playEffectAnimation(resource: file._parse().resource) } private var playedPremiumStickerAnimation = false diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/ChatMessageDateAndStatusNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/ChatMessageDateAndStatusNode.swift index c1212c0a0e..7665ed8d47 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/ChatMessageDateAndStatusNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/ChatMessageDateAndStatusNode.swift @@ -733,7 +733,7 @@ public class ChatMessageDateAndStatusNode: ASDisplayNode { if let availableReactions = arguments.availableReactions { for availableReaction in availableReactions.reactions { if availableReaction.value == reaction.value { - centerAnimation = availableReaction.centerAnimation + centerAnimation = availableReaction.centerAnimation?._parse() break } } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageReactionsFooterContentNode/Sources/ChatMessageReactionsFooterContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageReactionsFooterContentNode/Sources/ChatMessageReactionsFooterContentNode.swift index a01d02ed29..16b8040848 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageReactionsFooterContentNode/Sources/ChatMessageReactionsFooterContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageReactionsFooterContentNode/Sources/ChatMessageReactionsFooterContentNode.swift @@ -156,7 +156,7 @@ public final class MessageReactionButtonsNode: ASDisplayNode { if let availableReactions = availableReactions { for availableReaction in availableReactions.reactions { if availableReaction.value == reaction.value { - centerAnimation = availableReaction.centerAnimation + centerAnimation = availableReaction.centerAnimation?._parse() break } } @@ -167,7 +167,7 @@ public final class MessageReactionButtonsNode: ASDisplayNode { if let availableReactions = availableReactions { for availableReaction in availableReactions.reactions { if availableReaction.value == reaction.value { - centerAnimation = availableReaction.centerAnimation + centerAnimation = availableReaction.centerAnimation?._parse() break } } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift index 2c88943faf..f6e820a9af 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift @@ -1007,9 +1007,9 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { let (emoji, fitz) = item.message.text.basicEmoji var emojiFile: TelegramMediaFile? - emojiFile = item.associatedData.animatedEmojiStickers[emoji]?.first?.file + emojiFile = item.associatedData.animatedEmojiStickers[emoji]?.first?.file._parse() if emojiFile == nil { - emojiFile = item.associatedData.animatedEmojiStickers[emoji.strippedEmoji]?.first?.file + emojiFile = item.associatedData.animatedEmojiStickers[emoji.strippedEmoji]?.first?.file._parse() } if let emojiFile = emojiFile { diff --git a/submodules/TelegramUI/Components/Chat/ChatQrCodeScreen/Sources/ChatQrCodeScreen.swift b/submodules/TelegramUI/Components/Chat/ChatQrCodeScreen/Sources/ChatQrCodeScreen.swift index fe0ddd4798..68d70b547a 100644 --- a/submodules/TelegramUI/Components/Chat/ChatQrCodeScreen/Sources/ChatQrCodeScreen.swift +++ b/submodules/TelegramUI/Components/Chat/ChatQrCodeScreen/Sources/ChatQrCodeScreen.swift @@ -1070,12 +1070,12 @@ private class ChatQrCodeScreenNode: ViewControllerTracingNode, ASScrollViewDeleg } else { defaultWallpaper = nil } - entries.append(ThemeSettingsThemeEntry(index: 0, emoticon: defaultEmoticon, emojiFile: animatedEmojiStickers[defaultEmoticon]?.first?.file, themeReference: .builtin(isDarkAppearance ? .night : .dayClassic), nightMode: isDarkAppearance, selected: selectedEmoticon == defaultEmoticon, theme: presentationData.theme, strings: presentationData.strings, wallpaper: defaultWallpaper, message: isMessage)) + entries.append(ThemeSettingsThemeEntry(index: 0, emoticon: defaultEmoticon, emojiFile: animatedEmojiStickers[defaultEmoticon]?.first?.file._parse(), themeReference: .builtin(isDarkAppearance ? .night : .dayClassic), nightMode: isDarkAppearance, selected: selectedEmoticon == defaultEmoticon, theme: presentationData.theme, strings: presentationData.strings, wallpaper: defaultWallpaper, message: isMessage)) for theme in themes { guard let emoticon = theme.emoticon else { continue } - entries.append(ThemeSettingsThemeEntry(index: entries.count, emoticon: emoticon, emojiFile: animatedEmojiStickers[emoticon]?.first?.file, themeReference: .cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil, creatorAccountId: nil)), nightMode: isDarkAppearance, selected: selectedEmoticon == theme.emoticon, theme: presentationData.theme, strings: presentationData.strings, wallpaper: nil, message: isMessage)) + entries.append(ThemeSettingsThemeEntry(index: entries.count, emoticon: emoticon, emojiFile: animatedEmojiStickers[emoticon]?.first?.file._parse(), themeReference: .cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil, creatorAccountId: nil)), nightMode: isDarkAppearance, selected: selectedEmoticon == theme.emoticon, theme: presentationData.theme, strings: presentationData.strings, wallpaper: nil, message: isMessage)) } let wallpaper: TelegramWallpaper diff --git a/submodules/TelegramUI/Components/Chat/ChatShareMessageTagView/Sources/ChatShareMessageTagView.swift b/submodules/TelegramUI/Components/Chat/ChatShareMessageTagView/Sources/ChatShareMessageTagView.swift index 555f5a2dce..8b68cfd8be 100644 --- a/submodules/TelegramUI/Components/Chat/ChatShareMessageTagView/Sources/ChatShareMessageTagView.swift +++ b/submodules/TelegramUI/Components/Chat/ChatShareMessageTagView/Sources/ChatShareMessageTagView.swift @@ -94,7 +94,7 @@ public final class ChatShareMessageTagView: UIView, UndoOverlayControllerAdditio case .builtin: for reaction in availableReactions.reactions { if reaction.value == updateReaction.reaction { - file = reaction.centerAnimation + file = reaction.centerAnimation?._parse() break } } @@ -103,7 +103,7 @@ public final class ChatShareMessageTagView: UIView, UndoOverlayControllerAdditio case .stars: for reaction in availableReactions.reactions { if reaction.value == updateReaction.reaction { - file = reaction.centerAnimation + file = reaction.centerAnimation?._parse() break } } diff --git a/submodules/TelegramUI/Components/Chat/ManagedDiceAnimationNode/Sources/ManagedDiceAnimationNode.swift b/submodules/TelegramUI/Components/Chat/ManagedDiceAnimationNode/Sources/ManagedDiceAnimationNode.swift index d08dc54f6f..284ef98d39 100644 --- a/submodules/TelegramUI/Components/Chat/ManagedDiceAnimationNode/Sources/ManagedDiceAnimationNode.swift +++ b/submodules/TelegramUI/Components/Chat/ManagedDiceAnimationNode/Sources/ManagedDiceAnimationNode.swift @@ -142,7 +142,7 @@ public final class ManagedDiceAnimationNode: ManagedAnimationNode { case let .result(_, items, _): var emojiStickers: [TelegramMediaFile] = [] for item in items { - emojiStickers.append(item.file) + emojiStickers.append(item.file._parse()) } return .single(emojiStickers) default: diff --git a/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift b/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift index d35e761b46..be3736f8ce 100644 --- a/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift +++ b/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift @@ -156,12 +156,13 @@ public func tagMessageReactions(context: AccountContext, subPeerId: EnginePeer.I } existingIds.insert(.custom(file.fileId.id)) + let itemFile = TelegramMediaFile.Accessor(file) result.append(ReactionItem( reaction: ReactionItem.Reaction(rawValue: .custom(file.fileId.id)), - appearAnimation: file, - stillAnimation: file, - listAnimation: file, - largeListAnimation: file, + appearAnimation: itemFile, + stillAnimation: itemFile, + listAnimation: itemFile, + largeListAnimation: itemFile, applicationAnimation: nil, largeApplicationAnimation: nil, isCustom: true @@ -441,6 +442,7 @@ public func topMessageReactions(context: AccountContext, message: Message, subPe break case let .custom(fileId): if let file = allowedReactionsAndFiles.files[fileId] { + let file = TelegramMediaFile.Accessor(file) result.append(ReactionItem( reaction: ReactionItem.Reaction(rawValue: .custom(file.fileId.id)), appearAnimation: file, @@ -499,7 +501,7 @@ public func effectMessageReactions(context: AccountContext) -> Signal<[ReactionI } existingIds.insert(messageEffect.id) - let mainFile: TelegramMediaFile = messageEffect.effectSticker + let mainFile = TelegramMediaFile.Accessor(messageEffect.effectSticker) result.append(ReactionItem( reaction: ReactionItem.Reaction(rawValue: .custom(messageEffect.id)), diff --git a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift index 64c2fbc605..6a255b4e5a 100644 --- a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/ChatEntityKeyboardInputNode.swift @@ -336,7 +336,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { continue } - availableGifSearchEmojies.append(EntityKeyboardComponent.GifSearchEmoji(emoji: reaction, file: file, title: title)) + availableGifSearchEmojies.append(EntityKeyboardComponent.GifSearchEmoji(emoji: reaction, file: file._parse(), title: title)) } } @@ -649,7 +649,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { } } }) - } else if let file = item.itemFile { + } else if let file = item.itemFile?._parse() { var text = "." var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? loop: for attribute in file.attributes { @@ -970,11 +970,11 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { if itemFile.isPremiumEmoji && !hasPremium { continue } - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, + itemFile: TelegramMediaFile.Accessor(itemFile), subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none @@ -1086,11 +1086,11 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { continue } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, + itemFile: TelegramMediaFile.Accessor(itemFile), subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none @@ -1177,7 +1177,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { guard let interaction else { return } - guard let file = item.itemFile else { + guard let file = item.itemFile?._parse() else { if case .icon(.add) = item.content { interaction.openStickerEditor() } @@ -1433,11 +1433,12 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode { continue } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, subgroupId: nil, + itemFile: TelegramMediaFile.Accessor(itemFile), + subgroupId: nil, icon: itemFile.isPremiumSticker ? .premium : .none, tintMode: animationData.isTemplate ? .primary : .none ) @@ -2316,10 +2317,10 @@ public final class EntityInputView: UIInputView, AttachmentTextInputPanelInputVi if groupId == AnyHashable("featuredTop") { } else { - if let file = item.itemFile { + if let file = item.itemFile?._parse() { var text = "." var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? - loop: for attribute in file.attributes { + loop: for attribute in file.attributes { switch attribute { case let .CustomEmoji(_, _, displayText, _): text = displayText diff --git a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/StickerPaneSearchContentNode.swift b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/StickerPaneSearchContentNode.swift index 23230d48ba..45312d1404 100644 --- a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/StickerPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/StickerPaneSearchContentNode.swift @@ -568,7 +568,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { func itemAt(point: CGPoint) -> (ASDisplayNode, Any)? { if !self.trendingPane.isHidden { if let (itemNode, item) = self.trendingPane.itemAt(point: self.view.convert(point, to: self.trendingPane.view)) { - return (itemNode, StickerPreviewPeekItem.pack(item.file)) + return (itemNode, StickerPreviewPeekItem.pack(item.file._parse())) } } else { if let itemNode = self.gridNode.itemNodeAtPoint(self.view.convert(point, to: self.gridNode.view)) { @@ -576,7 +576,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { return (itemNode, StickerPreviewPeekItem.found(stickerItem)) } else if let itemNode = itemNode as? StickerPaneSearchGlobalItemNode { if let (node, item) = itemNode.itemAt(point: self.view.convert(point, to: itemNode.view)) { - return (node, StickerPreviewPeekItem.pack(item.file)) + return (node, StickerPreviewPeekItem.pack(item.file._parse())) } } } diff --git a/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift b/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift index beed3cb9d5..984f2791f9 100644 --- a/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift +++ b/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift @@ -23,20 +23,17 @@ import TelegramNotices private func randomGenericReactionEffect(context: AccountContext) -> Signal { return context.engine.stickers.loadedStickerPack(reference: .emojiGenericAnimations, forceActualized: false) - |> map { result -> [TelegramMediaFile]? in + |> map { result -> TelegramMediaFile? in switch result { case let .result(_, items, _): - return items.map(\.file) + return items.randomElement()?.file._parse() default: return nil } } |> take(1) - |> mapToSignal { items -> Signal in - guard let items = items else { - return .single(nil) - } - guard let file = items.randomElement() else { + |> mapToSignal { file -> Signal in + guard let file else { return .single(nil) } return Signal { subscriber in @@ -380,14 +377,9 @@ public final class EmojiStatusSelectionController: ViewController { let filterList: [String] = ["😖", "😫", "🫠", "😨", "❓"] for featuredEmojiPack in featuredEmojiPacks { for item in featuredEmojiPack.topItems { - for attribute in item.file.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - if filterList.contains(alt) { - filteredFiles.append(item.file) - } - default: - break + if let alt = item.file.customEmojiAlt { + if filterList.contains(alt) { + filteredFiles.append(item.file._parse()) } } } @@ -531,7 +523,7 @@ public final class EmojiStatusSelectionController: ViewController { ) |> take(1) |> map { view, availableReactions, hasPremium -> [EmojiPagerContentComponent.ItemGroup] in - var result: [(String, TelegramMediaFile?, String)] = [] + var result: [(String, TelegramMediaFile.Accessor?, String)] = [] var allEmoticons: [String: String] = [:] for keyword in keywords { @@ -544,18 +536,13 @@ public final class EmojiStatusSelectionController: ViewController { guard let item = entry.item as? StickerPackItem else { continue } - for attribute in item.file.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - if !item.file.isPremiumEmoji || hasPremium { - if !alt.isEmpty, let keyword = allEmoticons[alt] { - result.append((alt, item.file, keyword)) - } else if alt == query { - result.append((alt, item.file, alt)) - } + if let alt = item.file.customEmojiAlt { + if !item.file.isPremiumEmoji || hasPremium { + if !alt.isEmpty, let keyword = allEmoticons[alt] { + result.append((alt, item.file, keyword)) + } else if alt == query { + result.append((alt, item.file, alt)) } - default: - break } } } @@ -626,11 +613,12 @@ public final class EmojiStatusSelectionController: ViewController { continue } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, subgroupId: nil, + itemFile: TelegramMediaFile.Accessor(itemFile), + subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none ) @@ -801,7 +789,8 @@ public final class EmojiStatusSelectionController: ViewController { if itemFile.isCustomTemplateEmoji { useCleanEffect = true } - for attribute in itemFile.attributes { + + for attribute in itemFile._parse().attributes { if case let .CustomEmoji(_, _, _, packReference) = attribute { switch packReference { case let .id(id, _): @@ -843,8 +832,8 @@ public final class EmojiStatusSelectionController: ViewController { context: self.context, userLocation: .other, attemptSynchronousLoad: false, - emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: itemFile.fileId.id, file: itemFile), - file: item.itemFile, + emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: itemFile.fileId.id, file: itemFile._parse()), + file: item.itemFile?._parse(), cache: animationCache, renderer: animationRenderer, placeholderColor: UIColor(white: 0.0, alpha: 0.0), @@ -1149,7 +1138,7 @@ public final class EmojiStatusSelectionController: ViewController { } } - if let previewItem = self.previewItem, let itemFile = previewItem.item.displayFile { + if let previewItem = self.previewItem, let itemFile = previewItem.item.displayFile?._parse() { let previewScreenView: ComponentView var previewScreenTransition = transition if let current = self.previewScreenView { @@ -1202,14 +1191,8 @@ public final class EmojiStatusSelectionController: ViewController { } else { var emojiString: String? if let itemFile = previewItem.item.itemFile { - attributeLoop: for attribute in itemFile.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - emojiString = alt - break attributeLoop - default: - break - } + if let alt = itemFile.customEmojiAlt { + emojiString = alt } } @@ -1222,7 +1205,7 @@ public final class EmojiStatusSelectionController: ViewController { } for reaction in availableReactions.reactions { if case let .builtin(value) = reaction.value, value == emojiString { - if let aroundAnimation = reaction.aroundAnimation { + if let aroundAnimation = reaction.aroundAnimation?._parse() { return context.account.postbox.mediaBox.resourceData(aroundAnimation.resource) |> take(1) |> map { data -> String? in @@ -1244,7 +1227,7 @@ public final class EmojiStatusSelectionController: ViewController { return } - let _ = (strongSelf.context.engine.accountData.setEmojiStatus(file: previewItem.item.itemFile, expirationDate: expirationDate) + let _ = (strongSelf.context.engine.accountData.setEmojiStatus(file: previewItem.item.itemFile?._parse(), expirationDate: expirationDate) |> deliverOnMainQueue).start() strongSelf.animateOutToStatus(item: previewItem.item, sourceLayer: result.sourceView.layer, customEffectFile: filePath, destinationView: destinationView, fromBackground: true) @@ -1351,13 +1334,13 @@ public final class EmojiStatusSelectionController: ViewController { } }) } else { - let _ = (self.context.engine.accountData.setEmojiStatus(file: item?.itemFile, expirationDate: nil) + let _ = (self.context.engine.accountData.setEmojiStatus(file: item?.itemFile?._parse(), expirationDate: nil) |> deliverOnMainQueue).start() } case let .backgroundSelection(completion): - completion(item?.itemFile) + completion(item?.itemFile?._parse()) case let .customStatusSelection(completion): - completion(item?.itemFile, nil) + completion(item?.itemFile?._parse(), nil) case let .quickReactionSelection(completion): if let item = item, let itemFile = item.itemFile { var selectedReaction: MessageReaction.Reaction? @@ -1397,14 +1380,8 @@ public final class EmojiStatusSelectionController: ViewController { if animateOutToView, let item = item, let destinationView = controller.destinationItemView() { var emojiString: String? if let itemFile = item.itemFile { - attributeLoop: for attribute in itemFile.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - emojiString = alt - break attributeLoop - default: - break - } + if let alt = itemFile.customEmojiAlt { + emojiString = alt } } @@ -1417,7 +1394,7 @@ public final class EmojiStatusSelectionController: ViewController { } for reaction in availableReactions.reactions { if case let .builtin(value) = reaction.value, value == emojiString { - if let aroundAnimation = reaction.aroundAnimation { + if let aroundAnimation = reaction.aroundAnimation?._parse() { return context.account.postbox.mediaBox.resourceData(aroundAnimation.resource) |> take(1) |> map { data -> String? in @@ -1561,11 +1538,15 @@ private func generateParabollicMotionKeyframes(from sourcePoint: CGPoint, to tar } extension EmojiPagerContentComponent.Item { - var displayFile: TelegramMediaFile? { + var displayFile: TelegramMediaFile.Accessor? { if let file = self.itemFile { return file } else if let gift = self.itemGift { - return gift.itemFile + if let itemFile = gift.itemFile { + return TelegramMediaFile.Accessor(itemFile) + } else { + return nil + } } else { return nil } diff --git a/submodules/TelegramUI/Components/EmojiSuggestionsComponent/Sources/EmojiSuggestionsComponent.swift b/submodules/TelegramUI/Components/EmojiSuggestionsComponent/Sources/EmojiSuggestionsComponent.swift index 6a21882f2b..38a60a4819 100644 --- a/submodules/TelegramUI/Components/EmojiSuggestionsComponent/Sources/EmojiSuggestionsComponent.swift +++ b/submodules/TelegramUI/Components/EmojiSuggestionsComponent/Sources/EmojiSuggestionsComponent.swift @@ -77,7 +77,7 @@ public final class EmojiSuggestionsComponent: Component { if stringRepresentation == query || (!normalizedQuery.isEmpty && stringRepresentation == normalizedQuery) { if !existingIds.contains(item.file.fileId) { existingIds.insert(item.file.fileId) - result.append(item.file) + result.append(item.file._parse()) } break } @@ -86,19 +86,14 @@ public final class EmojiSuggestionsComponent: Component { for featuredPack in featuredEmojiPacks { for item in featuredPack.topItems { - for attribute in item.file.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - if alt == query || (!normalizedQuery.isEmpty && alt == normalizedQuery) { - if !item.file.isPremiumEmoji || hasPremium { - if !existingIds.contains(item.file.fileId) { - existingIds.insert(item.file.fileId) - result.append(item.file) - } + if let alt = item.file.customEmojiAlt { + if alt == query || (!normalizedQuery.isEmpty && alt == normalizedQuery) { + if !item.file.isPremiumEmoji || hasPremium { + if !existingIds.contains(item.file.fileId) { + existingIds.insert(item.file.fileId) + result.append(item.file._parse()) } } - default: - break } } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiKeyboardItemLayer.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiKeyboardItemLayer.swift index 43ff78156c..db8ad96529 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiKeyboardItemLayer.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiKeyboardItemLayer.swift @@ -177,19 +177,21 @@ public final class EmojiKeyboardItemLayer: MultiAnimationRenderTarget { switch content { case let .animation(animationData): + let animationDataResource = animationData.resource._parse() + let loadAnimation: () -> Void = { [weak self] in guard let strongSelf = self else { return } - strongSelf.disposable = renderer.add(target: strongSelf, cache: cache, itemId: animationData.resource.resource.id.stringRepresentation, unique: false, size: pixelSize, fetch: animationCacheFetchFile(context: context, userLocation: .other, userContentType: .sticker, resource: animationData.resource, type: animationData.type.animationCacheAnimationType, keyframeOnly: pixelSize.width >= 120.0, customColor: animationData.isTemplate ? .white : nil)) + strongSelf.disposable = renderer.add(target: strongSelf, cache: cache, itemId: animationDataResource.resource.id.stringRepresentation, unique: false, size: pixelSize, fetch: animationCacheFetchFile(context: context, userLocation: .other, userContentType: .sticker, resource: animationDataResource, type: animationData.type.animationCacheAnimationType, keyframeOnly: pixelSize.width >= 120.0, customColor: animationData.isTemplate ? .white : nil)) } if attemptSynchronousLoad { - if !renderer.loadFirstFrameSynchronously(target: self, cache: cache, itemId: animationData.resource.resource.id.stringRepresentation, size: pixelSize) { + if !renderer.loadFirstFrameSynchronously(target: self, cache: cache, itemId: animationDataResource.resource.id.stringRepresentation, size: pixelSize) { self.updateDisplayPlaceholder(displayPlaceholder: true) - self.fetchDisposable = renderer.loadFirstFrame(target: self, cache: cache, itemId: animationData.resource.resource.id.stringRepresentation, size: pixelSize, fetch: animationCacheFetchFile(context: context, userLocation: .other, userContentType: .sticker, resource: animationData.resource, type: animationData.type.animationCacheAnimationType, keyframeOnly: true, customColor: animationData.isTemplate ? .white : nil), completion: { [weak self] success, isFinal in + self.fetchDisposable = renderer.loadFirstFrame(target: self, cache: cache, itemId: animationDataResource.resource.id.stringRepresentation, size: pixelSize, fetch: animationCacheFetchFile(context: context, userLocation: .other, userContentType: .sticker, resource: animationDataResource, type: animationData.type.animationCacheAnimationType, keyframeOnly: true, customColor: animationData.isTemplate ? .white : nil), completion: { [weak self] success, isFinal in if !isFinal { if !success { Queue.mainQueue().async { @@ -219,7 +221,7 @@ public final class EmojiKeyboardItemLayer: MultiAnimationRenderTarget { loadAnimation() } } else { - self.fetchDisposable = renderer.loadFirstFrame(target: self, cache: cache, itemId: animationData.resource.resource.id.stringRepresentation, size: pixelSize, fetch: animationCacheFetchFile(context: context, userLocation: .other, userContentType: .sticker, resource: animationData.resource, type: animationData.type.animationCacheAnimationType, keyframeOnly: true, customColor: animationData.isTemplate ? .white : nil), completion: { [weak self] success, isFinal in + self.fetchDisposable = renderer.loadFirstFrame(target: self, cache: cache, itemId: animationDataResource.resource.id.stringRepresentation, size: pixelSize, fetch: animationCacheFetchFile(context: context, userLocation: .other, userContentType: .sticker, resource: animationDataResource, type: animationData.type.animationCacheAnimationType, keyframeOnly: true, customColor: animationData.isTemplate ? .white : nil), completion: { [weak self] success, isFinal in if !isFinal { if !success { Queue.mainQueue().async { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 0ed6da0bb0..f997809448 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -28,9 +28,9 @@ import GenerateStickerPlaceholderImage public struct EmojiComponentReactionItem: Equatable { public var reaction: MessageReaction.Reaction - public var file: TelegramMediaFile + public var file: TelegramMediaFile.Accessor - public init(reaction: MessageReaction.Reaction, file: TelegramMediaFile) { + public init(reaction: MessageReaction.Reaction, file: TelegramMediaFile.Accessor) { self.reaction = reaction self.file = file } @@ -60,16 +60,35 @@ public final class EntityKeyboardAnimationData: Equatable { } } + public enum Resource: Equatable { + case resource(MediaResourceReference) + case file(PartialMediaReference?, TelegramMediaFile.Accessor) + + func _parse() -> MediaResourceReference { + switch self { + case let .resource(resource): + return resource + case let .file(partialReference, file): + let file = file._parse() + if let partialReference { + return partialReference.mediaReference(file).resourceReference(file.resource) + } else { + return .standalone(resource: file.resource) + } + } + } + } + public let id: Id public let type: ItemType - public let resource: MediaResourceReference + public let resource: Resource public let dimensions: CGSize public let immediateThumbnailData: Data? public let isReaction: Bool public let isTemplate: Bool public let particleColor: UIColor? - public init(id: Id, type: ItemType, resource: MediaResourceReference, dimensions: CGSize, immediateThumbnailData: Data?, isReaction: Bool, isTemplate: Bool, particleColor: UIColor? = nil) { + public init(id: Id, type: ItemType, resource: Resource, dimensions: CGSize, immediateThumbnailData: Data?, isReaction: Bool, isTemplate: Bool, particleColor: UIColor? = nil) { self.id = id self.type = type self.resource = resource @@ -80,7 +99,7 @@ public final class EntityKeyboardAnimationData: Equatable { self.particleColor = particleColor } - public convenience init(file: TelegramMediaFile, isReaction: Bool = false, partialReference: PartialMediaReference? = nil) { + public convenience init(file: TelegramMediaFile.Accessor, isReaction: Bool = false, partialReference: PartialMediaReference? = nil) { let type: ItemType if file.isVideoSticker || file.isVideoEmoji { type = .video @@ -91,13 +110,8 @@ public final class EntityKeyboardAnimationData: Equatable { } let isTemplate = file.isCustomTemplateEmoji - let resourceReference: MediaResourceReference - if let partialReference { - resourceReference = partialReference.mediaReference(file).resourceReference(file.resource) - } else { - resourceReference = .standalone(resource: file.resource) - } - self.init(id: .file(file.fileId), type: type, resource: resourceReference, dimensions: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), immediateThumbnailData: file.immediateThumbnailData, isReaction: isReaction, isTemplate: isTemplate) + let resource: Resource = .file(partialReference, file) + self.init(id: .file(file.fileId), type: type, resource: resource, dimensions: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), immediateThumbnailData: file.immediateThumbnailData, isReaction: isReaction, isTemplate: isTemplate) } public convenience init?(gift: StarGift.UniqueGift) { @@ -113,7 +127,7 @@ public final class EntityKeyboardAnimationData: Equatable { } if let file, let color { let resourceReference: MediaResourceReference = .standalone(resource: file.resource) - self.init(id: .gift(gift.slug), type: .lottie, resource: resourceReference, dimensions: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), immediateThumbnailData: file.immediateThumbnailData, isReaction: false, isTemplate: false, particleColor: color) + self.init(id: .gift(gift.slug), type: .lottie, resource: .resource(resourceReference), dimensions: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), immediateThumbnailData: file.immediateThumbnailData, isReaction: false, isTemplate: false, particleColor: color) } else { return nil } @@ -124,7 +138,7 @@ public final class EntityKeyboardAnimationData: Equatable { return true } - if lhs.resource.resource.id != rhs.resource.resource.id { + if lhs.resource != rhs.resource { return false } if lhs.dimensions != rhs.dimensions { @@ -401,7 +415,7 @@ public final class EmojiPagerContentComponent: Component { public let animationData: EntityKeyboardAnimationData? public let content: ItemContent - public let itemFile: TelegramMediaFile? + public let itemFile: TelegramMediaFile.Accessor? public let itemGift: StarGift.UniqueGift? public let subgroupId: Int32? public let icon: Icon @@ -410,7 +424,7 @@ public final class EmojiPagerContentComponent: Component { public init( animationData: EntityKeyboardAnimationData?, content: ItemContent, - itemFile: TelegramMediaFile?, + itemFile: TelegramMediaFile.Accessor?, itemGift: StarGift.UniqueGift? = nil, subgroupId: Int32?, icon: Icon, @@ -429,7 +443,7 @@ public final class EmojiPagerContentComponent: Component { if lhs === rhs { return true } - if lhs.animationData?.resource.resource.id != rhs.animationData?.resource.resource.id { + if lhs.animationData?.resource != rhs.animationData?.resource { return false } if lhs.content != rhs.content { @@ -1723,7 +1737,7 @@ public final class EmojiPagerContentComponent: Component { }) } - component.animationRenderer.setFrameIndex(itemId: animationData.resource.resource.id.stringRepresentation, size: itemLayer.pixelSize, frameIndex: sourceItem.frameIndex, placeholder: sourceItem.placeholder) + component.animationRenderer.setFrameIndex(itemId: animationData.resource._parse().resource.id.stringRepresentation, size: itemLayer.pixelSize, frameIndex: sourceItem.frameIndex, placeholder: sourceItem.placeholder) } else { let distance = itemLayer.position.y - itemLayout.frame(groupIndex: 0, itemIndex: 0).midY let maxDistance = self.bounds.height @@ -4126,7 +4140,7 @@ public final class EmojiPagerContentComponent: Component { if itemLayer.displayPlaceholder { return nil } - return (item.1.groupId, itemLayer, file) + return (item.1.groupId, itemLayer, file._parse()) }) let keyboardChildEnvironment = environment[EntityKeyboardChildEnvironment.self].value diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift index 3d3b7deaf0..ec2cf27bd0 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift @@ -134,7 +134,7 @@ public extension EmojiPagerContentComponent { |> map { result -> [TelegramMediaFile] in switch result { case let .result(_, items, _): - return items.map(\.file) + return items.map({ $0.file._parse() }) default: return [] } @@ -148,7 +148,7 @@ public extension EmojiPagerContentComponent { |> map { result -> [TelegramMediaFile] in switch result { case let .result(_, items, _): - return items.map(\.file) + return items.map({ $0.file._parse() }) default: return [] } @@ -164,7 +164,7 @@ public extension EmojiPagerContentComponent { |> map { result -> [TelegramMediaFile] in switch result { case let .result(_, items, _): - return items.map(\.file) + return items.map({ $0.file._parse() }) default: return [] } @@ -198,6 +198,11 @@ public extension EmojiPagerContentComponent { searchCategories = .single(nil) } + #if DEBUG || true + var isFirstTime = true + let measure_startTime = CFAbsoluteTimeGetCurrent() + #endif + let emojiItems: Signal = combineLatest( context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), forceHasPremium ? .single(true) : hasPremium(context: context, chatPeerId: chatPeerId, premiumIfSavedMessages: premiumIfSavedMessages), @@ -209,6 +214,52 @@ public extension EmojiPagerContentComponent { ApplicationSpecificNotice.dismissedTrendingEmojiPacks(accountManager: context.sharedContext.accountManager) ) |> map { view, hasPremium, featuredEmojiPacks, availableReactions, searchCategories, iconStatusEmoji, peerSpecificPack, dismissedTrendingEmojiPacks -> EmojiPagerContentComponent in + #if DEBUG || true + if isFirstTime { + var files: [TelegramMediaFile] = [] + files.removeAll() + + if "".isEmpty { + for entry in view.entries { + guard let item = entry.item as? StickerPackItem else { + continue + } + files.append(item.file._parse()) + } + for featuredEmojiPack in featuredEmojiPacks { + for item in featuredEmojiPack.topItems { + files.append(item.file._parse()) + } + } + if let availableReactions { + for reactionItem in availableReactions.reactions { + files.append(reactionItem.staticIcon._parse()) + files.append(reactionItem.appearAnimation._parse()) + files.append(reactionItem.selectAnimation._parse()) + files.append(reactionItem.activateAnimation._parse()) + files.append(reactionItem.effectAnimation._parse()) + if let aroundAnimation = reactionItem.aroundAnimation { + files.append(aroundAnimation._parse()) + } + if let centerAnimation = reactionItem.centerAnimation { + files.append(centerAnimation._parse()) + } + } + } + Thread.current.threadDictionary["afwefw"] = files + } + + isFirstTime = false + let measuredTime = CFAbsoluteTimeGetCurrent() - measure_startTime + for file in files { + if file.fileId.id == 123 { + print("Interesting") + } + } + print("emojiInputData init isMainThread: \(Thread.isMainThread): \(measuredTime * 1000.0) ms") + } + #endif + struct ItemGroup { var supergroupId: AnyHashable var id: AnyHashable @@ -295,7 +346,7 @@ public extension EmojiPagerContentComponent { animationData = EntityKeyboardAnimationData( id: .stickerPackThumbnail(featuredEmojiPack.info.id), type: type, - resource: .stickerPackThumbnail(stickerPack: .id(id: featuredEmojiPack.info.id.id, accessHash: featuredEmojiPack.info.accessHash), resource: thumbnail.resource), + resource: .resource(.stickerPackThumbnail(stickerPack: .id(id: featuredEmojiPack.info.id.id, accessHash: featuredEmojiPack.info.accessHash), resource: thumbnail.resource)), dimensions: thumbnail.dimensions.cgSize, immediateThumbnailData: featuredEmojiPack.info.immediateThumbnailData, isReaction: false, @@ -440,11 +491,11 @@ public extension EmojiPagerContentComponent { let resultItem: EmojiPagerContentComponent.Item - let animationData = EntityKeyboardAnimationData(file: file) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(file)) resultItem = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: file, + itemFile: TelegramMediaFile.Accessor(file), subgroupId: nil, icon: .none, tintMode: tintMode @@ -499,11 +550,11 @@ public extension EmojiPagerContentComponent { let resultItem: EmojiPagerContentComponent.Item - let animationData = EntityKeyboardAnimationData(file: file) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(file)) resultItem = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: file, + itemFile: TelegramMediaFile.Accessor(file), subgroupId: nil, icon: .none, tintMode: tintMode @@ -530,17 +581,8 @@ public extension EmojiPagerContentComponent { if file.isCustomTemplateEmoji { tintMode = .accent } - for attribute in file.attributes { - if case let .CustomEmoji(_, _, _, packReference) = attribute { - switch packReference { - case let .id(id, _): - if id == 773947703670341676 || id == 2964141614563343 { - tintMode = .accent - } - default: - break - } - } + if file.internal_isHardcodedTemplateEmoji { + tintMode = .accent } let resultItem: EmojiPagerContentComponent.Item @@ -582,17 +624,8 @@ public extension EmojiPagerContentComponent { if file.isCustomTemplateEmoji { tintMode = .accent } - for attribute in file.attributes { - if case let .CustomEmoji(_, _, _, packReference) = attribute { - switch packReference { - case let .id(id, _): - if id == 773947703670341676 || id == 2964141614563343 { - tintMode = .accent - } - default: - break - } - } + if file.internal_isHardcodedTemplateEmoji { + tintMode = .accent } let animationData = EntityKeyboardAnimationData(file: file) @@ -700,11 +733,11 @@ public extension EmojiPagerContentComponent { let resultItem: EmojiPagerContentComponent.Item - let animationData = EntityKeyboardAnimationData(file: file) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(file)) resultItem = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: file, + itemFile: TelegramMediaFile.Accessor(file), subgroupId: nil, icon: .none, tintMode: tintMode @@ -733,17 +766,8 @@ public extension EmojiPagerContentComponent { if file.isCustomTemplateEmoji { tintMode = .accent } - for attribute in file.attributes { - if case let .CustomEmoji(_, _, _, packReference) = attribute { - switch packReference { - case let .id(id, _): - if id == 773947703670341676 || id == 2964141614563343 { - tintMode = .accent - } - default: - break - } - } + if file.internal_isHardcodedTemplateEmoji { + tintMode = .accent } let animationData = EntityKeyboardAnimationData(file: file) @@ -757,10 +781,6 @@ public extension EmojiPagerContentComponent { ) if let groupIndex = itemGroupIndexById[groupId] { - /*if itemGroups[groupIndex].items.count >= (5 + 8) * 8 { - break - }*/ - itemGroups[groupIndex].items.append(resultItem) } } @@ -971,7 +991,7 @@ public extension EmojiPagerContentComponent { continue } - let animationFile: TelegramMediaFile + let animationFile: TelegramMediaFile.Accessor let icon: EmojiPagerContentComponent.Item.Icon switch item.content { @@ -1145,17 +1165,8 @@ public extension EmojiPagerContentComponent { if file.isCustomTemplateEmoji { tintMode = .accent } - for attribute in file.attributes { - if case let .CustomEmoji(_, _, _, packReference) = attribute { - switch packReference { - case let .id(id, _): - if id == 773947703670341676 || id == 2964141614563343 { - tintMode = .accent - } - default: - break - } - } + if file.internal_isHardcodedTemplateEmoji { + tintMode = .accent } let animationData = EntityKeyboardAnimationData(file: file) @@ -1219,17 +1230,8 @@ public extension EmojiPagerContentComponent { tintMode = .accent } } - for attribute in file.attributes { - if case let .CustomEmoji(_, _, _, packReference) = attribute { - switch packReference { - case let .id(id, _): - if id == 773947703670341676 || id == 2964141614563343 { - tintMode = .accent - } - default: - break - } - } + if file.internal_isHardcodedTemplateEmoji { + tintMode = .accent } let animationData = EntityKeyboardAnimationData(file: file) @@ -1277,11 +1279,11 @@ public extension EmojiPagerContentComponent { tintMode = .primary } - let animationData = EntityKeyboardAnimationData(file: file) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(file)) resultItem = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: file, + itemFile: TelegramMediaFile.Accessor(file), subgroupId: nil, icon: .none, tintMode: tintMode @@ -1368,14 +1370,6 @@ public extension EmojiPagerContentComponent { continue } - #if DEBUG && false - let fbData = item.file.encodeToFlatBuffersData() - var byteBuffer = ByteBuffer(data: fbData) - let flatBuffersObject: TelegramCore_TelegramMediaFile = try! getCheckedRoot(byteBuffer: &byteBuffer) - let fbObject = try! TelegramMediaFile(flatBuffersObject: flatBuffersObject) - assert(item.file == fbObject) - #endif - var icon: EmojiPagerContentComponent.Item.Icon = .none if [.reaction(onlyTop: false), .quickReaction].contains(subject), !hasPremium { icon = .locked @@ -1455,7 +1449,7 @@ public extension EmojiPagerContentComponent { headerItem = EntityKeyboardAnimationData( id: .stickerPackThumbnail(info.id), type: type, - resource: .stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource), + resource: .resource(.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)), dimensions: thumbnail.dimensions.cgSize, immediateThumbnailData: info.immediateThumbnailData, isReaction: false, @@ -1542,7 +1536,7 @@ public extension EmojiPagerContentComponent { headerItem = EntityKeyboardAnimationData( id: .stickerPackThumbnail(info.id), type: type, - resource: .stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource), + resource: .resource(.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)), dimensions: thumbnail.dimensions.cgSize, immediateThumbnailData: info.immediateThumbnailData, isReaction: false, @@ -1839,7 +1833,7 @@ public extension EmojiPagerContentComponent { 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), + resource: .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, @@ -2076,7 +2070,7 @@ public extension EmojiPagerContentComponent { headerItem = EntityKeyboardAnimationData( id: .stickerPackThumbnail(info.id), type: type, - resource: .stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource), + resource: .resource(.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)), dimensions: thumbnail.dimensions.cgSize, immediateThumbnailData: info.immediateThumbnailData, isReaction: false, @@ -2155,7 +2149,7 @@ public extension EmojiPagerContentComponent { headerItem = EntityKeyboardAnimationData( id: .stickerPackThumbnail(info.id), type: type, - resource: .stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource), + resource: .resource(.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource)), dimensions: thumbnail.dimensions.cgSize, immediateThumbnailData: info.immediateThumbnailData, isReaction: false, @@ -2315,11 +2309,11 @@ public extension EmojiPagerContentComponent { } } - let animationData = EntityKeyboardAnimationData(file: itemFile, partialReference: .none) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile), partialReference: .none) let resultItem = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, + itemFile: TelegramMediaFile.Accessor(itemFile), subgroupId: nil, icon: icon, tintMode: tintMode diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiSearchContent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiSearchContent.swift index 1820835356..7e04ed8f6e 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiSearchContent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiSearchContent.swift @@ -234,7 +234,7 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode ) |> take(1) |> map { view, availableReactions, hasPremium -> [EmojiPagerContentComponent.ItemGroup] in - var result: [(String, TelegramMediaFile?, String)] = [] + var result: [(String, TelegramMediaFile.Accessor?, String)] = [] var allEmoticons: [String: String] = [:] for keyword in keywords { @@ -247,18 +247,16 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode guard let item = entry.item as? StickerPackItem else { continue } - for attribute in item.file.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - if !item.file.isPremiumEmoji || hasPremium { + + if item.file.isCustomEmoji { + if !item.file.isPremiumEmoji || hasPremium { + if let alt = item.file.customEmojiAlt { if !alt.isEmpty, let keyword = allEmoticons[alt] { result.append((alt, item.file, keyword)) } else if alt == query { result.append((alt, item.file, alt)) } } - default: - break } } } @@ -329,11 +327,11 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode continue } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, + itemFile: TelegramMediaFile.Accessor(itemFile), subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none diff --git a/submodules/TelegramUI/Components/EntityKeyboardGifContent/Sources/GifContext.swift b/submodules/TelegramUI/Components/EntityKeyboardGifContent/Sources/GifContext.swift index b3f29327b0..b888b84842 100644 --- a/submodules/TelegramUI/Components/EntityKeyboardGifContent/Sources/GifContext.swift +++ b/submodules/TelegramUI/Components/EntityKeyboardGifContent/Sources/GifContext.swift @@ -200,7 +200,7 @@ public final class GifContext { var items: [GifPagerContentComponent.Item] = [] for gifItem in savedGifs { items.append(GifPagerContentComponent.Item( - file: .savedGif(media: gifItem.contents.get(RecentMediaItem.self)!.media), + file: .savedGif(media: gifItem.contents.get(RecentMediaItem.self)!.media._parse()), contextResult: nil )) } diff --git a/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackCurrentItem.swift b/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackCurrentItem.swift index a2548b8368..e29543ef28 100644 --- a/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackCurrentItem.swift +++ b/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackCurrentItem.swift @@ -267,7 +267,7 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode { var file: TelegramMediaFile? var previousFile: TelegramMediaFile? if let currentItem = currentItem, case let .found(_, topItem, _) = currentItem.content { - previousFile = topItem?.file + previousFile = topItem?.file._parse() } switch item.content { @@ -278,7 +278,7 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode { titleAttributedString = NSAttributedString(string: item.strings.Channel_Stickers_Searching, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor) statusAttributedString = NSAttributedString(string: "", font: statusFont, textColor: item.theme.list.itemSecondaryTextColor) case let .found(packInfo, topItem, subtitle): - file = topItem?.file + file = topItem?.file._parse() titleAttributedString = NSAttributedString(string: packInfo.title, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor) statusAttributedString = NSAttributedString(string: subtitle, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor) } diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index ed70d21472..aa05dc3e44 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -4703,11 +4703,8 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID |> map { result -> TelegramMediaFile? in if case let .result(_, items, _) = result, let match = items.first(where: { item in var displayText: String? - for attribute in item.file.attributes { - if case let .CustomEmoji(_, _, alt, _) = attribute { - displayText = alt - break - } + if let alt = item.file.customEmojiAlt { + displayText = alt } if let displayText, displayText.hasPrefix(flag) { return true @@ -4715,7 +4712,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID return false } }) { - return match.file + return match.file._parse() } else { return nil } @@ -5113,7 +5110,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID if let reaction = self.availableReactions.first(where: { reaction in return reaction.reaction.rawValue == .builtin(heart) }) { - let stickerEntity = DrawingStickerEntity(content: .file(.standalone(media: reaction.stillAnimation), .reaction(.builtin(heart), .white))) + let stickerEntity = DrawingStickerEntity(content: .file(.standalone(media: reaction.stillAnimation._parse()), .reaction(.builtin(heart), .white))) self.interaction?.insertEntity(stickerEntity, scale: 1.175) } diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerPackListContextItem.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerPackListContextItem.swift index 51729f2efc..e33448bbe4 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerPackListContextItem.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerPackListContextItem.swift @@ -53,14 +53,15 @@ private final class StickerPackListContextItemNode: ASDisplayNode, ContextMenuCu continue } let thumbSize = CGSize(width: 24.0, height: 24.0) - let thumbnailResource = pack.thumbnail?.resource ?? topItem?.file.resource + let topItemFile = topItem?.file._parse() + let thumbnailResource = pack.thumbnail?.resource ?? topItemFile?.resource let thumbnailIconSource: ContextMenuActionItemIconSource? if let thumbnailResource { var resourceId: Int64 = 0 if let resource = thumbnailResource as? CloudDocumentMediaResource { resourceId = resource.fileId } - let thumbnailFile = topItem?.file ?? TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: resourceId), partialReference: nil, resource: thumbnailResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "image/webp", size: thumbnailResource.size ?? 0, attributes: [], alternativeRepresentations: []) + let thumbnailFile = topItemFile ?? TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: resourceId), partialReference: nil, resource: thumbnailResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "image/webp", size: thumbnailResource.size ?? 0, attributes: [], alternativeRepresentations: []) let _ = freeMediaFileInteractiveFetched(account: item.context.account, userLocation: .other, fileReference: .stickerPack(stickerPack: .id(id: pack.id.id, accessHash: pack.accessHash), media: thumbnailFile)).start() thumbnailIconSource = ContextMenuActionItemIconSource( diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/Weather.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/Weather.swift index bd9b3e8d71..fb1624ad74 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/Weather.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/Weather.swift @@ -73,7 +73,7 @@ func getWeather(context: AccountContext, load: Bool) -> Signal map { view, availableReactions, hasPremium, foundPacks, foundEmoji, foundLocalPacks -> [EmojiPagerContentComponent.ItemGroup] in - var result: [(String, TelegramMediaFile?, String)] = [] + var result: [(String, TelegramMediaFile.Accessor?, String)] = [] var allEmoticons: [String: String] = [:] for keyword in keywords { @@ -712,9 +712,9 @@ final class PeerAllowedReactionsScreenComponent: Component { switch attribute { case let .CustomEmoji(_, _, alt, _): if !alt.isEmpty, let keyword = allEmoticons[alt] { - result.append((alt, itemFile, keyword)) + result.append((alt, TelegramMediaFile.Accessor(itemFile), keyword)) } else if alt == query { - result.append((alt, itemFile, alt)) + result.append((alt, TelegramMediaFile.Accessor(itemFile), alt)) } default: break @@ -726,18 +726,13 @@ final class PeerAllowedReactionsScreenComponent: Component { guard let item = entry.item as? StickerPackItem else { continue } - for attribute in item.file.attributes { - switch attribute { - case let .CustomEmoji(_, _, alt, _): - if !item.file.isPremiumEmoji { - if !alt.isEmpty, let keyword = allEmoticons[alt] { - result.append((alt, item.file, keyword)) - } else if alt == query { - result.append((alt, item.file, alt)) - } + if !item.file.isPremiumEmoji { + if let alt = item.file.customEmojiAlt { + if !alt.isEmpty, let keyword = allEmoticons[alt] { + result.append((alt, item.file, keyword)) + } else if alt == query { + result.append((alt, item.file, alt)) } - default: - break } } } @@ -877,11 +872,12 @@ final class PeerAllowedReactionsScreenComponent: Component { continue } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, subgroupId: nil, + itemFile: TelegramMediaFile.Accessor(itemFile), + subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none ) @@ -1855,7 +1851,7 @@ public class PeerAllowedReactionsScreen: ViewControllerComponentContainer { } else { if case let .custom(fileId) = reaction { if let file = files[fileId] { - result.append(EmojiComponentReactionItem(reaction: reaction, file: file)) + result.append(EmojiComponentReactionItem(reaction: reaction, file: TelegramMediaFile.Accessor(file))) } } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift index 344ef5873f..b4992663c4 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift @@ -616,7 +616,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { var file: TelegramMediaFile? switch leftIcon { case .birthday: - file = context.animatedEmojiStickersValue["🎂"]?.first?.file + file = context.animatedEmojiStickersValue["🎂"]?.first?.file._parse() } if let file { diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoBirthdayOverlay.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoBirthdayOverlay.swift index 103d3d82a4..d6e4eec46c 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoBirthdayOverlay.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoBirthdayOverlay.swift @@ -45,11 +45,11 @@ final class PeerInfoBirthdayOverlay: ASDisplayNode { var effectFile: FileMediaReference? if case let .result(_, items, _) = animatedEmoji { let randomKey = ["🎉", "🎈", "🎆"].randomElement()! - outer: for item in items { + outer: for item in items { let indexKeys = item.getStringRepresentationsOfIndexKeys() for key in indexKeys { if key == randomKey { - effectFile = .stickerPack(stickerPack: .animatedEmojiAnimations, media: item.file) + effectFile = .stickerPack(stickerPack: .animatedEmojiAnimations, media: item.file._parse()) break outer } } @@ -63,7 +63,7 @@ final class PeerInfoBirthdayOverlay: ASDisplayNode { let indexKeys = item.getStringRepresentationsOfIndexKeys() for key in indexKeys { if key == ageKey { - numberFiles.append(.stickerPack(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), media: item.file)) + numberFiles.append(.stickerPack(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), media: item.file._parse())) } } } @@ -185,7 +185,7 @@ final class PeerInfoBirthdayOverlay: ASDisplayNode { let indexKeys = item.getStringRepresentationsOfIndexKeys() for key in indexKeys { if ["🎉", "🎈", "🎆"].contains(key) { - signals.append(freeMediaFileInteractiveFetched(account: context.account, userLocation: .peer(context.account.peerId), fileReference: .stickerPack(stickerPack: .animatedEmojiAnimations, media: item.file))) + signals.append(freeMediaFileInteractiveFetched(account: context.account, userLocation: .peer(context.account.peerId), fileReference: .stickerPack(stickerPack: .animatedEmojiAnimations, media: item.file._parse()))) } } } @@ -196,7 +196,7 @@ final class PeerInfoBirthdayOverlay: ASDisplayNode { let indexKeys = item.getStringRepresentationsOfIndexKeys() for key in indexKeys { if ageKeys.contains(key) { - signals.append(freeMediaFileInteractiveFetched(account: context.account, userLocation: .peer(context.account.peerId), fileReference: .stickerPack(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), media: item.file))) + signals.append(freeMediaFileInteractiveFetched(account: context.account, userLocation: .peer(context.account.peerId), fileReference: .stickerPack(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), media: item.file._parse()))) } } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift index 84fee2862f..782bb722a9 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift @@ -952,7 +952,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { } |> mapToSignal { result -> Signal<(TelegramMediaFile, LoadedStickerPack)?, NoError> in if case let .result(_, items, _) = result { - return .single(items.first.flatMap { ($0.file, result) }) + return .single(items.first.flatMap { ($0.file._parse(), result) }) } else { return .complete() } diff --git a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift index fe6a74bcd5..df8ae9b171 100644 --- a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift +++ b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift @@ -306,7 +306,7 @@ final class BusinessIntroSetupScreenComponent: Component { return } - self.stickerFile = itemFile + self.stickerFile = itemFile._parse() self.displayStickerInput = false self.stickerSearchDisposable.set(nil) @@ -490,11 +490,11 @@ final class BusinessIntroSetupScreenComponent: Component { } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, + itemFile: TelegramMediaFile.Accessor(itemFile), subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none @@ -581,11 +581,12 @@ final class BusinessIntroSetupScreenComponent: Component { continue } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, subgroupId: nil, + itemFile: TelegramMediaFile.Accessor(itemFile), + subgroupId: nil, icon: itemFile.isPremiumSticker ? .premium : .none, tintMode: animationData.isTemplate ? .primary : .none ) diff --git a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ItemListReactionItem.swift b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ItemListReactionItem.swift index d44e1374d5..75659198ad 100644 --- a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ItemListReactionItem.swift +++ b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ItemListReactionItem.swift @@ -331,7 +331,7 @@ public class ItemListReactionItemNode: ListViewItemNode, ItemListItemNode { if let availableReactions = item.availableReactions { for reaction in availableReactions.reactions { if reaction.value == item.reaction { - animationContent = .file(file: reaction.selectAnimation) + animationContent = .file(file: reaction.selectAnimation._parse()) break } } @@ -342,7 +342,7 @@ public class ItemListReactionItemNode: ListViewItemNode, ItemListItemNode { if let availableReactions = item.availableReactions { for reaction in availableReactions.reactions { if reaction.value == item.reaction { - animationContent = .file(file: reaction.selectAnimation) + animationContent = .file(file: reaction.selectAnimation._parse()) break } } diff --git a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift index bdda9120b4..301cbe8927 100644 --- a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift +++ b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift @@ -194,6 +194,7 @@ class ReactionChatPreviewItemNode: ListViewItemNode { return } if let itemFile = files[fileId] { + let itemFile = TelegramMediaFile.Accessor(itemFile) let reactionItem = ReactionItem( reaction: ReactionItem.Reaction(rawValue: .custom(itemFile.fileId.id)), appearAnimation: itemFile, diff --git a/submodules/TelegramUI/Components/Settings/ThemeCarouselItem/Sources/ThemeCarouselItem.swift b/submodules/TelegramUI/Components/Settings/ThemeCarouselItem/Sources/ThemeCarouselItem.swift index 68e12157f4..b5340ad252 100644 --- a/submodules/TelegramUI/Components/Settings/ThemeCarouselItem/Sources/ThemeCarouselItem.swift +++ b/submodules/TelegramUI/Components/Settings/ThemeCarouselItem/Sources/ThemeCarouselItem.swift @@ -875,7 +875,7 @@ public class ThemeCarouselThemeItemNode: ListViewItemNode, ItemListItemNode { hasCurrentTheme = true } let emojiFile = theme.emoticon.flatMap { item.animatedEmojiStickers[$0]?.first?.file } - entries.append(ThemeCarouselThemeEntry(index: index, emojiFile: emojiFile, themeReference: theme, nightMode: item.nightMode, channelMode: item.channelMode, themeSpecificAccentColors: item.themeSpecificAccentColors, themeSpecificChatWallpapers: item.themeSpecificChatWallpapers, selected: selected, theme: item.theme, strings: item.strings, wallpaper: nil)) + entries.append(ThemeCarouselThemeEntry(index: index, emojiFile: emojiFile?._parse(), themeReference: theme, nightMode: item.nightMode, channelMode: item.channelMode, themeSpecificAccentColors: item.themeSpecificAccentColors, themeSpecificChatWallpapers: item.themeSpecificChatWallpapers, selected: selected, theme: item.theme, strings: item.strings, wallpaper: nil)) index += 1 } diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift index 1f32b66fb4..9cc18c2c11 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift @@ -418,7 +418,7 @@ final class ThemeGridControllerNode: ASDisplayNode { if let selectedWallpaper, !selectedWallpaper.isEmoticon { entries.append(ThemeGridControllerEntry(index: index, theme: presentationData.theme, wallpaper: selectedWallpaper, channelMode: true, isEditable: false, isSelected: true)) } else { - let emojiFile = context.animatedEmojiStickersValue["❌"]?.first?.file + let emojiFile = context.animatedEmojiStickersValue["❌"]?.first?.file._parse() entries.append(ThemeGridControllerEntry(index: index, theme: presentationData.theme, wallpaper: .color(0), isEmpty: true, emoji: emojiFile, channelMode: true, isEditable: false, isSelected: selectedWallpaper == nil)) } index += 1 @@ -441,7 +441,7 @@ final class ThemeGridControllerNode: ASDisplayNode { } let emoji = context.animatedEmojiStickersValue[themeEmoticon] - entries.append(ThemeGridControllerEntry(index: index, theme: presentationData.theme, wallpaper: updatedWallpaper, emoji: emoji?.first?.file, channelMode: true, isEditable: false, isSelected: isSelected)) + entries.append(ThemeGridControllerEntry(index: index, theme: presentationData.theme, wallpaper: updatedWallpaper, emoji: emoji?.first?.file._parse(), channelMode: true, isEditable: false, isSelected: isSelected)) index += 1 } } else { diff --git a/submodules/TelegramUI/Components/StickerPickerScreen/Sources/StickerPickerScreen.swift b/submodules/TelegramUI/Components/StickerPickerScreen/Sources/StickerPickerScreen.swift index e69fd70984..033efa1e4a 100644 --- a/submodules/TelegramUI/Components/StickerPickerScreen/Sources/StickerPickerScreen.swift +++ b/submodules/TelegramUI/Components/StickerPickerScreen/Sources/StickerPickerScreen.swift @@ -896,7 +896,7 @@ public class StickerPickerScreen: ViewController { } }) }) - } else if let file = item.itemFile { + } else if let file = item.itemFile?._parse() { if controller.completion(.file(.standalone(media: file), .sticker)) { controller.dismiss(animated: true) } @@ -1119,11 +1119,11 @@ public class StickerPickerScreen: ViewController { if itemFile.isPremiumEmoji && !hasPremium { continue } - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, + itemFile: TelegramMediaFile.Accessor(itemFile), subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none @@ -1180,11 +1180,12 @@ public class StickerPickerScreen: ViewController { continue } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, subgroupId: nil, + itemFile: TelegramMediaFile.Accessor(itemFile), + subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none ) @@ -1289,7 +1290,7 @@ public class StickerPickerScreen: ViewController { content.stickers?.inputInteractionHolder.inputInteraction = EmojiPagerContentComponent.InputInteraction( performItemAction: { [weak self] groupId, item, _, _, _, _ in - guard let self, let controller = self.controller, let file = item.itemFile else { + guard let self, let controller = self.controller, let file = item.itemFile?._parse() else { return } let presentationData = controller.context.sharedContext.currentPresentationData.with { $0 } @@ -1467,11 +1468,12 @@ public class StickerPickerScreen: ViewController { continue } existingIds.insert(itemFile.fileId) - let animationData = EntityKeyboardAnimationData(file: itemFile) + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile)) let item = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: itemFile, subgroupId: nil, + itemFile: TelegramMediaFile.Accessor(itemFile), + subgroupId: nil, icon: .none, tintMode: animationData.isTemplate ? .primary : .none ) @@ -2733,7 +2735,7 @@ final class StoryStickersContentView: UIView, EmojiCustomContentView { theme: theme, title: stringForTemperature(24), iconName: "☀️", - iconFile: self.context.animatedEmojiStickersValue["☀️"]?.first?.file, + iconFile: self.context.animatedEmojiStickersValue["☀️"]?.first?.file._parse(), useOpaqueTheme: useOpaqueTheme, tintContainerView: self.tintContainerView ) diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift index 212e669dbf..dabc123237 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift @@ -1876,7 +1876,7 @@ public func preloadStoryMedia(context: AccountContext, info: StoryPreloadInfo) - for reaction in availableReactions.reactions { for value in builtinReactions { if case .builtin(value) = reaction.value { - files.append(reaction.selectAnimation) + files.append(reaction.selectAnimation._parse()) } } } @@ -2110,7 +2110,7 @@ public func waitUntilStoryMediaPreloaded(context: AccountContext, peerId: Engine for reaction in availableReactions.reactions { for value in builtinReactions { if case .builtin(value) = reaction.value { - files.append(reaction.selectAnimation) + files.append(reaction.selectAnimation._parse()) } } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift index 6ce4ea56fc..72f8685b71 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift @@ -89,7 +89,7 @@ public func storyPreviewWithAddedReactions( guard let file = item.centerAnimation else { break } - return loadFile(reaction, file) + return loadFile(reaction, file._parse()) } } return .single((reaction, nil)) @@ -339,7 +339,7 @@ final class StoryItemOverlaysView: UIView { if let availableReactions { for reactionItem in availableReactions.reactionItems { if reactionItem.reaction.rawValue == reaction { - file = reactionItem.stillAnimation + file = reactionItem.stillAnimation._parse() break } } @@ -367,7 +367,7 @@ final class StoryItemOverlaysView: UIView { if let availableReactions { for reactionItem in availableReactions.reactionItems { if reactionItem.reaction.rawValue == reaction { - file = reactionItem.stillAnimation + file = reactionItem.stillAnimation._parse() break } } @@ -790,7 +790,7 @@ final class StoryItemOverlaysView: UIView { let itemSize = itemView.update( context: context, emoji: emoji, - emojiFile: context.animatedEmojiStickersValue[emoji]?.first?.file, + emojiFile: context.animatedEmojiStickersValue[emoji]?.first?.file._parse(), temperature: temperature, color: color, synchronous: attemptSynchronous, diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 7be24715ce..97f1f3c842 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -1738,7 +1738,7 @@ public final class StoryItemSetContainerComponent: Component { if let availableReactions = component.availableReactions { for availableReaction in availableReactions.reactionItems { if availableReaction.reaction.rawValue == value { - centerAnimation = availableReaction.listAnimation + centerAnimation = availableReaction.listAnimation._parse() break } } @@ -1749,7 +1749,7 @@ public final class StoryItemSetContainerComponent: Component { if let availableReactions = component.availableReactions { for availableReaction in availableReactions.reactionItems { if availableReaction.reaction.rawValue == value { - centerAnimation = availableReaction.listAnimation + centerAnimation = availableReaction.listAnimation._parse() break } } @@ -2951,7 +2951,7 @@ public final class StoryItemSetContainerComponent: Component { if let availableReactions = component.availableReactions { for availableReaction in availableReactions.reactionItems { if availableReaction.reaction.rawValue == value { - centerAnimation = availableReaction.listAnimation + centerAnimation = availableReaction.listAnimation._parse() break } } @@ -2962,7 +2962,7 @@ public final class StoryItemSetContainerComponent: Component { if let availableReactions = component.availableReactions { for availableReaction in availableReactions.reactionItems { if availableReaction.reaction.rawValue == value { - centerAnimation = availableReaction.listAnimation + centerAnimation = availableReaction.listAnimation._parse() break } } @@ -4582,7 +4582,7 @@ public final class StoryItemSetContainerComponent: Component { var animation: TelegramMediaFile? for reaction in availableReactions.reactions { if reaction.value == updateReaction.reaction { - animation = reaction.centerAnimation + animation = reaction.centerAnimation?._parse() break } } @@ -5989,7 +5989,7 @@ public final class StoryItemSetContainerComponent: Component { placeholderColor: .clear, attemptSynchronous: true ), - file: items.first?.file, + file: items.first?.file._parse(), action: action) return .single(tip) } else { diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift index a16eec5159..02b9a3db5f 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift @@ -3569,6 +3569,7 @@ final class StoryItemSetContainerSendMessage { let _ = (component.context.engine.stickers.resolveInlineStickers(fileIds: [fileId]) |> deliverOnMainQueue).start(next: { files in if let itemFile = files[fileId] { + let itemFile = TelegramMediaFile.Accessor(itemFile) let reactionItem = ReactionItem( reaction: ReactionItem.Reaction(rawValue: .custom(itemFile.fileId.id)), appearAnimation: itemFile, diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift index 5c2a590428..ebda94d2e7 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift @@ -559,7 +559,7 @@ final class StoryItemSetViewListComponent: Component { if let availableReactions = component.availableReactions { for availableReaction in availableReactions.reactionItems { if availableReaction.reaction.rawValue == reaction { - animationFile = availableReaction.listAnimation + animationFile = availableReaction.listAnimation._parse() break } } @@ -573,7 +573,7 @@ final class StoryItemSetViewListComponent: Component { if let availableReactions = component.availableReactions { for availableReaction in availableReactions.reactionItems { if availableReaction.reaction.rawValue == reaction { - animationFile = availableReaction.listAnimation + animationFile = availableReaction.listAnimation._parse() break } } diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift index 83413d3be0..3f1e87fd51 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift @@ -1750,6 +1750,7 @@ extension ChatControllerImpl { } case let .custom(fileId): if let itemFile = item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile { + let itemFile = TelegramMediaFile.Accessor(itemFile) reactionItem = ReactionItem( reaction: ReactionItem.Reaction(rawValue: updatedReaction), appearAnimation: itemFile, diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift index eec8e97cd6..8dcfbc918e 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift @@ -276,7 +276,7 @@ extension ChatControllerImpl { placeholderColor: .clear, attemptSynchronous: true ), - file: items.first?.file, + file: items.first?.file._parse(), action: action) return .single(actions) } else { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index c544cc6d78..804d6f3568 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1692,6 +1692,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } case let .custom(fileId): if let itemFile = item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile { + let itemFile = TelegramMediaFile.Accessor(itemFile) reactionItem = ReactionItem( reaction: ReactionItem.Reaction(rawValue: chosenReaction), appearAnimation: itemFile, @@ -1879,6 +1880,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } case let .custom(fileId): if let itemFile = item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile { + let itemFile = TelegramMediaFile.Accessor(itemFile) reactionItem = ReactionItem( reaction: ReactionItem.Reaction(rawValue: chosenReaction), appearAnimation: itemFile, @@ -4424,7 +4426,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G |> take(1) |> mapToSignal { result -> Signal in if case let .result(_, items, _) = result { - return .single(.emojiStatus(peerId, peerStatus, items.first?.file, result)) + return .single(.emojiStatus(peerId, peerStatus, items.first?.file._parse(), result)) } else { return .single(.emojiStatus(peerId, peerStatus, nil, nil)) } diff --git a/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift b/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift index 0f6a4423f6..974d800cef 100644 --- a/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift +++ b/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift @@ -48,7 +48,7 @@ extension ChatControllerImpl { reactionFile = self.context.engine.stickers.availableReactions() |> take(1) |> map { availableReactions -> TelegramMediaFile? in - return availableReactions?.reactions.first(where: { $0.value == value })?.selectAnimation + return availableReactions?.reactions.first(where: { $0.value == value })?.selectAnimation._parse() } case let .custom(fileId): reactionFile = self.context.engine.stickers.resolveInlineStickers(fileIds: [fileId]) @@ -325,7 +325,7 @@ extension ChatControllerImpl { placeholderColor: .clear, attemptSynchronous: true ), - file: items.first?.file, + file: items.first?.file._parse(), action: action) return .single(tip) } else { @@ -338,7 +338,7 @@ extension ChatControllerImpl { let reactionFile: TelegramMediaFile? switch value { case .builtin, .stars: - reactionFile = availableReactions?.reactions.first(where: { $0.value == value })?.selectAnimation + reactionFile = availableReactions?.reactions.first(where: { $0.value == value })?.selectAnimation._parse() case let .custom(fileId): reactionFile = customEmoji[fileId] } diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index bb140f1581..3e0b8df127 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -4188,6 +4188,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto } case let .custom(fileId): if let itemFile = item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile { + let itemFile = TelegramMediaFile.Accessor(itemFile) reactionItem = ReactionItem( reaction: ReactionItem.Reaction(rawValue: updatedReaction), appearAnimation: itemFile, diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift index 5ab696ab99..823ea8c51c 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift @@ -388,7 +388,7 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee let stringRepresentations = item.getStringRepresentationsOfIndexKeys() for stringRepresentation in stringRepresentations { if stringRepresentation == query { - result.append((stringRepresentation, item.file, stringRepresentation)) + result.append((stringRepresentation, item.file._parse(), stringRepresentation)) break } } @@ -438,7 +438,7 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee let stringRepresentations = item.getStringRepresentationsOfIndexKeys() for stringRepresentation in stringRepresentations { if let keyword = allEmoticons[stringRepresentation] { - result.append((stringRepresentation, item.file, keyword)) + result.append((stringRepresentation, item.file._parse(), keyword)) break } } diff --git a/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift index 65c9a4eb20..f4507ed78a 100644 --- a/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift @@ -517,7 +517,7 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, Chat inner: for availableReaction in availableReactions.reactions { if availableReaction.value == reaction { if let file = availableReaction.centerAnimation { - self.items.append(Item(reaction: reaction, count: count, title: title, file: file)) + self.items.append(Item(reaction: reaction, count: count, title: title, file: file._parse())) } break inner } @@ -769,7 +769,7 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, Chat reactionFile = self.context.engine.stickers.availableReactions() |> take(1) |> map { availableReactions -> TelegramMediaFile? in - return availableReactions?.reactions.first(where: { $0.value == reaction })?.selectAnimation + return availableReactions?.reactions.first(where: { $0.value == reaction })?.selectAnimation._parse() } case let .custom(fileId): reactionFile = self.context.engine.stickers.resolveInlineStickers(fileIds: [fileId]) diff --git a/submodules/TelegramUI/Sources/ChatThemeScreen.swift b/submodules/TelegramUI/Sources/ChatThemeScreen.swift index 7f3a277dac..cdf9b92f22 100644 --- a/submodules/TelegramUI/Sources/ChatThemeScreen.swift +++ b/submodules/TelegramUI/Sources/ChatThemeScreen.swift @@ -893,7 +893,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, ASScrollViewDelega guard let emoticon = theme.emoticon else { continue } - entries.append(ThemeSettingsThemeEntry(index: entries.count, emoticon: emoticon, emojiFile: animatedEmojiStickers[emoticon]?.first?.file, themeReference: .cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil, creatorAccountId: nil)), nightMode: isDarkAppearance, selected: selectedEmoticon == theme.emoticon?.strippedEmoji, theme: presentationData.theme, strings: presentationData.strings, wallpaper: nil)) + entries.append(ThemeSettingsThemeEntry(index: entries.count, emoticon: emoticon, emojiFile: animatedEmojiStickers[emoticon]?.first?.file._parse(), themeReference: .cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil, creatorAccountId: nil)), nightMode: isDarkAppearance, selected: selectedEmoticon == theme.emoticon?.strippedEmoji, theme: presentationData.theme, strings: presentationData.strings, wallpaper: nil)) } let action: (String?) -> Void = { [weak self] emoticon in diff --git a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift index 2f530668a3..3890be0c49 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift @@ -179,18 +179,18 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { .action(ContextMenuActionItem(text: strongSelf.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in f(.default) - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, false, nil, true, itemNode.view, itemNode.bounds, nil, []) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file._parse()), false, false, nil, true, itemNode.view, itemNode.bounds, nil, []) })), .action(ContextMenuActionItem(text: isStarred ? strongSelf.strings.Stickers_RemoveFromFavorites : strongSelf.strings.Stickers_AddToFavorites, icon: { theme in generateTintedImage(image: isStarred ? UIImage(bundleImageName: "Chat/Context Menu/Unfave") : UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in f(.default) if let strongSelf = self { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let _ = (strongSelf.context.engine.stickers.toggleStickerSaved(file: item.file, saved: !isStarred) + let _ = (strongSelf.context.engine.stickers.toggleStickerSaved(file: item.file._parse(), saved: !isStarred) |> deliverOnMainQueue).startStandalone(next: { result in switch result { case .generic: - strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, loop: true, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), nil) + strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file._parse(), loop: true, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) let text: String @@ -199,7 +199,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { } else { text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, loop: true, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in + strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file._parse(), loop: true, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -217,7 +217,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { f(.default) if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { - loop: for attribute in item.file.attributes { + loop: for attribute in item.file._parse().attributes { switch attribute { case let .Sticker(_, packReference, _): if let packReference = packReference { @@ -240,7 +240,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { } })) ] - return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(context: strongSelf.context, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item.file), menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(context: strongSelf.context, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item.file._parse()), menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index 8ca90a5755..fd32edc50c 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -114,9 +114,9 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, ASScrollVie }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, animationNode.view, animationNode.bounds, nil, []) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file._parse()), true, false, nil, true, animationNode.view, animationNode.bounds, nil, []) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, imageNode.view, imageNode.bounds, nil, []) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file._parse()), true, false, nil, true, imageNode.view, imageNode.bounds, nil, []) } } f(.default) @@ -128,9 +128,9 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, ASScrollVie }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, animationNode.view, animationNode.bounds, nil, []) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file._parse()), false, true, nil, true, animationNode.view, animationNode.bounds, nil, []) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, imageNode.view, imageNode.bounds, nil, []) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file._parse()), false, true, nil, true, imageNode.view, imageNode.bounds, nil, []) } } f(.default) @@ -142,11 +142,11 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, ASScrollVie if let strongSelf = self { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let _ = (strongSelf.context.engine.stickers.toggleStickerSaved(file: item.file, saved: !isStarred) + let _ = (strongSelf.context.engine.stickers.toggleStickerSaved(file: item.file._parse(), saved: !isStarred) |> deliverOnMainQueue).startStandalone(next: { result in switch result { case .generic: - strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, loop: true, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), nil) + strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file._parse(), loop: true, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) let text: String @@ -155,7 +155,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, ASScrollVie } else { text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, loop: true, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in + strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file._parse(), loop: true, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -176,7 +176,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, ASScrollVie f(.default) if let strongSelf = self, let controllerInteraction = strongSelf.getControllerInteraction?() { - loop: for attribute in item.file.attributes { + loop: for attribute in item.file._parse().attributes { switch attribute { case let .Sticker(_, packReference, _): if let packReference = packReference { @@ -199,7 +199,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, ASScrollVie } })) ) - return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(context: strongSelf.context, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item.file), menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(context: strongSelf.context, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item.file._parse()), menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self, let controllerInteraction = strongSelf.getControllerInteraction?() else { return } diff --git a/submodules/TelegramUI/Sources/PrefetchManager.swift b/submodules/TelegramUI/Sources/PrefetchManager.swift index be6dafa68a..1ab0ba75e7 100644 --- a/submodules/TelegramUI/Sources/PrefetchManager.swift +++ b/submodules/TelegramUI/Sources/PrefetchManager.swift @@ -75,9 +75,10 @@ private final class PrefetchManagerInnerImpl { let popularEmoji = ["\u{2764}", "👍", "👎", "😳", "😒", "🥳", "😡", "😮", "😂", "😘", "😍", "🙄", "😎"] for emoji in popularEmoji { if let sticker = animatedEmojiStickers[emoji] { - if let _ = account.postbox.mediaBox.completedResourcePath(sticker.file.resource) { + let stickerFile = sticker.file._parse() + if let _ = account.postbox.mediaBox.completedResourcePath(stickerFile.resource) { } else { - stickerItems.append(.animatedEmojiSticker(sticker.file)) + stickerItems.append(.animatedEmojiSticker(stickerFile)) } } } diff --git a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift index 5114787d01..586ed5b192 100644 --- a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift +++ b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift @@ -62,7 +62,6 @@ public struct ExperimentalUISettings: Codable, Equatable { public var dynamicStreaming: Bool public var enableLocalTranslation: Bool public var autoBenchmarkReflectors: Bool? - public var conferenceCalls: Bool public var playerV2: Bool public var devRequests: Bool public var fakeAds: Bool @@ -106,7 +105,6 @@ public struct ExperimentalUISettings: Codable, Equatable { dynamicStreaming: false, enableLocalTranslation: false, autoBenchmarkReflectors: nil, - conferenceCalls: false, playerV2: false, devRequests: false, fakeAds: false @@ -151,7 +149,6 @@ public struct ExperimentalUISettings: Codable, Equatable { dynamicStreaming: Bool, enableLocalTranslation: Bool, autoBenchmarkReflectors: Bool?, - conferenceCalls: Bool, playerV2: Bool, devRequests: Bool, fakeAds: Bool @@ -193,7 +190,6 @@ public struct ExperimentalUISettings: Codable, Equatable { self.dynamicStreaming = dynamicStreaming self.enableLocalTranslation = enableLocalTranslation self.autoBenchmarkReflectors = autoBenchmarkReflectors - self.conferenceCalls = conferenceCalls self.playerV2 = playerV2 self.devRequests = devRequests self.fakeAds = fakeAds @@ -239,7 +235,6 @@ public struct ExperimentalUISettings: Codable, Equatable { self.dynamicStreaming = try container.decodeIfPresent(Bool.self, forKey: "dynamicStreaming_v2") ?? false self.enableLocalTranslation = try container.decodeIfPresent(Bool.self, forKey: "enableLocalTranslation") ?? false self.autoBenchmarkReflectors = try container.decodeIfPresent(Bool.self, forKey: "autoBenchmarkReflectors") - self.conferenceCalls = try container.decodeIfPresent(Bool.self, forKey: "conferenceCalls") ?? false self.playerV2 = try container.decodeIfPresent(Bool.self, forKey: "playerV2") ?? false self.devRequests = try container.decodeIfPresent(Bool.self, forKey: "devRequests") ?? false self.fakeAds = try container.decodeIfPresent(Bool.self, forKey: "fakeAds") ?? false @@ -285,7 +280,6 @@ public struct ExperimentalUISettings: Codable, Equatable { try container.encode(self.dynamicStreaming, forKey: "dynamicStreaming") try container.encode(self.enableLocalTranslation, forKey: "enableLocalTranslation") try container.encodeIfPresent(self.autoBenchmarkReflectors, forKey: "autoBenchmarkReflectors") - try container.encodeIfPresent(self.conferenceCalls, forKey: "conferenceCalls") try container.encodeIfPresent(self.playerV2, forKey: "playerV2") try container.encodeIfPresent(self.devRequests, forKey: "devRequests") try container.encodeIfPresent(self.fakeAds, forKey: "fakeAds") diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index 28f30c7066..df4a7d6f2c 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -555,12 +555,13 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { } resourceReference = MediaResourceReference.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource) } else if let item = topItem { - if item.file.isAnimatedSticker || item.file.isVideoSticker { - thumbnailItem = .animated(EngineMediaResource(item.file.resource), item.file.dimensions ?? PixelDimensions(width: 512, height: 512), item.file.isVideoSticker) - resourceReference = MediaResourceReference.media(media: .standalone(media: item.file), resource: item.file.resource) - } else if let dimensions = item.file.dimensions, let resource = chatMessageStickerResource(file: item.file, small: true) as? TelegramMediaResource { + let itemFile = item.file._parse() + if itemFile.isAnimatedSticker || itemFile.isVideoSticker { + thumbnailItem = .animated(EngineMediaResource(itemFile.resource), itemFile.dimensions ?? PixelDimensions(width: 512, height: 512), itemFile.isVideoSticker) + resourceReference = MediaResourceReference.media(media: .standalone(media: itemFile), resource: itemFile.resource) + } else if let dimensions = itemFile.dimensions, let resource = chatMessageStickerResource(file: itemFile, small: true) as? TelegramMediaResource { thumbnailItem = .still(TelegramMediaImageRepresentation(dimensions: dimensions, resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)) - resourceReference = MediaResourceReference.media(media: .standalone(media: item.file), resource: resource) + resourceReference = MediaResourceReference.media(media: .standalone(media: itemFile), resource: resource) } } @@ -668,7 +669,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { case let .result(_, items, _): let item = items[Int(value)] - animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: context.account, resource: item.file.resource), width: 120, height: 120, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: context.account, resource: item.file._parse().resource), width: 120, height: 120, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) default: break } diff --git a/submodules/WatchBridge/Sources/WatchRequestHandlers.swift b/submodules/WatchBridge/Sources/WatchRequestHandlers.swift index 3ec2264511..2292d590eb 100644 --- a/submodules/WatchBridge/Sources/WatchRequestHandlers.swift +++ b/submodules/WatchBridge/Sources/WatchRequestHandlers.swift @@ -314,12 +314,12 @@ private func mediaForSticker(documentId: Int64, account: Account) -> Signal map { result -> [TelegramMediaFile] in + |> map { result -> [TelegramMediaFile.Accessor] in switch result { case let .result(_, items, _): return items.map(\.file) diff --git a/submodules/WebUI/Sources/WebAppEmojiStatusAlertController.swift b/submodules/WebUI/Sources/WebAppEmojiStatusAlertController.swift index 45039c81c9..316962fb11 100644 --- a/submodules/WebUI/Sources/WebAppEmojiStatusAlertController.swift +++ b/submodules/WebUI/Sources/WebAppEmojiStatusAlertController.swift @@ -18,7 +18,7 @@ private final class IconsNode: ASDisplayNode { private let context: AccountContext private var animationLayer: InlineStickerItemLayer? - private var files: [TelegramMediaFile] + private var files: [TelegramMediaFile.Accessor] private var currentIndex = 0 private var switchingToNext = false @@ -26,7 +26,7 @@ private final class IconsNode: ASDisplayNode { private var currentParams: (size: CGSize, theme: PresentationTheme)? - init(context: AccountContext, files: [TelegramMediaFile]) { + init(context: AccountContext, files: [TelegramMediaFile.Accessor]) { self.context = context self.files = files @@ -63,7 +63,7 @@ private final class IconsNode: ASDisplayNode { disappearingAnimationLayer = self.animationLayer self.switchingToNext = false } - let file = self.files[self.currentIndex] + let file = self.files[self.currentIndex]._parse() let emoji = ChatTextInputTextCustomEmojiAttribute( interactivelySelectedFromPackId: nil, fileId: file.fileId.id, @@ -132,7 +132,7 @@ private final class WebAppEmojiStatusAlertContentNode: AlertContentNode { strings: PresentationStrings, accountPeer: EnginePeer, botName: String, - icons: [TelegramMediaFile], + icons: [TelegramMediaFile.Accessor], actions: [TextAlertAction] ) { self.strings = strings @@ -331,7 +331,7 @@ func webAppEmojiStatusAlertController( context: AccountContext, accountPeer: EnginePeer, botName: String, - icons: [TelegramMediaFile], + icons: [TelegramMediaFile.Accessor], completion: @escaping (Bool) -> Void ) -> AlertController { let presentationData = context.sharedContext.currentPresentationData.with { $0 } diff --git a/third-party/webp/BUILD b/third-party/webp/BUILD index 310c69bfd3..b6ef3be99f 100644 --- a/third-party/webp/BUILD +++ b/third-party/webp/BUILD @@ -56,7 +56,7 @@ genrule( mkdir -p "$$BUILD_DIR/Public/libwebp" - PATH="$$PATH:$$CMAKE_DIR/cmake-3.23.1-macos-universal/CMake.app/Contents/bin" sh $$BUILD_DIR/build-webp-bazel.sh $$BUILD_ARCH "$$BUILD_DIR/libwebp" "$$BUILD_DIR" >/dev/null 2>&1 + PATH="$$PATH:$$CMAKE_DIR/cmake-3.23.1-macos-universal/CMake.app/Contents/bin" sh $$BUILD_DIR/build-webp-bazel.sh $$BUILD_ARCH "$$BUILD_DIR/libwebp" "$$BUILD_DIR" """ + "\n".join([ "cp -f \"$$BUILD_DIR/libwebp/src/webp/{}\" \"$(location Public/webp/{})\"".format(header, header) for header in headers