From ea0f6a685ce1cb845324197ada26de0099f90650 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 00:54:26 +0200 Subject: [PATCH 01/14] =?UTF-8?q?Postbox=20refactor=20wave=20277:=20cached?= =?UTF-8?q?Wallpaper(account:)=20=E2=86=92=20cachedWallpaper(engine:networ?= =?UTF-8?q?k:)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate `cachedWallpaper(account: Account, ...)` in WallpaperCache.swift to take `(engine: TelegramEngine, network: Network, ...)` instead of the umbrella Account parameter. Body drops the local `let engine = TelegramEngine(account:)` since engine is now a parameter; `account.network` is now `network`. 19 context-based callers (`account: context.account` / `self.context.account` / `component.context.account`) update via perl sweep to pass `engine: context.engine, network: context.account.network`. 3 internal-Account-typed callers (WallpaperResources.swift × 2, ThemeUpdateManager.swift × 1) bridge with adhoc `engine: TelegramEngine(account: account), network: account.network` since they're inside functions that still take `account: Account` and have heavier Postbox uses we can't migrate yet. Drops `import Postbox` from WallpaperCache.swift since the only remaining Postbox-ish identifier was `ValueBoxKey`, which swaps to `EngineDataBuffer`. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../SettingsUI/Sources/ThemePickerController.swift | 12 ++++++------ .../Sources/Themes/EditThemeController.swift | 4 ++-- .../Themes/ThemeAutoNightSettingsController.swift | 2 +- .../Sources/Themes/ThemePreviewController.swift | 2 +- .../Sources/Themes/ThemeSettingsController.swift | 12 ++++++------ .../Sources/ChannelAppearanceScreen.swift | 2 +- .../Sources/UserApperanceScreen.swift | 2 +- .../TelegramUI/Sources/ThemeUpdateManager.swift | 2 +- .../WallpaperResources/Sources/WallpaperCache.swift | 13 +++++-------- .../Sources/WallpaperResources.swift | 4 ++-- 10 files changed, 26 insertions(+), 29 deletions(-) diff --git a/submodules/SettingsUI/Sources/ThemePickerController.swift b/submodules/SettingsUI/Sources/ThemePickerController.swift index b90159eb76..986b79cc0b 100644 --- a/submodules/SettingsUI/Sources/ThemePickerController.swift +++ b/submodules/SettingsUI/Sources/ThemePickerController.swift @@ -517,7 +517,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme } |> mapToSignal { accentColor, wallpaper -> Signal<(PresentationThemeAccentColor?, TelegramWallpaper), NoError> in if case let .file(file) = wallpaper, file.id == 0 { - return cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + return cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { cachedWallpaper in if let wallpaper = cachedWallpaper?.wallpaper, case .file = wallpaper { return (accentColor, wallpaper) @@ -578,7 +578,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme let resolvedWallpaper: Signal if case let .file(file) = theme.chat.defaultWallpaper, file.id == 0 { - resolvedWallpaper = cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + resolvedWallpaper = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { cachedWallpaper -> TelegramWallpaper in return cachedWallpaper?.wallpaper ?? theme.chat.defaultWallpaper } @@ -745,7 +745,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme let wallpaperSignal: Signal if case let .file(file) = effectiveWallpaper, file.id == 0 { - wallpaperSignal = cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + wallpaperSignal = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { cachedWallpaper in return cachedWallpaper?.wallpaper ?? effectiveWallpaper } @@ -825,7 +825,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme let resolvedWallpaper: Signal if case let .file(file) = theme.chat.defaultWallpaper, file.id == 0 { - resolvedWallpaper = cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + resolvedWallpaper = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { cachedWallpaper -> TelegramWallpaper in return cachedWallpaper?.wallpaper ?? theme.chat.defaultWallpaper } @@ -1129,7 +1129,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme let resolvedWallpaper: Signal if case let .file(file) = presentationTheme.chat.defaultWallpaper, file.id == 0 { - resolvedWallpaper = cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + resolvedWallpaper = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { wallpaper -> TelegramWallpaper? in return wallpaper?.wallpaper } @@ -1226,7 +1226,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme selectAccentColorImpl = { currentBaseTheme, accentColor in var wallpaperSignal: Signal = .single(nil) if let colorWallpaper = accentColor?.wallpaper, case let .file(file) = colorWallpaper { - wallpaperSignal = cachedWallpaper(account: context.account, slug: file.slug, settings: colorWallpaper.settings) + wallpaperSignal = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: colorWallpaper.settings) |> mapToSignal { cachedWallpaper in if let wallpaper = cachedWallpaper?.wallpaper, case let .file(file) = wallpaper { let _ = context.engine.resources.fetch(reference: .wallpaper(wallpaper: .slug(file.slug), resource: file.file.resource), userLocation: .other, userContentType: .other).start() diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index 7513a800e6..32112be4b5 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -335,7 +335,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll settingsPromise.set(.single(info.theme.settings?.first)) if let file = info.theme.file, let path = context.sharedContext.accountManager.resources.completedResourcePath(resource: EngineMediaResource(file.resource)), let data = try? Data(contentsOf: URL(fileURLWithPath: path)), let theme = makePresentationTheme(data: data, resolvedWallpaper: info.resolvedWallpaper) { if case let .file(file) = theme.chat.defaultWallpaper, file.id == 0 { - previewThemePromise.set(cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + previewThemePromise.set(cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map ({ wallpaper -> PresentationTheme in if let wallpaper = wallpaper { return theme.withUpdated(name: nil, defaultWallpaper: wallpaper.wallpaper) @@ -404,7 +404,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll if let url = urls.first{ if let data = try? Data(contentsOf: url), let theme = makePresentationTheme(data: data) { if case let .file(file) = theme.chat.defaultWallpaper, file.id == 0 { - let _ = (cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + let _ = (cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> mapToSignal { wallpaper -> Signal in if let wallpaper = wallpaper, case let .file(file) = wallpaper.wallpaper { var convertedRepresentations: [ImageRepresentationWithReference] = [] diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift index 9d92ab1692..bc300e2812 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift @@ -539,7 +539,7 @@ public func themeAutoNightSettingsController(context: AccountContext) -> ViewCon let resolvedWallpaper: Signal if case let .file(file) = presentationTheme.chat.defaultWallpaper, file.id == 0 { - resolvedWallpaper = cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + resolvedWallpaper = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { wallpaper -> TelegramWallpaper? in return wallpaper?.wallpaper } diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewController.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewController.swift index 7a0611c0ab..a251af569a 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewController.swift @@ -221,7 +221,7 @@ public final class ThemePreviewController: ViewController { if let initialWallpaper = initialWallpaper { self.controllerNode.wallpaperPromise.set(.single(initialWallpaper)) } else if case let .file(file) = previewTheme.chat.defaultWallpaper, file.id == 0 { - self.controllerNode.wallpaperPromise.set(cachedWallpaper(account: self.context.account, slug: file.slug, settings: file.settings) + self.controllerNode.wallpaperPromise.set(cachedWallpaper(engine: self.context.engine, network: self.context.account.network, slug: file.slug, settings: file.settings) |> mapToSignal { wallpaper in return .single(wallpaper?.wallpaper ?? .color(previewTheme.chatList.backgroundColor.argb)) }) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index 38f2bb26ca..9fcf97c4a6 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -677,7 +677,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The } |> mapToSignal { accentColor, wallpaper -> Signal<(PresentationThemeAccentColor?, TelegramWallpaper), NoError> in if case let .file(file) = wallpaper, file.id == 0 { - return cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + return cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { cachedWallpaper in if let wallpaper = cachedWallpaper?.wallpaper, case .file = wallpaper { return (accentColor, wallpaper) @@ -731,7 +731,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The let resolvedWallpaper: Signal if case let .file(file) = theme.chat.defaultWallpaper, file.id == 0 { - resolvedWallpaper = cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + resolvedWallpaper = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { cachedWallpaper -> TelegramWallpaper in return cachedWallpaper?.wallpaper ?? theme.chat.defaultWallpaper } @@ -896,7 +896,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The let wallpaperSignal: Signal if case let .file(file) = effectiveWallpaper, file.id == 0 { - wallpaperSignal = cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + wallpaperSignal = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { cachedWallpaper in return cachedWallpaper?.wallpaper ?? effectiveWallpaper } @@ -976,7 +976,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The let resolvedWallpaper: Signal if case let .file(file) = theme.chat.defaultWallpaper, file.id == 0 { - resolvedWallpaper = cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + resolvedWallpaper = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { cachedWallpaper -> TelegramWallpaper in return cachedWallpaper?.wallpaper ?? theme.chat.defaultWallpaper } @@ -1242,7 +1242,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The let resolvedWallpaper: Signal if case let .file(file) = presentationTheme.chat.defaultWallpaper, file.id == 0 { - resolvedWallpaper = cachedWallpaper(account: context.account, slug: file.slug, settings: file.settings) + resolvedWallpaper = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: file.settings) |> map { wallpaper -> TelegramWallpaper? in return wallpaper?.wallpaper } @@ -1319,7 +1319,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The selectAccentColorImpl = { accentColor in var wallpaperSignal: Signal = .single(nil) if let colorWallpaper = accentColor?.wallpaper, case let .file(file) = colorWallpaper { - wallpaperSignal = cachedWallpaper(account: context.account, slug: file.slug, settings: colorWallpaper.settings) + wallpaperSignal = cachedWallpaper(engine: context.engine, network: context.account.network, slug: file.slug, settings: colorWallpaper.settings) |> mapToSignal { cachedWallpaper in if let wallpaper = cachedWallpaper?.wallpaper, case let .file(file) = wallpaper { let _ = context.engine.resources.fetch(reference: .wallpaper(wallpaper: .slug(file.slug), resource: file.file.resource), userLocation: .other, userContentType: .other).start() diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift index 8959e21dda..c00225f8a7 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift @@ -929,7 +929,7 @@ final class ChannelAppearanceScreenComponent: Component { if let temporaryPeerWallpaper = self.temporaryPeerWallpaper { resolvedWallpaper = .single(temporaryPeerWallpaper) } else if case let .file(file) = presentationTheme.chat.defaultWallpaper, file.id == 0 { - resolvedWallpaper = cachedWallpaper(account: component.context.account, slug: file.slug, settings: file.settings) + resolvedWallpaper = cachedWallpaper(engine: component.context.engine, network: component.context.account.network, slug: file.slug, settings: file.settings) |> map { wallpaper -> TelegramWallpaper? in return wallpaper?.wallpaper } diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/UserApperanceScreen.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/UserApperanceScreen.swift index ce44581703..a0dac353e4 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/UserApperanceScreen.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/UserApperanceScreen.swift @@ -1112,7 +1112,7 @@ final class UserAppearanceScreenComponent: Component { if let presentationTheme { let resolvedWallpaper: Signal if case let .file(file) = presentationTheme.chat.defaultWallpaper, file.id == 0 { - resolvedWallpaper = cachedWallpaper(account: component.context.account, slug: file.slug, settings: file.settings) + resolvedWallpaper = cachedWallpaper(engine: component.context.engine, network: component.context.account.network, slug: file.slug, settings: file.settings) |> map { wallpaper -> TelegramWallpaper? in return wallpaper?.wallpaper } diff --git a/submodules/TelegramUI/Sources/ThemeUpdateManager.swift b/submodules/TelegramUI/Sources/ThemeUpdateManager.swift index 36ac6f790c..f6f3f81488 100644 --- a/submodules/TelegramUI/Sources/ThemeUpdateManager.swift +++ b/submodules/TelegramUI/Sources/ThemeUpdateManager.swift @@ -91,7 +91,7 @@ final class ThemeUpdateManagerImpl: ThemeUpdateManager { let resolvedWallpaper: Signal if case let .file(file) = presentationTheme.chat.defaultWallpaper, file.id == 0 { - resolvedWallpaper = cachedWallpaper(account: account, slug: file.slug, settings: file.settings) + resolvedWallpaper = cachedWallpaper(engine: TelegramEngine(account: account), network: account.network, slug: file.slug, settings: file.settings) |> map { wallpaper in return wallpaper?.wallpaper } diff --git a/submodules/WallpaperResources/Sources/WallpaperCache.swift b/submodules/WallpaperResources/Sources/WallpaperCache.swift index 12d999635e..dffd5045ea 100644 --- a/submodules/WallpaperResources/Sources/WallpaperCache.swift +++ b/submodules/WallpaperResources/Sources/WallpaperCache.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import SwiftSignalKit -import Postbox import TelegramApi import TelegramCore import TelegramUIPreferences @@ -27,10 +26,8 @@ public final class CachedWallpaper: Codable { } } -public func cachedWallpaper(account: Account, slug: String, settings: WallpaperSettings?, update: Bool = false) -> Signal { - let engine = TelegramEngine(account: account) - - let slugKey = ValueBoxKey(length: 8) +public func cachedWallpaper(engine: TelegramEngine, network: Network, slug: String, settings: WallpaperSettings?, update: Bool = false) -> Signal { + let slugKey = EngineDataBuffer(length: 8) slugKey.setInt64(0, value: Int64(bitPattern: slug.persistentHashValue)) return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.cachedWallpapers, id: slugKey)) |> mapToSignal { entry -> Signal in @@ -41,13 +38,13 @@ public func cachedWallpaper(account: Account, slug: String, settings: WallpaperS return .single(entry) } } else { - return getWallpaper(network: account.network, slug: slug) + return getWallpaper(network: network, slug: slug) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) } |> mapToSignal { wallpaper -> Signal in - let slugKey = ValueBoxKey(length: 8) + let slugKey = EngineDataBuffer(length: 8) slugKey.setInt64(0, value: Int64(bitPattern: slug.persistentHashValue)) if var wallpaper = wallpaper { @@ -81,7 +78,7 @@ public func updateCachedWallpaper(engine: TelegramEngine, wallpaper: TelegramWal guard case let .file(file) = wallpaper, file.id != 0 else { return } - let key = ValueBoxKey(length: 8) + let key = EngineDataBuffer(length: 8) key.setInt64(0, value: Int64(bitPattern: file.slug.persistentHashValue)) let _ = engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.cachedWallpapers, id: key, item: CachedWallpaper(wallpaper: wallpaper)).start() diff --git a/submodules/WallpaperResources/Sources/WallpaperResources.swift b/submodules/WallpaperResources/Sources/WallpaperResources.swift index 438b4904d5..07dd9e52d0 100644 --- a/submodules/WallpaperResources/Sources/WallpaperResources.swift +++ b/submodules/WallpaperResources/Sources/WallpaperResources.swift @@ -1247,7 +1247,7 @@ public func themeImage(account: Account, accountManager: AccountManager mapToSignal { (theme, thumbnailData) -> Signal<(PresentationTheme?, WallpaperImage?, Data?), NoError> in if let theme = theme { if case let .file(file) = theme.chat.defaultWallpaper { - return cachedWallpaper(account: account, slug: file.slug, settings: file.settings) + return cachedWallpaper(engine: TelegramEngine(account: account), network: account.network, slug: file.slug, settings: file.settings) |> mapToSignal { wallpaper -> Signal<(PresentationTheme?, WallpaperImage?, Data?), NoError> in if let wallpaper = wallpaper, case let .file(file) = wallpaper.wallpaper { var convertedRepresentations: [ImageRepresentationWithReference] = [] @@ -1496,7 +1496,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager mapToSignal { wallpaper in if let wallpaper = wallpaper, case let .file(file) = wallpaper.wallpaper { var effectiveBackgroundColor = backgroundColor From e918b353ec31beffef521d89f7694a925b6475f4 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 14:11:06 +0200 Subject: [PATCH 02/14] Postbox refactor waves 278-356: squash Squashes 79 sequential refactor waves into a single commit. Highlights: - Drop `import Postbox` (and matching `//submodules/Postbox` BUILD deps) from a wide swath of consumer files: ChatList, ChatMessage*BubbleContentNode subclasses, ListMessageNode/ListMessageItem, GalleryData, ChatHistorySearchContainerNode, ChatPanelInterfaceInteraction, ChatControllerInteraction, ChatMessageStickerItemNode, ChatMessageReplyInfoNode, ChatMessageInstantVideoItemNode, ChatPresentationInterfaceState, BrowserMarkdown/Readability, MediaResources, LocalMediaResources, ICloudResources, FetchManager, ShareController, OpenChatMessage, GalleryController, GroupStickerSearchContainerNode, GroupStickerPackCurrentItem, ChatPinnedMessageTitlePanelNode, OverlayAudioPlayerController, PresentationThemeSettings, StatisticsUI/StoryIconNode, TextFormat/StringWithAppliedEntities, GalleryUI/VideoAdComponent, StickerPackPreviewUI, WallpaperPreviewMedia, WallpaperResources, YoutubeEmbedImplementation, InstantPageExternalMediaResource, PlatformRestrictionMatching, TelegramUIDeclareEncodables, ChatListNode/ChatListSearchContainerNode. - Add `TelegramEngine` facades: `Themes.wallpapers`, `Themes.themes`, `AccountData.addAppLogEvent`. - Add `EngineMessageHistoryEntryLocation` wrapper. - Add `EngineRaw*` escape-hatch typealiases (`EngineRawMessage`, `EngineRawPeer`, `EngineRawMedia`, `EngineRawMediaResource`, `EngineRawMediaResourceData`, `EngineRawItemCollectionItem`, `EngineRawItemCollectionInfo`) and `engineDeclareEncodable` forwarder. - Drop unused `account:`/`postbox:`/`network:` parameters from several public functions and delete the dead overloads/types/functions left over: `automaticThemeShouldSwitchNow`, `cancelFreeMediaFileInteractiveFetch`, `legacyEnqueueVideoMessage`, `TelegramMediaFileReference`, plus assorted dead public TelegramCore/AccountContext SecureId entry points. - Delete entire dead modules: `LegacyDataImport`, `TonBinding`, `SpotlightSupport`, `SvgRendering`, third-party `AppCenter`/`VectorPlus`/`SwiftColor`/`SwiftSVG`. - Drop orphan `//submodules/Postbox` BUILD deps across 3 cleanup rounds. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../AccountContext/Sources/FetchManager.swift | 13 +- .../Sources/FetchMediaUtils.swift | 4 - .../Sources/GalleryController.swift | 21 +- .../Sources/OpenChatMessage.swift | 37 +- .../Sources/PeerSelectionController.swift | 34 - .../Sources/PresentationCallManager.swift | 16 - .../Sources/ShareController.swift | 23 +- submodules/AuthorizationUI/BUILD | 1 - .../AvatarNode/Sources/AvatarNode.swift | 2 +- .../AvatarNode/Sources/PeerAvatar.swift | 18 +- .../BrowserUI/Sources/BrowserMarkdown.swift | 15 +- .../Sources/BrowserReadability.swift | 33 +- .../Sources/ChatListSearchContainerNode.swift | 17 +- .../Sources/ChatListSearchListPaneNode.swift | 2 +- .../Sources/Node/ChatListItem.swift | 13 +- .../Sources/Node/ChatListNode.swift | 5 +- .../ChatPanelInterfaceInteraction.swift | 99 +- submodules/GalleryData/BUILD | 1 - .../GalleryData/Sources/GalleryData.swift | 39 +- .../Items/ChatDocumentGalleryItem.swift | 13 +- .../Items/ChatExternalFileGalleryItem.swift | 15 +- .../Items/UniversalVideoGalleryItem.swift | 10 +- .../Sources/Items/VideoAdComponent.swift | 3 +- submodules/ICloudResources/BUILD | 1 - .../Sources/ICloudResources.swift | 23 +- .../InstantPageExternalMediaResource.swift | 27 +- submodules/LegacyDataImport/BUILD | 23 - submodules/LegacyDataImport/Impl/BUILD | 22 - .../LegacyDataImportImpl.h | 7 - .../TGAutoDownloadPreferences.h | 76 - .../TGAutoDownloadPreferences.m | 250 ---- .../TGPresentationAutoNightPreferences.h | 31 - .../TGPresentationAutoNightPreferences.m | 23 - .../LegacyDataImportImpl/TGProxyItem.h | 15 - .../LegacyDataImportImpl/TGProxyItem.m | 73 - .../Impl/Sources/TGAutoDownloadPreferences.m | 250 ---- .../TGPresentationAutoNightPreferences.m | 23 - .../Impl/Sources/TGProxyItem.m | 73 - .../Sources/LegacyBuffer.swift | 197 --- .../Sources/LegacyChatImport.swift | 780 ----------- .../Sources/LegacyDataImport.swift | 245 ---- .../Sources/LegacyDataImportSplash.swift | 89 -- .../Sources/LegacyFileImport.swift | 189 --- .../Sources/LegacyPreferencesImport.swift | 438 ------ .../Sources/LegacyResourceImport.swift | 137 -- .../Sources/LegacyUserDataImport.swift | 47 - .../Sources/LegacyMediaPickers.swift | 42 - .../Sources/ListMessageItem.swift | 39 +- .../Sources/ListMessageNode.swift | 4 +- submodules/LocalMediaResources/BUILD | 1 - .../Sources/MediaResources.swift | 83 +- submodules/MediaResources/BUILD | 1 - .../CachedResourceRepresentations.swift | 86 +- .../LegacySecureIdAttachmentMenu.swift | 4 +- .../Sources/PhotoResources.swift | 110 -- .../Sources/PlatformRestrictionMatching.swift | 3 +- .../PremiumUI/Sources/PremiumGiftScreen.swift | 8 +- .../Sources/PremiumIntroScreen.swift | 10 +- .../Sources/DeleteAccountDataController.swift | 26 +- .../DeleteAccountOptionsController.swift | 22 +- .../Sources/ThemePickerController.swift | 4 +- .../ThemeAutoNightSettingsController.swift | 2 +- .../Themes/ThemePreviewController.swift | 4 +- .../Themes/ThemeSettingsController.swift | 4 +- submodules/SpotlightSupport/BUILD | 18 - .../StatisticsUI/Sources/StoryIconNode.swift | 5 +- submodules/StickerPackPreviewUI/BUILD | 1 - .../Sources/StickerPackScreen.swift | 26 +- .../Sources/StickerResources.swift | 68 - submodules/SvgRendering/BUILD | 14 - .../SvgRendering/Sources/SvgParser.swift | 0 .../Sources/LegacyCallControllerNode.swift | 1 - .../Sources/ApiUtils/ChatContextResult.swift | 4 - .../CloudMediaResourceParameters.swift | 8 - .../TelegramCore/Sources/Authorization.swift | 22 - .../Network/FetchedMediaResource.swift | 4 +- .../Sources/Network/NetworkStatsContext.swift | 2 +- .../PendingMessages/EnqueueMessage.swift | 31 - .../StandaloneUploadedMedia.swift | 6 - .../Settings/ContentPrivacySettings.swift | 20 - .../TelegramCore/Sources/SplitTest.swift | 2 +- .../Sources/State/CallSessionManager.swift | 4 - .../SynchronizeAppLogEventsOperation.swift | 2 +- .../SyncCore_ArchivedStickerPacksInfo.swift | 42 - .../SyncCore_AutodownloadSettings.swift | 6 - ...Core_LocalMediaPlaybackInfoAttribute.swift | 18 - .../SyncCore/SyncCore_NewSessionReview.swift | 17 - .../SyncCore/SyncCore_TelegramMediaFile.swift | 28 - .../SyncCore/SyncCore_VoipConfiguration.swift | 6 - .../TelegramEngineAccountData.swift | 4 + .../Auth/TwoStepVerification.swift | 7 - .../TelegramEngine/Calls/GroupCalls.swift | 4 - .../TelegramEngine/Payments/AppStore.swift | 4 - .../Peers/ChatListFiltering.swift | 12 - .../Peers/ResolvePeerByName.swift | 11 - .../SecureId/SaveSecureIdValue.swift | 38 - .../SecureId/SecureIdValueAccessContext.swift | 4 - .../Themes/TelegramEngineThemes.swift | 8 + .../Utils/EnginePostboxCoding.swift | 22 + submodules/TelegramCore/Sources/Themes.swift | 6 +- .../Sources/Utils/PeerUtils.swift | 12 - .../TelegramCore/Sources/Wallpapers.swift | 2 +- .../TelegramCore/Sources/WebpagePreview.swift | 4 - .../Sources/PresentationData.swift | 5 - .../Chat/ChatButtonKeyboardInputNode/BUILD | 1 - .../Chat/ChatHistorySearchContainerNode/BUILD | 1 - .../ChatHistorySearchContainerNode.swift | 21 +- .../Chat/ChatMediaInputStickerGridItem/BUILD | 1 - .../ChatMediaInputStickerGridItem.swift | 9 +- .../ChatMessageActionBubbleContentNode.swift | 11 +- .../Chat/ChatMessageBubbleContentNode/BUILD | 1 - .../ChatMessageBubbleContentNode.swift | 23 +- .../ChatMessageCommentFooterContentNode/BUILD | 1 - ...entLogPreviousDescriptionContentNode.swift | 7 +- ...ssageEventLogPreviousLinkContentNode.swift | 9 +- ...geEventLogPreviousMessageContentNode.swift | 7 +- .../ChatMessageFileBubbleContentNode.swift | 5 +- .../ChatMessageGameBubbleContentNode.swift | 7 +- .../BUILD | 1 - ...MessageInstantVideoBubbleContentNode.swift | 7 +- .../ChatMessageInstantVideoItemNode/BUILD | 1 - .../ChatMessageInstantVideoItemNode.swift | 11 +- .../ChatMessageInvoiceBubbleContentNode.swift | 7 +- .../Components/Chat/ChatMessageItem/BUILD | 1 - .../Sources/ChatMessageItem.swift | 29 +- .../Sources/ChatMessageItemImpl.swift | 25 +- .../Components/Chat/ChatMessageItemView/BUILD | 1 - .../Sources/ChatMessageItemView.swift | 23 +- ...essageJoinedChannelBubbleContentNode.swift | 2 +- .../ChatMessageMapBubbleContentNode.swift | 5 +- .../ChatMessageMediaBubbleContentNode.swift | 9 +- ...atMessageQuizAnswerBubbleContentNode.swift | 7 +- ...ageProfilePhotoSuggestionContentNode.swift | 9 +- .../Chat/ChatMessageReplyInfoNode/BUILD | 1 - .../Sources/ChatMessageReplyInfoNode.swift | 17 +- .../BUILD | 1 - ...ChatMessageRichDataBubbleContentNode.swift | 9 +- .../Chat/ChatMessageStickerItemNode/BUILD | 1 - .../Sources/ChatMessageStickerItemNode.swift | 21 +- .../ChatMessageStoryMentionContentNode.swift | 9 +- .../ChatMessageTodoBubbleContentNode/BUILD | 1 - .../ChatMessageTodoBubbleContentNode.swift | 9 +- ...hatMessageWallpaperBubbleContentNode.swift | 7 +- .../ChatMessageWebpageBubbleContentNode.swift | 15 +- .../ChatRecentActionsFilterController.swift | 504 ------- .../ChatControllerInteraction/BUILD | 1 - .../Sources/ChatControllerInteraction.swift | 267 ++-- .../Components/EntityKeyboardGifContent/BUILD | 1 - .../Sources/GiftSetupScreen.swift | 4 +- .../Components/Gifts/GiftViewScreen/BUILD | 1 - .../Sources/GroupStickerPackCurrentItem.swift | 3 +- .../GroupStickerSearchContainerNode.swift | 7 +- .../PeerInfo/PeerInfoChatListPaneNode/BUILD | 1 - .../PeerInfo/PeerInfoChatPaneNode/BUILD | 1 - .../PeerInfo/PeerInfoPaneNode/BUILD | 1 - .../Sources/Panes/PeerInfoListPaneNode.swift | 23 +- .../Resources/FetchAudioMediaResource/BUILD | 1 - .../Sources/FetchAudioMediaResource.swift | 5 +- .../Sources/ChannelAppearanceScreen.swift | 17 +- .../Sources/SettingsThemeWallpaperNode.swift | 2 +- .../Sources/ThemeAccentColorController.swift | 2 +- .../Sources/WallpaperGalleryItem.swift | 4 +- .../Sources/WallpaperPatternPanelNode.swift | 2 +- .../Sources/ThemeGridController.swift | 2 +- .../Sources/ThemeGridControllerNode.swift | 2 +- .../Sources/StorySetIndicatorComponent.swift | 2 +- .../TelegramAccountAuxiliaryMethods.swift | 2 +- .../TelegramUIDeclareEncodables/BUILD | 2 +- .../Sources/TelegramUIDeclareEncodables.swift | 14 +- .../Sources/WallpaperPreviewMedia.swift | 43 +- .../TelegramUI/Sources/ChatController.swift | 2 +- .../Sources/ChatControllerContentData.swift | 4 +- .../ChatPinnedMessageTitlePanelNode.swift | 19 +- .../Sources/FetchCachedRepresentations.swift | 55 +- .../Sources/HorizontalStickerGridItem.swift | 3 +- .../Sources/NotificationContentContext.swift | 7 +- .../OverlayAudioPlayerController.swift | 7 +- .../Sources/ThemeUpdateManager.swift | 3 +- .../Sources/PresentationThemeSettings.swift | 49 +- .../Sources/YoutubeEmbedImplementation.swift | 33 +- .../Sources/StringWithAppliedEntities.swift | 7 +- submodules/TonBinding/BUILD | 26 - submodules/TonBinding/Sources/TON.h | 190 --- submodules/TonBinding/Sources/TON.mm | 1227 ----------------- submodules/UrlHandling/BUILD | 1 - submodules/WallpaperResources/BUILD | 1 - .../Sources/WallpaperResources.swift | 19 +- third-party/AppCenter/AppCenter.BUILD | 15 - third-party/AppCenter/BUILD | 0 third-party/SwiftColor/BUILD | 17 - third-party/SwiftColor/Sources/Clamping.swift | 20 - .../SwiftColor/Sources/ColorSpace.swift | 3 - .../SwiftColor/Sources/Pigment+AppKit.swift | 24 - .../Sources/Pigment+CoreGraphics.swift | 39 - .../SwiftColor/Sources/Pigment+Float.swift | 95 -- .../SwiftColor/Sources/Pigment+Hex.swift | 145 -- .../SwiftColor/Sources/Pigment+Int.swift | 89 -- .../SwiftColor/Sources/Pigment+Name.swift | 470 ------- .../SwiftColor/Sources/Pigment+String.swift | 76 - .../SwiftColor/Sources/Pigment+SwiftUI.swift | 9 - .../SwiftColor/Sources/Pigment+UIKit.swift | 37 - third-party/SwiftColor/Sources/Pigment.swift | 53 - third-party/SwiftSVG/BUILD | 19 - third-party/SwiftSVG/Sources/Circle.swift | 93 -- .../Sources/CommandRepresentable.swift | 15 - third-party/SwiftSVG/Sources/Container.swift | 58 - .../SwiftSVG/Sources/CoreAttributes.swift | 17 - third-party/SwiftSVG/Sources/Element.swift | 46 - third-party/SwiftSVG/Sources/Ellipse.swift | 93 -- .../Sources/Extensions/Point+SwiftSVG.swift | 37 - third-party/SwiftSVG/Sources/Fill.swift | 44 - third-party/SwiftSVG/Sources/Group.swift | 152 -- .../Sources/Internal/EllipseProcessor.swift | 88 -- .../Sources/Internal/PathProcessor.swift | 12 - .../Sources/Internal/PolygonProcressor.swift | 52 - .../Sources/Internal/PolylineProcessor.swift | 54 - .../Sources/Internal/RectangleProcessor.swift | 175 --- third-party/SwiftSVG/Sources/Line.swift | 98 -- .../SwiftSVG/Sources/Path.Command.swift | 276 ---- .../SwiftSVG/Sources/Path.Component.swift | 98 -- .../Sources/Path.ComponentParser.swift | 275 ---- third-party/SwiftSVG/Sources/Path.swift | 101 -- third-party/SwiftSVG/Sources/Polygon.swift | 82 -- third-party/SwiftSVG/Sources/Polyline.swift | 81 -- .../Sources/PresentationAttributes.swift | 120 -- third-party/SwiftSVG/Sources/Rectangle.swift | 115 -- .../SwiftSVG/Sources/SVG+Swift2D.swift | 62 - third-party/SwiftSVG/Sources/SVG.swift | 160 --- third-party/SwiftSVG/Sources/Stroke.swift | 64 - .../SwiftSVG/Sources/StylingAttributes.swift | 17 - third-party/SwiftSVG/Sources/Text.swift | 110 -- .../SwiftSVG/Sources/Transformation.swift | 113 -- third-party/VectorPlus/BUILD | 19 - .../CoreGraphics/CGContext+Render.swift | 72 - .../CGMutablePath+Instruction.swift | 45 - .../CoreGraphics/Fill+CoreGraphics.swift | 14 - .../Sources/CoreGraphics/SVG+CGPath.swift | 37 - .../CoreGraphics/Stroke+CoreGraphics.swift | 25 - .../VectorPlus/Sources/Fill+VectorPlus.swift | 29 - .../VectorPlus/Sources/Path+VectorPlus.swift | 34 - .../Sources/Path.Command+VectorPlus.swift | 216 --- .../Sources/Pigment+VectorPlus.swift | 7 - .../VectorPlus/Sources/Point+VectorPlus.swift | 7 - .../VectorPlus/Sources/Rect+VectorPlus.swift | 7 - .../VectorPlus/Sources/SVG+AppleSymbols.swift | 324 ----- .../VectorPlus/Sources/SVG+Template.swift | 56 - .../VectorPlus/Sources/Size+VectorPlus.swift | 7 - .../Sources/Stroke+VectorPlus.swift | 40 - .../Sources/Template+UIImageView.swift | 177 --- .../Sources/UIKit/SVG+UIImage.swift | 43 - .../Sources/UIKit/SVGImageView.swift | 81 -- .../VectorPlus/Sources/VectorPoint.swift | 126 -- 252 files changed, 829 insertions(+), 11680 deletions(-) delete mode 100644 submodules/LegacyDataImport/BUILD delete mode 100644 submodules/LegacyDataImport/Impl/BUILD delete mode 100644 submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/LegacyDataImportImpl.h delete mode 100644 submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGAutoDownloadPreferences.h delete mode 100644 submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGAutoDownloadPreferences.m delete mode 100644 submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGPresentationAutoNightPreferences.h delete mode 100644 submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGPresentationAutoNightPreferences.m delete mode 100644 submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGProxyItem.h delete mode 100644 submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGProxyItem.m delete mode 100644 submodules/LegacyDataImport/Impl/Sources/TGAutoDownloadPreferences.m delete mode 100644 submodules/LegacyDataImport/Impl/Sources/TGPresentationAutoNightPreferences.m delete mode 100644 submodules/LegacyDataImport/Impl/Sources/TGProxyItem.m delete mode 100644 submodules/LegacyDataImport/Sources/LegacyBuffer.swift delete mode 100644 submodules/LegacyDataImport/Sources/LegacyChatImport.swift delete mode 100644 submodules/LegacyDataImport/Sources/LegacyDataImport.swift delete mode 100644 submodules/LegacyDataImport/Sources/LegacyDataImportSplash.swift delete mode 100644 submodules/LegacyDataImport/Sources/LegacyFileImport.swift delete mode 100644 submodules/LegacyDataImport/Sources/LegacyPreferencesImport.swift delete mode 100644 submodules/LegacyDataImport/Sources/LegacyResourceImport.swift delete mode 100644 submodules/LegacyDataImport/Sources/LegacyUserDataImport.swift delete mode 100644 submodules/SpotlightSupport/BUILD delete mode 100644 submodules/SvgRendering/BUILD delete mode 100644 submodules/SvgRendering/Sources/SvgParser.swift delete mode 100644 submodules/TelegramCore/Sources/ApiUtils/CloudMediaResourceParameters.swift delete mode 100644 submodules/TelegramCore/Sources/Settings/ContentPrivacySettings.swift delete mode 100644 submodules/TelegramCore/Sources/SyncCore/SyncCore_ArchivedStickerPacksInfo.swift delete mode 100644 submodules/TelegramCore/Sources/SyncCore/SyncCore_LocalMediaPlaybackInfoAttribute.swift delete mode 100644 submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsFilterController.swift delete mode 100644 submodules/TonBinding/BUILD delete mode 100644 submodules/TonBinding/Sources/TON.h delete mode 100644 submodules/TonBinding/Sources/TON.mm delete mode 100644 third-party/AppCenter/AppCenter.BUILD delete mode 100644 third-party/AppCenter/BUILD delete mode 100644 third-party/SwiftColor/BUILD delete mode 100644 third-party/SwiftColor/Sources/Clamping.swift delete mode 100644 third-party/SwiftColor/Sources/ColorSpace.swift delete mode 100644 third-party/SwiftColor/Sources/Pigment+AppKit.swift delete mode 100644 third-party/SwiftColor/Sources/Pigment+CoreGraphics.swift delete mode 100644 third-party/SwiftColor/Sources/Pigment+Float.swift delete mode 100644 third-party/SwiftColor/Sources/Pigment+Hex.swift delete mode 100644 third-party/SwiftColor/Sources/Pigment+Int.swift delete mode 100644 third-party/SwiftColor/Sources/Pigment+Name.swift delete mode 100644 third-party/SwiftColor/Sources/Pigment+String.swift delete mode 100644 third-party/SwiftColor/Sources/Pigment+SwiftUI.swift delete mode 100644 third-party/SwiftColor/Sources/Pigment+UIKit.swift delete mode 100644 third-party/SwiftColor/Sources/Pigment.swift delete mode 100644 third-party/SwiftSVG/BUILD delete mode 100644 third-party/SwiftSVG/Sources/Circle.swift delete mode 100644 third-party/SwiftSVG/Sources/CommandRepresentable.swift delete mode 100644 third-party/SwiftSVG/Sources/Container.swift delete mode 100644 third-party/SwiftSVG/Sources/CoreAttributes.swift delete mode 100644 third-party/SwiftSVG/Sources/Element.swift delete mode 100644 third-party/SwiftSVG/Sources/Ellipse.swift delete mode 100644 third-party/SwiftSVG/Sources/Extensions/Point+SwiftSVG.swift delete mode 100644 third-party/SwiftSVG/Sources/Fill.swift delete mode 100644 third-party/SwiftSVG/Sources/Group.swift delete mode 100644 third-party/SwiftSVG/Sources/Internal/EllipseProcessor.swift delete mode 100644 third-party/SwiftSVG/Sources/Internal/PathProcessor.swift delete mode 100644 third-party/SwiftSVG/Sources/Internal/PolygonProcressor.swift delete mode 100644 third-party/SwiftSVG/Sources/Internal/PolylineProcessor.swift delete mode 100644 third-party/SwiftSVG/Sources/Internal/RectangleProcessor.swift delete mode 100644 third-party/SwiftSVG/Sources/Line.swift delete mode 100644 third-party/SwiftSVG/Sources/Path.Command.swift delete mode 100644 third-party/SwiftSVG/Sources/Path.Component.swift delete mode 100644 third-party/SwiftSVG/Sources/Path.ComponentParser.swift delete mode 100644 third-party/SwiftSVG/Sources/Path.swift delete mode 100644 third-party/SwiftSVG/Sources/Polygon.swift delete mode 100644 third-party/SwiftSVG/Sources/Polyline.swift delete mode 100644 third-party/SwiftSVG/Sources/PresentationAttributes.swift delete mode 100644 third-party/SwiftSVG/Sources/Rectangle.swift delete mode 100644 third-party/SwiftSVG/Sources/SVG+Swift2D.swift delete mode 100644 third-party/SwiftSVG/Sources/SVG.swift delete mode 100644 third-party/SwiftSVG/Sources/Stroke.swift delete mode 100644 third-party/SwiftSVG/Sources/StylingAttributes.swift delete mode 100644 third-party/SwiftSVG/Sources/Text.swift delete mode 100644 third-party/SwiftSVG/Sources/Transformation.swift delete mode 100644 third-party/VectorPlus/BUILD delete mode 100644 third-party/VectorPlus/Sources/CoreGraphics/CGContext+Render.swift delete mode 100644 third-party/VectorPlus/Sources/CoreGraphics/CGMutablePath+Instruction.swift delete mode 100644 third-party/VectorPlus/Sources/CoreGraphics/Fill+CoreGraphics.swift delete mode 100644 third-party/VectorPlus/Sources/CoreGraphics/SVG+CGPath.swift delete mode 100644 third-party/VectorPlus/Sources/CoreGraphics/Stroke+CoreGraphics.swift delete mode 100644 third-party/VectorPlus/Sources/Fill+VectorPlus.swift delete mode 100644 third-party/VectorPlus/Sources/Path+VectorPlus.swift delete mode 100644 third-party/VectorPlus/Sources/Path.Command+VectorPlus.swift delete mode 100644 third-party/VectorPlus/Sources/Pigment+VectorPlus.swift delete mode 100644 third-party/VectorPlus/Sources/Point+VectorPlus.swift delete mode 100644 third-party/VectorPlus/Sources/Rect+VectorPlus.swift delete mode 100644 third-party/VectorPlus/Sources/SVG+AppleSymbols.swift delete mode 100644 third-party/VectorPlus/Sources/SVG+Template.swift delete mode 100644 third-party/VectorPlus/Sources/Size+VectorPlus.swift delete mode 100644 third-party/VectorPlus/Sources/Stroke+VectorPlus.swift delete mode 100644 third-party/VectorPlus/Sources/Template+UIImageView.swift delete mode 100644 third-party/VectorPlus/Sources/UIKit/SVG+UIImage.swift delete mode 100644 third-party/VectorPlus/Sources/UIKit/SVGImageView.swift delete mode 100644 third-party/VectorPlus/Sources/VectorPoint.swift diff --git a/submodules/AccountContext/Sources/FetchManager.swift b/submodules/AccountContext/Sources/FetchManager.swift index 39ca3de10c..a705710c9c 100644 --- a/submodules/AccountContext/Sources/FetchManager.swift +++ b/submodules/AccountContext/Sources/FetchManager.swift @@ -1,5 +1,4 @@ import Foundation -import Postbox import TelegramCore import SwiftSignalKit import TelegramUIPreferences @@ -13,7 +12,7 @@ public enum FetchManagerCategory: Int32 { } public enum FetchManagerLocationKey: Comparable, Hashable { - case messageId(MessageId) + case messageId(EngineMessage.Id) case free public static func <(lhs: FetchManagerLocationKey, rhs: FetchManagerLocationKey) -> Bool { @@ -87,7 +86,7 @@ public struct FetchManagerPriorityKey: Comparable { } public enum FetchManagerLocation: Hashable, CustomStringConvertible { - case chat(PeerId) + case chat(EnginePeer.Id) public var description: String { switch self { @@ -104,8 +103,8 @@ public enum FetchManagerForegroundDirection { public enum FetchManagerPriority: Comparable { case userInitiated - case foregroundPrefetch(direction: FetchManagerForegroundDirection, localOrder: MessageIndex) - case backgroundPrefetch(locationOrder: HistoryPreloadIndex, localOrder: MessageIndex) + case foregroundPrefetch(direction: FetchManagerForegroundDirection, localOrder: EngineMessage.Index) + case backgroundPrefetch(locationOrder: HistoryPreloadIndex, localOrder: EngineMessage.Index) public static func <(lhs: FetchManagerPriority, rhs: FetchManagerPriority) -> Bool { switch lhs { @@ -160,11 +159,11 @@ public protocol FetchManager { var queue: Queue { get } func interactivelyFetched(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, mediaReference: AnyMediaReference?, resourceReference: MediaResourceReference, ranges: RangeSet, statsCategory: MediaResourceStatsCategory, elevatedPriority: Bool, userInitiated: Bool, priority: FetchManagerPriority, storeToDownloadsPeerId: EnginePeer.Id?) -> Signal - func cancelInteractiveFetches(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: MediaResource) + func cancelInteractiveFetches(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: EngineRawMediaResource) func cancelInteractiveFetches(resourceId: String) func toggleInteractiveFetchPaused(resourceId: String, isPaused: Bool) func raisePriority(resourceId: String) - func fetchStatus(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: MediaResource) -> Signal + func fetchStatus(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: EngineRawMediaResource) -> Signal } public protocol PrefetchManager { diff --git a/submodules/AccountContext/Sources/FetchMediaUtils.swift b/submodules/AccountContext/Sources/FetchMediaUtils.swift index 805ae7a967..b969890fbb 100644 --- a/submodules/AccountContext/Sources/FetchMediaUtils.swift +++ b/submodules/AccountContext/Sources/FetchMediaUtils.swift @@ -24,10 +24,6 @@ public func freeMediaFileResourceInteractiveFetched(postbox: Postbox, userLocati return fetchedMediaResource(mediaBox: postbox.mediaBox, userLocation: userLocation, userContentType: MediaResourceUserContentType(file: fileReference.media), reference: fileReference.resourceReference(resource), range: range) } -public func cancelFreeMediaFileInteractiveFetch(account: Account, file: TelegramMediaFile) { - account.postbox.mediaBox.cancelInteractiveResourceFetch(file.resource) -} - private func fetchCategoryForFile(_ file: TelegramMediaFile) -> FetchManagerCategory { if file.isVoice || file.isInstantVideo { return .voice diff --git a/submodules/AccountContext/Sources/GalleryController.swift b/submodules/AccountContext/Sources/GalleryController.swift index 7a13847f0c..02b81f7088 100644 --- a/submodules/AccountContext/Sources/GalleryController.swift +++ b/submodules/AccountContext/Sources/GalleryController.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import Display -import Postbox import SwiftSignalKit import TelegramCore @@ -10,13 +9,13 @@ public enum GalleryMediaSubject: Hashable { case pollDescription case pollOption(Data) case pollSolution - case instantPageMedia(MediaId) + case instantPageMedia(EngineMedia.Id) } public enum GalleryControllerItemSource { - case peerMessagesAtId(messageId: MessageId, chatLocation: ChatLocation, customTag: MemoryBuffer?, chatLocationContextHolder: Atomic) - case standaloneMessage(Message, GalleryMediaSubject?) - case custom(messages: Signal<([Message], Int32, Bool), NoError>, messageId: MessageId, loadMore: (() -> Void)?) + case peerMessagesAtId(messageId: EngineMessage.Id, chatLocation: ChatLocation, customTag: EngineMemoryBuffer?, chatLocationContextHolder: Atomic) + case standaloneMessage(EngineRawMessage, GalleryMediaSubject?) + case custom(messages: Signal<([EngineRawMessage], Int32, Bool), NoError>, messageId: EngineMessage.Id, loadMore: (() -> Void)?) } public final class GalleryControllerActionInteraction { @@ -26,10 +25,10 @@ public final class GalleryControllerActionInteraction { public let openPeer: (EnginePeer) -> Void public let openHashtag: (String?, String) -> Void public let openBotCommand: (String) -> Void - public let openAd: (MessageId) -> Void + public let openAd: (EngineMessage.Id) -> Void public let addContact: (String) -> Void - public let storeMediaPlaybackState: (MessageId, Double?, Double) -> Void - public let editMedia: (MessageId, [UIView], @escaping () -> Void) -> Void + public let storeMediaPlaybackState: (EngineMessage.Id, Double?, Double) -> Void + public let editMedia: (EngineMessage.Id, [UIView], @escaping () -> Void) -> Void public let updateCanReadHistory: (Bool) -> Void public let sendSticker: ((FileMediaReference) -> Void)? @@ -40,10 +39,10 @@ public final class GalleryControllerActionInteraction { openPeer: @escaping (EnginePeer) -> Void, openHashtag: @escaping (String?, String) -> Void, openBotCommand: @escaping (String) -> Void, - openAd: @escaping (MessageId) -> Void, + openAd: @escaping (EngineMessage.Id) -> Void, addContact: @escaping (String) -> Void, - storeMediaPlaybackState: @escaping (MessageId, Double?, Double) -> Void, - editMedia: @escaping (MessageId, [UIView], @escaping () -> Void) -> Void, + storeMediaPlaybackState: @escaping (EngineMessage.Id, Double?, Double) -> Void, + editMedia: @escaping (EngineMessage.Id, [UIView], @escaping () -> Void) -> Void, updateCanReadHistory: @escaping (Bool) -> Void, sendSticker: ((FileMediaReference) -> Void)? ) { diff --git a/submodules/AccountContext/Sources/OpenChatMessage.swift b/submodules/AccountContext/Sources/OpenChatMessage.swift index 43f9bf0caf..68b45fe0ed 100644 --- a/submodules/AccountContext/Sources/OpenChatMessage.swift +++ b/submodules/AccountContext/Sources/OpenChatMessage.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import TelegramCore import SwiftSignalKit import Display @@ -22,9 +21,9 @@ public final class OpenChatMessageParams { public let context: AccountContext public let updatedPresentationData: (initial: PresentationData, signal: Signal)? public let chatLocation: ChatLocation? - public let chatFilterTag: MemoryBuffer? + public let chatFilterTag: EngineMemoryBuffer? public let chatLocationContextHolder: Atomic? - public let message: Message + public let message: EngineRawMessage public let mediaSubject: GalleryMediaSubject? public let standalone: Bool public let copyProtected: Bool @@ -34,21 +33,21 @@ public final class OpenChatMessageParams { public let modal: Bool public let dismissInput: () -> Void public let present: (ViewController, Any?, PresentationContextType) -> Void - public let transitionNode: (MessageId, Media, Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? + public let transitionNode: (EngineMessage.Id, EngineRawMedia, Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? public let addToTransitionSurface: (UIView) -> Void public let openUrl: (String) -> Void - public let openPeer: (Peer, ChatControllerInteractionNavigateToPeer) -> Void - public let callPeer: (PeerId, Bool) -> Void - public let openConferenceCall: (Message) -> Void + public let openPeer: (EngineRawPeer, ChatControllerInteractionNavigateToPeer) -> Void + public let callPeer: (EnginePeer.Id, Bool) -> Void + public let openConferenceCall: (EngineRawMessage) -> Void public let enqueueMessage: (EnqueueMessage) -> Void public let sendSticker: ((FileMediaReference, UIView?, CGRect?) -> Bool)? public let sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)? - public let setupTemporaryHiddenMedia: (Signal, Int, Media) -> Void - public let chatAvatarHiddenMedia: (Signal, Media) -> Void + public let setupTemporaryHiddenMedia: (Signal, Int, EngineRawMedia) -> Void + public let chatAvatarHiddenMedia: (Signal, EngineRawMedia) -> Void public let actionInteraction: GalleryControllerActionInteraction? public let playlistLocation: PeerMessagesPlaylistLocation? public let gallerySource: GalleryControllerItemSource? - public let centralItemUpdated: ((MessageId) -> Void)? + public let centralItemUpdated: ((EngineMessage.Id) -> Void)? public let navigateToMessageContext: ((EngineMessage) -> Void)? public let getSourceRect: (() -> CGRect?)? public let blockInteraction: Promise @@ -57,9 +56,9 @@ public final class OpenChatMessageParams { context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, chatLocation: ChatLocation?, - chatFilterTag: MemoryBuffer?, + chatFilterTag: EngineMemoryBuffer?, chatLocationContextHolder: Atomic?, - message: Message, + message: EngineRawMessage, mediaSubject: GalleryMediaSubject? = nil, standalone: Bool, copyProtected: Bool = false, @@ -69,21 +68,21 @@ public final class OpenChatMessageParams { modal: Bool = false, dismissInput: @escaping () -> Void, present: @escaping (ViewController, Any?, PresentationContextType) -> Void, - transitionNode: @escaping (MessageId, Media, Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, + transitionNode: @escaping (EngineMessage.Id, EngineRawMedia, Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, addToTransitionSurface: @escaping (UIView) -> Void, openUrl: @escaping (String) -> Void, - openPeer: @escaping (Peer, ChatControllerInteractionNavigateToPeer) -> Void, - callPeer: @escaping (PeerId, Bool) -> Void, - openConferenceCall: @escaping (Message) -> Void, + openPeer: @escaping (EngineRawPeer, ChatControllerInteractionNavigateToPeer) -> Void, + callPeer: @escaping (EnginePeer.Id, Bool) -> Void, + openConferenceCall: @escaping (EngineRawMessage) -> Void, enqueueMessage: @escaping (EnqueueMessage) -> Void, sendSticker: ((FileMediaReference, UIView?, CGRect?) -> Bool)?, sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)?, - setupTemporaryHiddenMedia: @escaping (Signal, Int, Media) -> Void, - chatAvatarHiddenMedia: @escaping (Signal, Media) -> Void, + setupTemporaryHiddenMedia: @escaping (Signal, Int, EngineRawMedia) -> Void, + chatAvatarHiddenMedia: @escaping (Signal, EngineRawMedia) -> Void, actionInteraction: GalleryControllerActionInteraction? = nil, playlistLocation: PeerMessagesPlaylistLocation? = nil, gallerySource: GalleryControllerItemSource? = nil, - centralItemUpdated: ((MessageId) -> Void)? = nil, + centralItemUpdated: ((EngineMessage.Id) -> Void)? = nil, navigateToMessageContext: ((EngineMessage) -> Void)? = nil, getSourceRect: (() -> CGRect?)? = nil ) { diff --git a/submodules/AccountContext/Sources/PeerSelectionController.swift b/submodules/AccountContext/Sources/PeerSelectionController.swift index 547d98a0e6..19e8d7a3bc 100644 --- a/submodules/AccountContext/Sources/PeerSelectionController.swift +++ b/submodules/AccountContext/Sources/PeerSelectionController.swift @@ -2,7 +2,6 @@ import Foundation import Display import SwiftSignalKit import TelegramCore -import Postbox import TelegramPresentationData import AnimationCache import MultiAnimationRenderer @@ -125,39 +124,6 @@ public enum AttachmentTextInputPanelSendMode { case whenOnline } -public enum PeerSelectionControllerContext { - public final class Custom { - public let accountPeerId: EnginePeer.Id - public let postbox: Postbox - public let network: Network - public let animationCache: AnimationCache - public let animationRenderer: MultiAnimationRenderer - public let presentationData: PresentationData - public let updatedPresentationData: Signal - - public init( - accountPeerId: EnginePeer.Id, - postbox: Postbox, - network: Network, - animationCache: AnimationCache, - animationRenderer: MultiAnimationRenderer, - presentationData: PresentationData, - updatedPresentationData: Signal - ) { - self.accountPeerId = accountPeerId - self.postbox = postbox - self.network = network - self.animationCache = animationCache - self.animationRenderer = animationRenderer - self.presentationData = presentationData - self.updatedPresentationData = updatedPresentationData - } - } - - case account(AccountContext) - case custom(Custom) -} - public protocol PeerSelectionController: ViewController { var peerSelected: ((EnginePeer, Int64?) -> Void)? { get set } var multiplePeersSelected: (([EnginePeer], [EnginePeer.Id: EnginePeer], NSAttributedString, AttachmentTextInputPanelSendMode, ChatInterfaceForwardOptionsState?, ChatSendMessageActionSheetController.SendParameters?) -> Void)? { get set } diff --git a/submodules/AccountContext/Sources/PresentationCallManager.swift b/submodules/AccountContext/Sources/PresentationCallManager.swift index 62bde63548..a3ac3bb3bd 100644 --- a/submodules/AccountContext/Sources/PresentationCallManager.swift +++ b/submodules/AccountContext/Sources/PresentationCallManager.swift @@ -309,22 +309,6 @@ public struct PresentationGroupCallSummaryState: Equatable { } } -public struct PresentationGroupCallMemberState: Equatable { - public var ssrc: UInt32 - public var muteState: GroupCallParticipantsContext.Participant.MuteState? - public var speaking: Bool - - public init( - ssrc: UInt32, - muteState: GroupCallParticipantsContext.Participant.MuteState?, - speaking: Bool - ) { - self.ssrc = ssrc - self.muteState = muteState - self.speaking = speaking - } -} - public enum PresentationGroupCallMuteAction: Equatable { case muted(isPushToTalkActive: Bool) case unmuted diff --git a/submodules/AccountContext/Sources/ShareController.swift b/submodules/AccountContext/Sources/ShareController.swift index 5ef521a5d5..a018a1f987 100644 --- a/submodules/AccountContext/Sources/ShareController.swift +++ b/submodules/AccountContext/Sources/ShareController.swift @@ -1,6 +1,5 @@ import Foundation import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -9,7 +8,7 @@ import MultiAnimationRenderer import Display public enum StorySharingSubject { - case messages([Message]) + case messages([EngineRawMessage]) case gift(StarGift.UniqueGift) } @@ -110,11 +109,11 @@ public enum ShareControllerSubject { case url(String) case text(String) case quote(text: String, url: String) - case messages([Message]) + case messages([EngineRawMessage]) case image([ImageRepresentationWithReference]) case media(AnyMediaReference, MediaParameters?) case mapMedia(TelegramMediaMap) - case fromExternal(Int, ([PeerId], [PeerId: Int64], [PeerId: StarsAmount], String, ShareControllerAccountContext, Bool) -> Signal) + case fromExternal(Int, ([EnginePeer.Id], [EnginePeer.Id: Int64], [EnginePeer.Id: StarsAmount], String, ShareControllerAccountContext, Bool) -> Signal) } public struct ShareControllerAction { @@ -151,12 +150,12 @@ public final class ShareControllerParams { public let subject: ShareControllerSubject public let presetText: String? public let preferredAction: ShareControllerPreferredAction - public let showInChat: ((Message) -> Void)? + public let showInChat: ((EngineRawMessage) -> Void)? public let fromForeignApp: Bool public let segmentedValues: [ShareControllerSegmentedValue]? public let externalShare: Bool public let immediateExternalShare: Bool - public let immediatePeerId: PeerId? + public let immediatePeerId: EnginePeer.Id? public let updatedPresentationData: (initial: PresentationData, signal: Signal)? public let forceTheme: PresentationTheme? public let forcedActionTitle: String? @@ -165,8 +164,8 @@ public final class ShareControllerParams { public let actionCompleted: (() -> Void)? public let dismissed: ((Bool) -> Void)? - public let completed: (([PeerId]) -> Void)? - public let enqueued: (([PeerId], [Int64]) -> Void)? + public let completed: (([EnginePeer.Id]) -> Void)? + public let enqueued: (([EnginePeer.Id], [Int64]) -> Void)? public let shareStory: (() -> Void)? public let debugAction: (() -> Void)? public let onMediaTimestampLinkCopied: ((Int32?) -> Void)? @@ -177,12 +176,12 @@ public final class ShareControllerParams { subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, - showInChat: ((Message) -> Void)? = nil, + showInChat: ((EngineRawMessage) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, - immediatePeerId: PeerId? = nil, + immediatePeerId: EnginePeer.Id? = nil, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil, @@ -190,8 +189,8 @@ public final class ShareControllerParams { collectibleItemInfo: TelegramCollectibleItemInfo? = nil, actionCompleted: (() -> Void)? = nil, dismissed: ((Bool) -> Void)? = nil, - completed: (([PeerId]) -> Void)? = nil, - enqueued: (([PeerId], [Int64]) -> Void)? = nil, + completed: (([EnginePeer.Id]) -> Void)? = nil, + enqueued: (([EnginePeer.Id], [Int64]) -> Void)? = nil, shareStory: (() -> Void)? = nil, debugAction: (() -> Void)? = nil, onMediaTimestampLinkCopied: ((Int32?) -> Void)? = nil, diff --git a/submodules/AuthorizationUI/BUILD b/submodules/AuthorizationUI/BUILD index cc280f1551..00851a3e15 100644 --- a/submodules/AuthorizationUI/BUILD +++ b/submodules/AuthorizationUI/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/TelegramCore:TelegramCore", - "//submodules/Postbox:Postbox", "//submodules/Display:Display", "//submodules/SSignalKit/SSignalKit", "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", diff --git a/submodules/AvatarNode/Sources/AvatarNode.swift b/submodules/AvatarNode/Sources/AvatarNode.swift index bbecec9430..e690da30ad 100644 --- a/submodules/AvatarNode/Sources/AvatarNode.swift +++ b/submodules/AvatarNode/Sources/AvatarNode.swift @@ -643,7 +643,7 @@ public final class AvatarNode: ASDisplayNode { let parameters: AvatarNodeParameters - if let peer = peer, let signal = peerAvatarImage(postbox: postbox, network: network, peerReference: PeerReference(peer), authorOfMessage: authorOfMessage, representation: representation, displayDimensions: displayDimensions, clipStyle: clipStyle, emptyColor: emptyColor, synchronousLoad: synchronousLoad, provideUnrounded: storeUnrounded, cutoutRect: cutoutRect) { + if let peer = peer, let signal = peerAvatarImage(postbox: postbox, peerReference: PeerReference(peer), authorOfMessage: authorOfMessage, representation: representation, displayDimensions: displayDimensions, clipStyle: clipStyle, emptyColor: emptyColor, synchronousLoad: synchronousLoad, provideUnrounded: storeUnrounded, cutoutRect: cutoutRect) { self.contents = nil self.displaySuspended = true self.imageReady.set(self.imageNode.contentReady) diff --git a/submodules/AvatarNode/Sources/PeerAvatar.swift b/submodules/AvatarNode/Sources/PeerAvatar.swift index 61b7742175..caf06427e9 100644 --- a/submodules/AvatarNode/Sources/PeerAvatar.swift +++ b/submodules/AvatarNode/Sources/PeerAvatar.swift @@ -27,11 +27,7 @@ public enum PeerAvatarImageType { case complete } -public func peerAvatarImageData(account: Account, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, synchronousLoad: Bool) -> Signal<(Data, PeerAvatarImageType)?, NoError>? { - return peerAvatarImageData(postbox: account.postbox, network: account.network, peerReference: peerReference, authorOfMessage: authorOfMessage, representation: representation, synchronousLoad: synchronousLoad) -} - -public func peerAvatarImageData(postbox: Postbox, network: Network, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, synchronousLoad: Bool) -> Signal<(Data, PeerAvatarImageType)?, NoError>? { +public func peerAvatarImageData(postbox: Postbox, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, synchronousLoad: Bool) -> Signal<(Data, PeerAvatarImageType)?, NoError>? { if let smallProfileImage = representation { let resourceData = postbox.mediaBox.resourceData(smallProfileImage.resource, attemptSynchronously: synchronousLoad) let imageData = resourceData @@ -92,7 +88,6 @@ public func peerAvatarImageData(postbox: Postbox, network: Network, peerReferenc public func peerAvatarCompleteImage(account: Account, peer: EnginePeer, forceProvidedRepresentation: Bool = false, representation: TelegramMediaImageRepresentation? = nil, size: CGSize, round: Bool = true, font: UIFont = avatarPlaceholderFont(size: 13.0), drawLetters: Bool = true, fullSize: Bool = false, blurred: Bool = false) -> Signal { return peerAvatarCompleteImage( postbox: account.postbox, - network: account.network, peer: peer, forceProvidedRepresentation: forceProvidedRepresentation, representation: representation, @@ -105,7 +100,7 @@ public func peerAvatarCompleteImage(account: Account, peer: EnginePeer, forcePro ) } -public func peerAvatarCompleteImage(postbox: Postbox, network: Network, peer: EnginePeer, forceProvidedRepresentation: Bool = false, representation: TelegramMediaImageRepresentation? = nil, size: CGSize, round: Bool = true, font: UIFont = avatarPlaceholderFont(size: 13.0), drawLetters: Bool = true, fullSize: Bool = false, blurred: Bool = false) -> Signal { +public func peerAvatarCompleteImage(postbox: Postbox, peer: EnginePeer, forceProvidedRepresentation: Bool = false, representation: TelegramMediaImageRepresentation? = nil, size: CGSize, round: Bool = true, font: UIFont = avatarPlaceholderFont(size: 13.0), drawLetters: Bool = true, fullSize: Bool = false, blurred: Bool = false) -> Signal { let iconSignal: Signal let clipStyle: AvatarNodeClipStyle @@ -126,8 +121,8 @@ public func peerAvatarCompleteImage(postbox: Postbox, network: Network, peer: En thumbnailRepresentation = peer.profileImageRepresentations.first } - if let signal = peerAvatarImage(postbox: postbox, network: network, peerReference: PeerReference(peer), authorOfMessage: nil, representation: thumbnailRepresentation, displayDimensions: size, clipStyle: clipStyle, blurred: blurred, inset: 0.0, emptyColor: nil, synchronousLoad: fullSize) { - if fullSize, let fullSizeSignal = peerAvatarImage(postbox: postbox, network: network, peerReference: PeerReference(peer), authorOfMessage: nil, representation: peer.profileImageRepresentations.last, displayDimensions: size, emptyColor: nil, synchronousLoad: true) { + if let signal = peerAvatarImage(postbox: postbox, peerReference: PeerReference(peer), authorOfMessage: nil,representation: thumbnailRepresentation, displayDimensions: size, clipStyle: clipStyle, blurred: blurred, inset: 0.0, emptyColor: nil, synchronousLoad: fullSize) { + if fullSize, let fullSizeSignal = peerAvatarImage(postbox: postbox, peerReference: PeerReference(peer), authorOfMessage: nil,representation: peer.profileImageRepresentations.last, displayDimensions: size, emptyColor: nil, synchronousLoad: true) { iconSignal = combineLatest(.single(nil) |> then(signal), .single(nil) |> then(fullSizeSignal)) |> mapToSignal { thumbnailImage, fullSizeImage -> Signal in if let fullSizeImage = fullSizeImage { @@ -174,7 +169,6 @@ public func peerAvatarCompleteImage(postbox: Postbox, network: Network, peer: En public func peerAvatarImage(account: Account, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, displayDimensions: CGSize = CGSize(width: 60.0, height: 60.0), clipStyle: AvatarNodeClipStyle = .round, blurred: Bool = false, inset: CGFloat = 0.0, emptyColor: UIColor? = nil, synchronousLoad: Bool = false, provideUnrounded: Bool = false, cutoutRect: CGRect? = nil) -> Signal<(UIImage, UIImage)?, NoError>? { return peerAvatarImage( postbox: account.postbox, - network: account.network, peerReference: peerReference, authorOfMessage: authorOfMessage, representation: representation, @@ -189,8 +183,8 @@ public func peerAvatarImage(account: Account, peerReference: PeerReference?, aut ) } -public func peerAvatarImage(postbox: Postbox, network: Network, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, displayDimensions: CGSize = CGSize(width: 60.0, height: 60.0), clipStyle: AvatarNodeClipStyle = .round, blurred: Bool = false, inset: CGFloat = 0.0, emptyColor: UIColor? = nil, synchronousLoad: Bool = false, provideUnrounded: Bool = false, cutoutRect: CGRect? = nil) -> Signal<(UIImage, UIImage)?, NoError>? { - if let imageData = peerAvatarImageData(postbox: postbox, network: network, peerReference: peerReference, authorOfMessage: authorOfMessage, representation: representation, synchronousLoad: synchronousLoad) { +public func peerAvatarImage(postbox: Postbox, peerReference: PeerReference?, authorOfMessage: MessageReference?, representation: TelegramMediaImageRepresentation?, displayDimensions: CGSize = CGSize(width: 60.0, height: 60.0), clipStyle: AvatarNodeClipStyle = .round, blurred: Bool = false, inset: CGFloat = 0.0, emptyColor: UIColor? = nil, synchronousLoad: Bool = false, provideUnrounded: Bool = false, cutoutRect: CGRect? = nil) -> Signal<(UIImage, UIImage)?, NoError>? { + if let imageData = peerAvatarImageData(postbox: postbox, peerReference: peerReference, authorOfMessage: authorOfMessage, representation: representation, synchronousLoad: synchronousLoad) { return imageData |> mapToSignal { data -> Signal<(UIImage, UIImage)?, NoError> in let generate = deferred { () -> Signal<(UIImage, UIImage)?, NoError> in diff --git a/submodules/BrowserUI/Sources/BrowserMarkdown.swift b/submodules/BrowserUI/Sources/BrowserMarkdown.swift index c3723b4075..d5669a19c7 100644 --- a/submodules/BrowserUI/Sources/BrowserMarkdown.swift +++ b/submodules/BrowserUI/Sources/BrowserMarkdown.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import TelegramCore import AccountContext import InstantPageUI @@ -211,7 +210,7 @@ private final class MarkdownConversionBudget { private struct MarkdownPageResult { let blocks: [InstantPageBlock] - let media: [MediaId: Media] + let media: [EngineMedia.Id: EngineRawMedia] } private enum MarkdownFormulaMode { @@ -315,7 +314,7 @@ private struct MarkdownInlineContent { } private struct MarkdownResolvedImage { - let mediaId: MediaId + let mediaId: EngineMedia.Id let inlineDimensions: PixelDimensions let caption: InstantPageCaption let linkUrl: String? @@ -340,7 +339,7 @@ private final class MarkdownConversionContext { private var nextRemoteMediaId: Int64 = 0 private var nextLocalMediaId: Int64 = 0 - private(set) var media: [MediaId: Media] = [:] + private(set) var media: [EngineMedia.Id: EngineRawMedia] = [:] init(context: AccountContext, documentURL: URL, formulasByPlaceholder: [String: MarkdownFormulaDescriptor], budget: MarkdownConversionBudget) { self.context = context @@ -426,14 +425,14 @@ private final class MarkdownConversionContext { } } - private func nextMediaId(namespace: Int32) -> MediaId { + private func nextMediaId(namespace: Int32) -> EngineMedia.Id { switch namespace { case Namespaces.Media.LocalImage: self.nextLocalMediaId += 1 - return MediaId(namespace: namespace, id: self.nextLocalMediaId) + return EngineMedia.Id(namespace: namespace, id: self.nextLocalMediaId) default: self.nextRemoteMediaId += 1 - return MediaId(namespace: namespace, id: self.nextRemoteMediaId) + return EngineMedia.Id(namespace: namespace, id: self.nextRemoteMediaId) } } } @@ -1028,7 +1027,7 @@ private func markdownWebpage(context: AccountContext, file: FileMediaReference, ) return TelegramMediaWebpage( - webpageId: MediaId(namespace: 0, id: 0), + webpageId: EngineMedia.Id(namespace: 0, id: 0), content: .Loaded( TelegramMediaWebpageLoadedContent( url: fileURL.absoluteString, diff --git a/submodules/BrowserUI/Sources/BrowserReadability.swift b/submodules/BrowserUI/Sources/BrowserReadability.swift index e021ad2d01..c63a4469bf 100644 --- a/submodules/BrowserUI/Sources/BrowserReadability.swift +++ b/submodules/BrowserUI/Sources/BrowserReadability.swift @@ -1,7 +1,6 @@ import Foundation import WebKit import AppBundle -import Postbox import TelegramCore import InstantPageUI @@ -115,14 +114,14 @@ private func parseJson(_ input: [String: Any], url: String) -> TelegramMediaWebp let byline = input["byline"] as? String let excerpt = input["excerpt"] as? String - var media: [MediaId: Media] = [:] + var media: [EngineMedia.Id: EngineRawMedia] = [:] let blocks = parseContent(input, url, &media) guard !blocks.isEmpty else { return nil } return TelegramMediaWebpage( - webpageId: MediaId(namespace: 0, id: 0), + webpageId: EngineMedia.Id(namespace: 0, id: 0), content: .Loaded( TelegramMediaWebpageLoadedContent( url: url, @@ -156,7 +155,7 @@ private func parseJson(_ input: [String: Any], url: String) -> TelegramMediaWebp ) } -private func parseContent(_ input: [String: Any], _ url: String, _ media: inout [MediaId: Media]) -> [InstantPageBlock] { +private func parseContent(_ input: [String: Any], _ url: String, _ media: inout [EngineMedia.Id: EngineRawMedia]) -> [InstantPageBlock] { let title = input["title"] as? String let byline = input["byline"] as? String let date = input["publishedTime"] as? String @@ -185,7 +184,7 @@ private func parseRichText(_ input: String) -> RichText { return .plain(input) } -private func parseRichText(_ input: [String: Any], _ media: inout [MediaId: Media]) -> RichText { +private func parseRichText(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> RichText { var text: RichText if let string = input["content"] as? String { text = parseRichText(string) @@ -204,7 +203,7 @@ private func parseRichText(_ input: [String: Any], _ media: inout [MediaId: Medi return text } -private func parseRichText(_ input: [Any], _ media: inout [MediaId: Media]) -> RichText { +private func parseRichText(_ input: [Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> RichText { var result: [RichText] = [] for item in input { @@ -258,7 +257,7 @@ private func parseRichText(_ input: [Any], _ media: inout [MediaId: Media]) -> R } else { height = 0 } - let id = MediaId(namespace: Namespaces.Media.CloudFile, id: Int64(media.count)) + let id = EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: Int64(media.count)) media[id] = TelegramMediaImage( imageId: id, representations: [ @@ -489,7 +488,7 @@ private func applyAnchor(_ input: RichText, item: [String: Any]) -> RichText { return .anchor(text: input, name: id) } -private func parseTable(_ input: [String: Any], _ media: inout [MediaId: Media]) -> InstantPageBlock { +private func parseTable(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock { let title = (input["title"] as? String) ?? "" return .table( title: trim(applyAnchor(parseRichText(title), item: input)), @@ -499,7 +498,7 @@ private func parseTable(_ input: [String: Any], _ media: inout [MediaId: Media]) ) } -private func parseTableRows(_ input: [Any], _ media: inout [MediaId: Media]) -> [InstantPageTableRow] { +private func parseTableRows(_ input: [Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> [InstantPageTableRow] { var result: [InstantPageTableRow] = [] for item in input { if let item = item as? [String: Any] { @@ -514,7 +513,7 @@ private func parseTableRows(_ input: [Any], _ media: inout [MediaId: Media]) -> return result } -private func parseTableRow(_ input: [String: Any], _ media: inout [MediaId: Media]) -> InstantPageTableRow { +private func parseTableRow(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageTableRow { var cells: [InstantPageTableCell] = [] if let content = input["content"] as? [Any] { @@ -552,7 +551,7 @@ private func parseTableRow(_ input: [String: Any], _ media: inout [MediaId: Medi return InstantPageTableRow(cells: cells) } -private func parseDetails(_ item: [String: Any], _ url: String, _ media: inout [MediaId: Media]) -> InstantPageBlock? { +private func parseDetails(_ item: [String: Any], _ url: String, _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock? { guard var content = item["contant"] as? [Any] else { return nil } @@ -576,7 +575,7 @@ private func parseDetails(_ item: [String: Any], _ url: String, _ media: inout [ } private let nonListCharacters = CharacterSet(charactersIn: "0123456789").inverted -private func parseList(_ input: [String: Any], _ url: String, _ media: inout [MediaId: Media]) -> InstantPageBlock? { +private func parseList(_ input: [String: Any], _ url: String, _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock? { guard let content = input["content"] as? [Any], let tag = input["tag"] as? String else { return nil } @@ -625,7 +624,7 @@ private func parseList(_ input: [String: Any], _ url: String, _ media: inout [Me return .list(items: items, ordered: ordered) } -private func parseImage(_ input: [String: Any], _ media: inout [MediaId: Media]) -> InstantPageBlock? { +private func parseImage(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock? { guard let src = input["src"] as? String else { return nil } @@ -654,7 +653,7 @@ private func parseImage(_ input: [String: Any], _ media: inout [MediaId: Media]) height = 0 } - let id = MediaId(namespace: Namespaces.Media.CloudImage, id: Int64(media.count)) + let id = EngineMedia.Id(namespace: Namespaces.Media.CloudImage, id: Int64(media.count)) media[id] = TelegramMediaImage( imageId: id, representations: [ @@ -679,7 +678,7 @@ private func parseImage(_ input: [String: Any], _ media: inout [MediaId: Media]) ) } -private func parseVideo(_ input: [String: Any], _ media: inout [MediaId: Media]) -> InstantPageBlock? { +private func parseVideo(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock? { guard let src = input["src"] as? String else { return nil } @@ -709,7 +708,7 @@ private func parseVideo(_ input: [String: Any], _ media: inout [MediaId: Media]) ) } -private func parseFigure(_ input: [String: Any], _ media: inout [MediaId: Media]) -> InstantPageBlock? { +private func parseFigure(_ input: [String: Any], _ media: inout [EngineMedia.Id: EngineRawMedia]) -> InstantPageBlock? { guard let content = input["content"] as? [Any] else { return nil } @@ -743,7 +742,7 @@ private func parseFigure(_ input: [String: Any], _ media: inout [MediaId: Media] return block } -private func parsePageBlocks(_ input: [Any], _ url: String, _ media: inout [MediaId: Media]) -> [InstantPageBlock] { +private func parsePageBlocks(_ input: [Any], _ url: String, _ media: inout [EngineMedia.Id: EngineRawMedia]) -> [InstantPageBlock] { var result: [InstantPageBlock] = [] for item in input { if let string = item as? String { diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 09eec8961f..9a5b05d768 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -28,7 +28,6 @@ import InstantPageUI import ChatInterfaceState import UndoUI import TextFormat -import Postbox import TelegramAnimatedStickerNode import AnimationCache import MultiAnimationRenderer @@ -63,12 +62,12 @@ final class ChatListSearchInteraction { let present: (ViewController, Any?) -> Void let dismissInput: () -> Void let getSelectedMessageIds: () -> Set? - let openStories: ((PeerId, ASDisplayNode) -> Void)? + let openStories: ((EnginePeer.Id, ASDisplayNode) -> Void)? let switchToFilter: (ChatListSearchPaneKey) -> Void let dismissSearch: () -> Void let openAdInfo: (ASDisplayNode, AdPeer) -> Void - init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set?, openStories: ((PeerId, ASDisplayNode) -> Void)?, switchToFilter: @escaping (ChatListSearchPaneKey) -> Void, dismissSearch: @escaping () -> Void, openAdInfo: @escaping (ASDisplayNode, AdPeer) -> Void) { + init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set?, openStories: ((EnginePeer.Id, ASDisplayNode) -> Void)?, switchToFilter: @escaping (ChatListSearchPaneKey) -> Void, dismissSearch: @escaping () -> Void, openAdInfo: @escaping (ASDisplayNode, AdPeer) -> Void) { self.openPeer = openPeer self.openDisabledPeer = openDisabledPeer self.openMessage = openMessage @@ -215,14 +214,14 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo let interaction = ChatListSearchInteraction(openPeer: { peer, chatPeer, threadId, value in originalOpenPeer(peer, chatPeer, threadId, value) if peer.id.namespace != Namespaces.Peer.SecretChat { - addAppLogEvent(postbox: context.account.postbox, type: "search_global_open_peer", peerId: peer.id) + context.engine.accountData.addAppLogEvent(type: "search_global_open_peer") } }, openDisabledPeer: { peer, threadId, reason in openDisabledPeer(peer, threadId, reason) }, openMessage: { peer, threadId, messageId, deactivateOnAction in originalOpenMessage(peer, threadId, messageId, deactivateOnAction) if peer.id.namespace != Namespaces.Peer.SecretChat { - addAppLogEvent(postbox: context.account.postbox, type: "search_global_open_message", peerId: peer.id, data: .dictionary(["msg_id": .number(Double(messageId.id))])) + context.engine.accountData.addAppLogEvent(type: "search_global_open_message", data: .dictionary(["msg_id": .number(Double(messageId.id))])) } }, openUrl: { [weak self] url in let _ = openUserGeneratedUrl(context: context, peerId: nil, url: url, concealed: false, present: { c in @@ -1396,16 +1395,16 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo return } - var resourceIds = Set() + var resourceIds = Set() for message in messages { for media in message.media { if let file = media as? TelegramMediaFile { - resourceIds.insert(file.resource.id) + resourceIds.insert(EngineMediaResource.Id(file.resource.id)) } } } - - let _ = (strongSelf.context.engine.resources.removeCachedResources(ids: resourceIds.map { EngineMediaResource.Id($0) }, force: true, notify: true) + + let _ = (strongSelf.context.engine.resources.removeCachedResources(ids: Array(resourceIds), force: true, notify: true) |> deliverOnMainQueue).startStandalone(completed: { guard let strongSelf = self else { return diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index d702a7d420..0b47c1eacf 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -2732,7 +2732,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } } else { if !finalQuery.isEmpty { - addAppLogEvent(postbox: context.account.postbox, type: "search_global_query") + context.engine.accountData.addAppLogEvent(type: "search_global_query") } let searchSignals: [Signal<(SearchMessagesResult, SearchMessagesState), NoError>] diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index abc01321fb..7cb442d48e 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import ItemListUI @@ -2624,18 +2623,18 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { } if case .chatList = item.chatListLocation, itemPeer.peerId == item.context.account.peerId, let message = messages.first { - var effectiveAuthor: Peer? = message.author?._asPeer() + var effectiveAuthor: EngineRawPeer? = message.author?._asPeer() if let forwardInfo = message.forwardInfo { effectiveAuthor = forwardInfo.author if effectiveAuthor == nil, let authorSignature = forwardInfo.authorSignature { - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) + effectiveAuthor = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.Empty, id: EnginePeer.Id.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) } } if let sourceAuthorInfo = message._asMessage().sourceAuthorInfo { if let originalAuthor = sourceAuthorInfo.originalAuthor, let peer = message.peers[originalAuthor] { effectiveAuthor = peer } else if let authorSignature = sourceAuthorInfo.originalAuthorName { - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) + effectiveAuthor = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.Empty, id: EnginePeer.Id.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) } } @@ -2960,10 +2959,10 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { case let .preview(dimensions, immediateThumbnailData, videoDuration): if let immediateThumbnailData { if let videoDuration { - let thumbnailMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: index), partialReference: nil, resource: EmptyMediaResource(), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Video(duration: Double(videoDuration), size: dimensions ?? PixelDimensions(width: 1, height: 1), flags: [], preloadSize: nil, coverTime: nil, videoCodec: nil)], alternativeRepresentations: []) + let thumbnailMedia = TelegramMediaFile(fileId: EngineMedia.Id(namespace: 0, id: index), partialReference: nil, resource: EmptyMediaResource(), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Video(duration: Double(videoDuration), size: dimensions ?? PixelDimensions(width: 1, height: 1), flags: [], preloadSize: nil, coverTime: nil, videoCodec: nil)], alternativeRepresentations: []) contentImageSpecs.append(ContentImageSpec(message: message, media: .file(thumbnailMedia), size: fitSize)) } else { - let thumbnailMedia = TelegramMediaImage(imageId: MediaId(namespace: 0, id: index), representations: [], immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) + let thumbnailMedia = TelegramMediaImage(imageId: EngineMedia.Id(namespace: 0, id: index), representations: [], immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) contentImageSpecs.append(ContentImageSpec(message: message, media: .image(thumbnailMedia), size: fitSize)) } index += 1 @@ -3196,7 +3195,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { textAttributedString = attributedText let dateText: String - var topIndex: MessageIndex? + var topIndex: EngineMessage.Index? switch item.content { case .loading: break diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 8213296e4b..a835020531 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -16,7 +16,6 @@ import ChatListSearchItemHeader import PremiumUI import AnimationCache import MultiAnimationRenderer -import Postbox import ChatFolderLinkPreviewScreen import StoryContainerScreen import ChatListHeaderComponent @@ -1239,7 +1238,7 @@ public final class ChatListNode: ListViewImpl { case .Header, .Hole: return nil case let .PeerId(value): - return PeerId(value) + return EnginePeer.Id(value) case .ThreadId, .GroupId, .ContactId, .ArchiveIntro, .EmptyIntro, .SectionHeader, .Notice, .additionalCategory, .TopPeer: return nil } @@ -2618,7 +2617,7 @@ public final class ChatListNode: ListViewImpl { strongSelf.enqueueHistoryPreloadUpdate() } - var refreshStoryPeerIds: [PeerId] = [] + var refreshStoryPeerIds: [EnginePeer.Id] = [] var isHiddenItemVisible = false if let range = range.visibleRange { let entryCount = chatListView.filteredEntries.count diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift index 0833307f24..5eea683612 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import AsyncDisplayKit -import Postbox import SwiftSignalKit import TelegramCore import Display @@ -71,18 +70,18 @@ public final class ChatPanelInterfaceInteraction { case editPrice } - public let setupReplyMessage: (MessageId?, EngineMessageReplyInnerSubject?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void - public let setupEditMessage: (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void - public let beginMessageSelection: ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void + public let setupReplyMessage: (EngineMessage.Id?, EngineMessageReplyInnerSubject?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void + public let setupEditMessage: (EngineMessage.Id?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void + public let beginMessageSelection: ([EngineMessage.Id], @escaping (ContainedViewLayoutTransition) -> Void) -> Void public let cancelMessageSelection: (ContainedViewLayoutTransition) -> Void public let deleteSelectedMessages: () -> Void public let reportSelectedMessages: () -> Void - public let reportMessages: ([Message], ContextControllerProtocol?) -> Void - public let blockMessageAuthor: (Message, ContextControllerProtocol?) -> Void - public let deleteMessages: ([Message], ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void + public let reportMessages: ([EngineRawMessage], ContextControllerProtocol?) -> Void + public let blockMessageAuthor: (EngineRawMessage, ContextControllerProtocol?) -> Void + public let deleteMessages: ([EngineRawMessage], ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void public let forwardSelectedMessages: () -> Void public let forwardCurrentForwardMessages: () -> Void - public let forwardMessages: ([Message]) -> Void + public let forwardMessages: ([EngineRawMessage]) -> Void public let updateForwardOptionsState: ((ChatInterfaceForwardOptionsState) -> ChatInterfaceForwardOptionsState) -> Void public let presentForwardOptions: (UIView) -> Void public let presentReplyOptions: (UIView) -> Void @@ -90,7 +89,7 @@ public final class ChatPanelInterfaceInteraction { public let presentSuggestPostOptions: () -> Void public let shareSelectedMessages: () -> Void public let updateTextInputStateAndMode: (@escaping (ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void - public let updateInputModeAndDismissedButtonKeyboardMessageId: ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void + public let updateInputModeAndDismissedButtonKeyboardMessageId: ((ChatPresentationInterfaceState) -> (ChatInputMode, EngineMessage.Id?)) -> Void public let openStickers: () -> Void public let editMessage: () -> Void public let beginMessageSearch: (ChatSearchDomain, String) -> Void @@ -100,17 +99,17 @@ public final class ChatPanelInterfaceInteraction { public let openSearchResults: () -> Void public let openCalendarSearch: () -> Void public let toggleMembersSearch: (Bool) -> Void - public let navigateToMessage: (MessageId, Bool, Bool, ChatLoadingMessageSubject) -> Void - public let navigateToChat: (PeerId) -> Void - public let navigateToProfile: (PeerId) -> Void + public let navigateToMessage: (EngineMessage.Id, Bool, Bool, ChatLoadingMessageSubject) -> Void + public let navigateToChat: (EnginePeer.Id) -> Void + public let navigateToProfile: (EnginePeer.Id) -> Void public let openPeerInfo: () -> Void public let togglePeerNotifications: () -> Void public let sendContextResult: (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool - public let sendBotCommand: (Peer, String) -> Void + public let sendBotCommand: (EngineRawPeer, String) -> Void public let sendShortcut: (Int32) -> Void public let openEditShortcuts: () -> Void public let sendBotStart: (String?) -> Void - public let botSwitchChatWithPayload: (PeerId, String) -> Void + public let botSwitchChatWithPayload: (EnginePeer.Id, String) -> Void public let beginMediaRecording: (Bool) -> Void public let finishMediaRecording: (ChatFinishMediaRecordingAction) -> Void public let stopMediaRecording: () -> Void @@ -122,20 +121,20 @@ public final class ChatPanelInterfaceInteraction { public let displayVideoUnmuteTip: (CGPoint?) -> Void public let switchMediaRecordingMode: () -> Void public let setupMessageAutoremoveTimeout: () -> Void - public let sendSticker: (FileMediaReference, Bool, UIView?, CGRect?, CALayer?, [ItemCollectionId]) -> Bool + public let sendSticker: (FileMediaReference, Bool, UIView?, CGRect?, CALayer?, [EngineItemCollectionId]) -> Bool public let editSticker: (TelegramMediaFile) -> Void public let unblockPeer: () -> Void - public let pinMessage: (MessageId, ContextControllerProtocol?) -> Void - public let unpinMessage: (MessageId, Bool, ContextControllerProtocol?) -> Void + public let pinMessage: (EngineMessage.Id, ContextControllerProtocol?) -> Void + public let unpinMessage: (EngineMessage.Id, Bool, ContextControllerProtocol?) -> Void public let unpinAllMessages: () -> Void - public let openPinnedList: (MessageId) -> Void + public let openPinnedList: (EngineMessage.Id) -> Void public let shareAccountContact: () -> Void public let reportPeer: () -> Void public let presentPeerContact: () -> Void public let dismissReportPeer: () -> Void public let deleteChat: () -> Void public let beginCall: (Bool) -> Void - public let toggleMessageStickerStarred: (MessageId) -> Void + public let toggleMessageStickerStarred: (EngineMessage.Id) -> Void public let presentController: (ViewController, Any?) -> Void public let presentControllerInCurrent: (ViewController, Any?) -> Void public let getNavigationController: () -> NavigationController? @@ -143,8 +142,8 @@ public final class ChatPanelInterfaceInteraction { public let navigateFeed: () -> Void public let openGrouping: () -> Void public let toggleSilentPost: () -> Void - public let requestUnvoteInMessage: (MessageId) -> Void - public let requestStopPollInMessage: (MessageId) -> Void + public let requestUnvoteInMessage: (EngineMessage.Id) -> Void + public let requestStopPollInMessage: (EngineMessage.Id) -> Void public let updateInputLanguage: (@escaping (String?) -> String?) -> Void public let unarchiveChat: () -> Void public let openLinkEditing: () -> Void @@ -156,9 +155,9 @@ public final class ChatPanelInterfaceInteraction { public let openPeersNearby: () -> Void public let unarchivePeer: () -> Void public let scrollToTop: () -> Void - public let viewReplies: (MessageId?, ChatReplyThreadMessage) -> Void + public let viewReplies: (EngineMessage.Id?, ChatReplyThreadMessage) -> Void public let activatePinnedListPreview: (ASDisplayNode, ContextGesture) -> Void - public let editMessageMedia: (MessageId, Bool) -> Void + public let editMessageMedia: (EngineMessage.Id, Bool) -> Void public let joinGroupCall: (CachedChannelData.ActiveCall) -> Void public let presentInviteMembers: () -> Void public let presentGigagroupHelp: () -> Void @@ -179,7 +178,7 @@ public final class ChatPanelInterfaceInteraction { public let addDoNotTranslateLanguage: (String) -> Void public let hideTranslationPanel: () -> Void public let openPremiumGift: () -> Void - public let openSuggestPost: (Message?, OpenSuggestPostMode) -> Void + public let openSuggestPost: (EngineRawMessage?, OpenSuggestPostMode) -> Void public let openPremiumRequiredForMessaging: () -> Void public let openStarsPurchase: (Int64?) -> Void public let openMessagePayment: () -> Void @@ -190,7 +189,7 @@ public final class ChatPanelInterfaceInteraction { public let openBoostToUnrestrict: () -> Void public let updateRecordingTrimRange: (Double, Double, Bool, Bool) -> Void public let dismissAllTooltips: () -> Void - public let editTodoMessage: (MessageId, Int32?, Bool) -> Void + public let editTodoMessage: (EngineMessage.Id, Int32?, Bool) -> Void public let dismissUrlPreview: () -> Void public let dismissForwardMessages: () -> Void public let dismissSuggestPost: () -> Void @@ -204,18 +203,18 @@ public final class ChatPanelInterfaceInteraction { public let statuses: ChatPanelInterfaceInteractionStatuses? public init( - setupReplyMessage: @escaping (MessageId?, EngineMessageReplyInnerSubject?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void, - setupEditMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void, - beginMessageSelection: @escaping ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void, + setupReplyMessage: @escaping (EngineMessage.Id?, EngineMessageReplyInnerSubject?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void, + setupEditMessage: @escaping (EngineMessage.Id?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void, + beginMessageSelection: @escaping ([EngineMessage.Id], @escaping (ContainedViewLayoutTransition) -> Void) -> Void, cancelMessageSelection: @escaping (ContainedViewLayoutTransition) -> Void, deleteSelectedMessages: @escaping () -> Void, reportSelectedMessages: @escaping () -> Void, - reportMessages: @escaping ([Message], ContextControllerProtocol?) -> Void, - blockMessageAuthor: @escaping (Message, ContextControllerProtocol?) -> Void, - deleteMessages: @escaping ([Message], ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void, + reportMessages: @escaping ([EngineRawMessage], ContextControllerProtocol?) -> Void, + blockMessageAuthor: @escaping (EngineRawMessage, ContextControllerProtocol?) -> Void, + deleteMessages: @escaping ([EngineRawMessage], ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void, forwardSelectedMessages: @escaping () -> Void, forwardCurrentForwardMessages: @escaping () -> Void, - forwardMessages: @escaping ([Message]) -> Void, + forwardMessages: @escaping ([EngineRawMessage]) -> Void, updateForwardOptionsState: @escaping ((ChatInterfaceForwardOptionsState) -> ChatInterfaceForwardOptionsState) -> Void, presentForwardOptions: @escaping (UIView) -> Void, presentReplyOptions: @escaping (UIView) -> Void, @@ -223,7 +222,7 @@ public final class ChatPanelInterfaceInteraction { presentSuggestPostOptions: @escaping () -> Void, shareSelectedMessages: @escaping () -> Void, updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void, - updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void, + updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, EngineMessage.Id?)) -> Void, openStickers: @escaping () -> Void, editMessage: @escaping () -> Void, beginMessageSearch: @escaping (ChatSearchDomain, String) -> Void, @@ -233,17 +232,17 @@ public final class ChatPanelInterfaceInteraction { navigateMessageSearch: @escaping (ChatPanelSearchNavigationAction) -> Void, openCalendarSearch: @escaping () -> Void, toggleMembersSearch: @escaping (Bool) -> Void, - navigateToMessage: @escaping (MessageId, Bool, Bool, ChatLoadingMessageSubject) -> Void, - navigateToChat: @escaping (PeerId) -> Void, - navigateToProfile: @escaping (PeerId) -> Void, + navigateToMessage: @escaping (EngineMessage.Id, Bool, Bool, ChatLoadingMessageSubject) -> Void, + navigateToChat: @escaping (EnginePeer.Id) -> Void, + navigateToProfile: @escaping (EnginePeer.Id) -> Void, openPeerInfo: @escaping () -> Void, togglePeerNotifications: @escaping () -> Void, sendContextResult: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool, - sendBotCommand: @escaping (Peer, String) -> Void, + sendBotCommand: @escaping (EngineRawPeer, String) -> Void, sendShortcut: @escaping (Int32) -> Void, openEditShortcuts: @escaping () -> Void, sendBotStart: @escaping (String?) -> Void, - botSwitchChatWithPayload: @escaping (PeerId, String) -> Void, + botSwitchChatWithPayload: @escaping (EnginePeer.Id, String) -> Void, beginMediaRecording: @escaping (Bool) -> Void, finishMediaRecording: @escaping (ChatFinishMediaRecordingAction) -> Void, stopMediaRecording: @escaping () -> Void, @@ -255,20 +254,20 @@ public final class ChatPanelInterfaceInteraction { displayVideoUnmuteTip: @escaping (CGPoint?) -> Void, switchMediaRecordingMode: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void, - sendSticker: @escaping (FileMediaReference, Bool, UIView?, CGRect?, CALayer?, [ItemCollectionId]) -> Bool, + sendSticker: @escaping (FileMediaReference, Bool, UIView?, CGRect?, CALayer?, [EngineItemCollectionId]) -> Bool, editSticker: @escaping (TelegramMediaFile) -> Void, unblockPeer: @escaping () -> Void, - pinMessage: @escaping (MessageId, ContextControllerProtocol?) -> Void, - unpinMessage: @escaping (MessageId, Bool, ContextControllerProtocol?) -> Void, + pinMessage: @escaping (EngineMessage.Id, ContextControllerProtocol?) -> Void, + unpinMessage: @escaping (EngineMessage.Id, Bool, ContextControllerProtocol?) -> Void, unpinAllMessages: @escaping () -> Void, - openPinnedList: @escaping (MessageId) -> Void, + openPinnedList: @escaping (EngineMessage.Id) -> Void, shareAccountContact: @escaping () -> Void, reportPeer: @escaping () -> Void, presentPeerContact: @escaping () -> Void, dismissReportPeer: @escaping () -> Void, deleteChat: @escaping () -> Void, beginCall: @escaping (Bool) -> Void, - toggleMessageStickerStarred: @escaping (MessageId) -> Void, + toggleMessageStickerStarred: @escaping (EngineMessage.Id) -> Void, presentController: @escaping (ViewController, Any?) -> Void, presentControllerInCurrent: @escaping (ViewController, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?, @@ -276,8 +275,8 @@ public final class ChatPanelInterfaceInteraction { navigateFeed: @escaping () -> Void, openGrouping: @escaping () -> Void, toggleSilentPost: @escaping () -> Void, - requestUnvoteInMessage: @escaping (MessageId) -> Void, - requestStopPollInMessage: @escaping (MessageId) -> Void, + requestUnvoteInMessage: @escaping (EngineMessage.Id) -> Void, + requestStopPollInMessage: @escaping (EngineMessage.Id) -> Void, updateInputLanguage: @escaping ((String?) -> String?) -> Void, unarchiveChat: @escaping () -> Void, openLinkEditing: @escaping () -> Void, @@ -289,13 +288,13 @@ public final class ChatPanelInterfaceInteraction { displaySearchResultsTooltip: @escaping (ASDisplayNode, CGRect) -> Void, unarchivePeer: @escaping () -> Void, scrollToTop: @escaping () -> Void, - viewReplies: @escaping (MessageId?, ChatReplyThreadMessage) -> Void, + viewReplies: @escaping (EngineMessage.Id?, ChatReplyThreadMessage) -> Void, activatePinnedListPreview: @escaping (ASDisplayNode, ContextGesture) -> Void, joinGroupCall: @escaping (CachedChannelData.ActiveCall) -> Void, presentInviteMembers: @escaping () -> Void, presentGigagroupHelp: @escaping () -> Void, openMonoforum: @escaping () -> Void, - editMessageMedia: @escaping (MessageId, Bool) -> Void, + editMessageMedia: @escaping (EngineMessage.Id, Bool) -> Void, updateShowCommands: @escaping ((Bool) -> Bool) -> Void, updateShowSendAsPeers: @escaping ((Bool) -> Bool) -> Void, openInviteRequests: @escaping () -> Void, @@ -312,14 +311,14 @@ public final class ChatPanelInterfaceInteraction { addDoNotTranslateLanguage: @escaping (String) -> Void, hideTranslationPanel: @escaping () -> Void, openPremiumGift: @escaping () -> Void, - openSuggestPost: @escaping (Message?, OpenSuggestPostMode) -> Void, + openSuggestPost: @escaping (EngineRawMessage?, OpenSuggestPostMode) -> Void, openPremiumRequiredForMessaging: @escaping () -> Void, openStarsPurchase: @escaping (Int64?) -> Void, openMessagePayment: @escaping () -> Void, openBoostToUnrestrict: @escaping () -> Void, updateRecordingTrimRange: @escaping (Double, Double, Bool, Bool) -> Void, dismissAllTooltips: @escaping () -> Void, - editTodoMessage: @escaping (MessageId, Int32?, Bool) -> Void, + editTodoMessage: @escaping (EngineMessage.Id, Int32?, Bool) -> Void, dismissUrlPreview: @escaping () -> Void, dismissForwardMessages: @escaping () -> Void, dismissSuggestPost: @escaping () -> Void, @@ -472,7 +471,7 @@ public final class ChatPanelInterfaceInteraction { public convenience init( updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void, - updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void, + updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, EngineMessage.Id?)) -> Void, openLinkEditing: @escaping () -> Void ) { self.init(setupReplyMessage: { _, _, _ in diff --git a/submodules/GalleryData/BUILD b/submodules/GalleryData/BUILD index ec0ae7d4d8..83e10f7cc2 100644 --- a/submodules/GalleryData/BUILD +++ b/submodules/GalleryData/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/AccountContext:AccountContext", diff --git a/submodules/GalleryData/Sources/GalleryData.swift b/submodules/GalleryData/Sources/GalleryData.swift index 3e8e70523f..b9c578e07c 100644 --- a/submodules/GalleryData/Sources/GalleryData.swift +++ b/submodules/GalleryData/Sources/GalleryData.swift @@ -1,7 +1,6 @@ import Foundation import Display import AsyncDisplayKit -import Postbox import TelegramCore import SwiftSignalKit import PassKit @@ -19,20 +18,20 @@ import StoryContainerScreen public enum ChatMessageGalleryControllerData { case url(String) case pass(TelegramMediaFile) - case instantPage(InstantPageGalleryController, Int, Media) + case instantPage(InstantPageGalleryController, Int, EngineRawMedia) case map(TelegramMediaMap) case stickerPack(StickerPackReference, TelegramMediaFile?) case audio(TelegramMediaFile) case document(TelegramMediaFile, Bool) case gallery(Signal) case secretGallery(SecretMediaPreviewController) - case chatAvatars(AvatarGalleryController, Media) + case chatAvatars(AvatarGalleryController, EngineRawMedia) case theme(TelegramMediaFile) - case other(Media) + case other(EngineRawMedia) case story(Signal) } -private func instantPageBlockMedia(pageId: MediaId, block: InstantPageBlock, media: [MediaId: Media], counter: inout Int) -> [InstantPageGalleryEntry] { +private func instantPageBlockMedia(pageId: EngineMedia.Id, block: InstantPageBlock, media: [EngineMedia.Id: EngineRawMedia], counter: inout Int) -> [InstantPageGalleryEntry] { switch block { case let .image(id, caption, _, _): if let m = media[id] { @@ -64,7 +63,7 @@ private func instantPageBlockMedia(pageId: MediaId, block: InstantPageBlock, med return [] } -public func instantPageGalleryMedia(webpageId: MediaId, page: InstantPage.Accessor, galleryMedia: Media) -> [InstantPageGalleryEntry] { +public func instantPageGalleryMedia(webpageId: EngineMedia.Id, page: InstantPage.Accessor, galleryMedia: EngineRawMedia) -> [InstantPageGalleryEntry] { var result: [InstantPageGalleryEntry] = [] var counter: Int = 0 @@ -96,9 +95,9 @@ public func instantPageGalleryMedia(webpageId: MediaId, page: InstantPage.Access public func chatMessageGalleryControllerData( context: AccountContext, chatLocation: ChatLocation?, - chatFilterTag: MemoryBuffer?, + chatFilterTag: EngineMemoryBuffer?, chatLocationContextHolder: Atomic?, - message: Message, + message: EngineRawMessage, mediaSubject: GalleryMediaSubject? = nil, navigationController: NavigationController?, standalone: Bool, @@ -113,10 +112,10 @@ public func chatMessageGalleryControllerData( standalone = true } - var galleryMedia: Media? - var otherMedia: Media? + var galleryMedia: EngineRawMedia? + var otherMedia: EngineRawMedia? var instantPageMedia: (TelegramMediaWebpage, [InstantPageGalleryEntry])? - if message.media.isEmpty, let entities = message.textEntitiesAttribute?.entities, entities.count == 1, let firstEntity = entities.first, case let .CustomEmoji(_, fileId) = firstEntity.type, let file = message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile { + if message.media.isEmpty, let entities = message.textEntitiesAttribute?.entities, entities.count == 1, let firstEntity = entities.first, case let .CustomEmoji(_, fileId) = firstEntity.type, let file = message.associatedMedia[EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile { for attribute in file.attributes { if case let .CustomEmoji(_, _, _, reference) = attribute { if let reference = reference { @@ -356,25 +355,11 @@ public func chatMessageGalleryControllerData( } public enum ChatMessagePreviewControllerData { - case instantPage(InstantPageGalleryController, Int, Media) + case instantPage(InstantPageGalleryController, Int, EngineRawMedia) case gallery(GalleryController) } -public func chatMessagePreviewControllerData(context: AccountContext, chatLocation: ChatLocation?, chatFilterTag: MemoryBuffer?, chatLocationContextHolder: Atomic?, message: Message, standalone: Bool, reverseMessageGalleryOrder: Bool, navigationController: NavigationController?) -> ChatMessagePreviewControllerData? { - if let mediaData = chatMessageGalleryControllerData(context: context, chatLocation: chatLocation, chatFilterTag: chatFilterTag, chatLocationContextHolder: chatLocationContextHolder, message: message, navigationController: navigationController, standalone: standalone, reverseMessageGalleryOrder: reverseMessageGalleryOrder, mode: .default, source: nil, synchronousLoad: true, actionInteraction: nil) { - switch mediaData { - case .gallery: - break - case let .instantPage(gallery, centralIndex, galleryMedia): - return .instantPage(gallery, centralIndex, galleryMedia) - default: - break - } - } - return nil -} - -public func chatMediaListPreviewControllerData(context: AccountContext, chatLocation: ChatLocation?, chatFilterTag: MemoryBuffer?, chatLocationContextHolder: Atomic?, message: Message, standalone: Bool, reverseMessageGalleryOrder: Bool, navigationController: NavigationController?) -> Signal { +public func chatMediaListPreviewControllerData(context: AccountContext, chatLocation: ChatLocation?, chatFilterTag: EngineMemoryBuffer?, chatLocationContextHolder: Atomic?, message: EngineRawMessage, standalone: Bool, reverseMessageGalleryOrder: Bool, navigationController: NavigationController?) -> Signal { if let mediaData = chatMessageGalleryControllerData(context: context, chatLocation: chatLocation, chatFilterTag: chatFilterTag, chatLocationContextHolder: chatLocationContextHolder, message: message, navigationController: navigationController, standalone: standalone, reverseMessageGalleryOrder: reverseMessageGalleryOrder, mode: .default, source: nil, synchronousLoad: true, actionInteraction: nil) { switch mediaData { case let .gallery(gallery): diff --git a/submodules/GalleryUI/Sources/Items/ChatDocumentGalleryItem.swift b/submodules/GalleryUI/Sources/Items/ChatDocumentGalleryItem.swift index 7d1b52c291..c3f795abc0 100644 --- a/submodules/GalleryUI/Sources/Items/ChatDocumentGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/ChatDocumentGalleryItem.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import AsyncDisplayKit -import Postbox import Display import SwiftSignalKit import WebKit @@ -17,10 +16,10 @@ class ChatDocumentGalleryItem: GalleryItem { let context: AccountContext let presentationData: PresentationData - let message: Message - let location: MessageHistoryEntryLocation? + let message: EngineRawMessage + let location: EngineMessageHistoryEntryLocation? - init(context: AccountContext, presentationData: PresentationData, message: Message, location: MessageHistoryEntryLocation?) { + init(context: AccountContext, presentationData: PresentationData, message: EngineRawMessage, location: EngineMessageHistoryEntryLocation?) { self.context = context self.presentationData = presentationData self.message = message @@ -104,7 +103,7 @@ class ChatDocumentGalleryItemNode: ZoomableContentGalleryItemNode, WKNavigationD private var itemIsVisible = false - private var message: Message? + private var message: EngineRawMessage? private let footerContentNode: ChatItemGalleryFooterContentNode @@ -163,7 +162,7 @@ class ChatDocumentGalleryItemNode: ZoomableContentGalleryItemNode, WKNavigationD transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(), size: statusSize)) } - fileprivate func setMessage(_ message: Message) { + fileprivate func setMessage(_ message: EngineRawMessage) { self.footerContentNode.setMessage(message) } @@ -187,7 +186,7 @@ class ChatDocumentGalleryItemNode: ZoomableContentGalleryItemNode, WKNavigationD } } - private func setupStatus(context: AccountContext, resource: MediaResource) { + private func setupStatus(context: AccountContext, resource: EngineRawMediaResource) { self.statusDisposable.set((context.engine.resources.status(resource: EngineMediaResource(resource)) |> deliverOnMainQueue).start(next: { [weak self] status in if let strongSelf = self { diff --git a/submodules/GalleryUI/Sources/Items/ChatExternalFileGalleryItem.swift b/submodules/GalleryUI/Sources/Items/ChatExternalFileGalleryItem.swift index 67f671959d..88027cbb47 100644 --- a/submodules/GalleryUI/Sources/Items/ChatExternalFileGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/ChatExternalFileGalleryItem.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import AsyncDisplayKit -import Postbox import Display import SwiftSignalKit import WebKit @@ -17,10 +16,10 @@ class ChatExternalFileGalleryItem: GalleryItem { let context: AccountContext let presentationData: PresentationData - let message: Message - let location: MessageHistoryEntryLocation? - - init(context: AccountContext, presentationData: PresentationData, message: Message, location: MessageHistoryEntryLocation?) { + let message: EngineRawMessage + let location: EngineMessageHistoryEntryLocation? + + init(context: AccountContext, presentationData: PresentationData, message: EngineRawMessage, location: EngineMessageHistoryEntryLocation?) { self.context = context self.presentationData = presentationData self.message = message @@ -78,7 +77,7 @@ class ChatExternalFileGalleryItemNode: GalleryItemNode { private var itemIsVisible = false - private var message: Message? + private var message: EngineRawMessage? private let footerContentNode: ChatItemGalleryFooterContentNode @@ -164,7 +163,7 @@ class ChatExternalFileGalleryItemNode: GalleryItemNode { transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(), size: statusSize)) } - fileprivate func setMessage(_ message: Message) { + fileprivate func setMessage(_ message: EngineRawMessage) { self.message = message self.footerContentNode.setMessage(message) } @@ -182,7 +181,7 @@ class ChatExternalFileGalleryItemNode: GalleryItemNode { } } - private func setupStatus(context: AccountContext, resource: MediaResource) { + private func setupStatus(context: AccountContext, resource: EngineRawMediaResource) { self.statusDisposable.set((context.engine.resources.status(resource: EngineMediaResource(resource)) |> deliverOnMainQueue).start(next: { [weak self] status in if let strongSelf = self { diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index ba222b9a7a..015887386d 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -2949,7 +2949,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } if swipeUpToClose { - addAppLogEvent(postbox: self.context.account.postbox, type: "swipe_up_close", peerId: self.context.account.peerId) + self.context.engine.accountData.addAppLogEvent(type: "swipe_up_close") return false } @@ -2957,7 +2957,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if #available(iOS 15.0, *) { if let nativePictureInPictureContent = self.nativePictureInPictureContent as? NativePictureInPictureContentImpl { - addAppLogEvent(postbox: self.context.account.postbox, type: "swipe_up_pip", peerId: self.context.account.peerId) + self.context.engine.accountData.addAppLogEvent(type: "swipe_up_pip") nativePictureInPictureContent.beginPictureInPicture() return true } @@ -2966,7 +2966,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } override func maybePerformActionForSwipeDownDismiss() -> Bool { - addAppLogEvent(postbox: self.context.account.postbox, type: "swipe_down_close", peerId: self.context.account.peerId) + self.context.engine.accountData.addAppLogEvent(type: "swipe_down_close") return false } @@ -3184,7 +3184,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { self.activePictureInPictureController = nil self.activePictureInPictureNavigationController = nil - addAppLogEvent(postbox: self.context.account.postbox, type: "pip_close_btn", peerId: self.context.account.peerId) + self.context.engine.accountData.addAppLogEvent(type: "pip_close_btn") } }, expand: { [weak self] completion in didExpand = true @@ -3234,7 +3234,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if #available(iOS 15.0, *) { if let nativePictureInPictureContent = self.nativePictureInPictureContent as? NativePictureInPictureContentImpl { - addAppLogEvent(postbox: self.context.account.postbox, type: "pip_btn", peerId: self.context.account.peerId) + self.context.engine.accountData.addAppLogEvent(type: "pip_btn") nativePictureInPictureContent.beginPictureInPicture() return } diff --git a/submodules/GalleryUI/Sources/Items/VideoAdComponent.swift b/submodules/GalleryUI/Sources/Items/VideoAdComponent.swift index 5bdb216175..31b54db45f 100644 --- a/submodules/GalleryUI/Sources/Items/VideoAdComponent.swift +++ b/submodules/GalleryUI/Sources/Items/VideoAdComponent.swift @@ -5,7 +5,6 @@ import SwiftSignalKit import ComponentFlow import MultilineTextComponent import MultilineTextWithEntitiesComponent -import Postbox import TelegramCore import TelegramPresentationData import ContextUI @@ -111,7 +110,7 @@ final class VideoAdComponent: Component { let titleString = component.message.author?.compactDisplayTitle ?? "" - var media: Media? + var media: EngineRawMedia? if let photo = component.message.media.first as? TelegramMediaImage { media = photo } else if let file = component.message.media.first as? TelegramMediaFile { diff --git a/submodules/ICloudResources/BUILD b/submodules/ICloudResources/BUILD index b282708cee..9b4faf0021 100644 --- a/submodules/ICloudResources/BUILD +++ b/submodules/ICloudResources/BUILD @@ -11,7 +11,6 @@ swift_library( ], deps = [ "//submodules/TelegramCore", - "//submodules/Postbox", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/Display", "//submodules/Pdf", diff --git a/submodules/ICloudResources/Sources/ICloudResources.swift b/submodules/ICloudResources/Sources/ICloudResources.swift index 9658b88460..b13f4dbbd0 100644 --- a/submodules/ICloudResources/Sources/ICloudResources.swift +++ b/submodules/ICloudResources/Sources/ICloudResources.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import TelegramCore import SwiftSignalKit import Display @@ -13,9 +12,9 @@ public struct ICloudFileResourceId { public var uniqueId: String { if self.thumbnail { - return "icloud-thumb-\(persistentHash32(self.urlData))" + return "icloud-thumb-\(enginePersistentHash32(self.urlData))" } else { - return "icloud-\(persistentHash32(self.urlData))" + return "icloud-\(enginePersistentHash32(self.urlData))" } } @@ -37,21 +36,21 @@ public class ICloudFileResource: TelegramMediaResource { self.thumbnail = thumbnail } - public required init(decoder: PostboxDecoder) { + public required init(decoder: EnginePostboxDecoder) { self.urlData = decoder.decodeStringForKey("url", orElse: "") self.thumbnail = decoder.decodeBoolForKey("thumb", orElse: false) } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeString(self.urlData, forKey: "url") encoder.encodeBool(self.thumbnail, forKey: "thumb") } - public var id: MediaResourceId { - return MediaResourceId(ICloudFileResourceId(urlData: self.urlData, thumbnail: self.thumbnail).uniqueId) + public var id: EngineRawMediaResourceId { + return EngineRawMediaResourceId(ICloudFileResourceId(urlData: self.urlData, thumbnail: self.thumbnail).uniqueId) } - - public func isEqual(to: MediaResource) -> Bool { + + public func isEqual(to: EngineRawMediaResource) -> Bool { if let to = to as? ICloudFileResource { if self.urlData != to.urlData || self.thumbnail != to.thumbnail { return false @@ -252,7 +251,7 @@ public func iCloudFileDescription(_ url: URL) -> Signal Signal { +public func fetchICloudFileResource(resource: ICloudFileResource) -> Signal { return Signal { subscriber in subscriber.putNext(.reset) @@ -306,7 +305,7 @@ public func fetchICloudFileResource(resource: ICloudFileResource) -> Signal Bool { + + public func isEqual(to: EngineRawMediaResource) -> Bool { if let to = to as? InstantPageExternalMediaResource { return self.url == to.url } else { diff --git a/submodules/LegacyDataImport/BUILD b/submodules/LegacyDataImport/BUILD deleted file mode 100644 index 199ce4f386..0000000000 --- a/submodules/LegacyDataImport/BUILD +++ /dev/null @@ -1,23 +0,0 @@ -load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") - -swift_library( - name = "LegacyDataImport", - module_name = "LegacyDataImport", - srcs = glob([ - "Sources/**/*.swift", - ]), - deps = [ - "//submodules/TelegramCore:TelegramCore", - "//submodules/SyncCore:SyncCore", - "//submodules/Postbox:Postbox", - "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", - "//submodules/TelegramNotices:TelegramNotices", - "//submodules/TelegramUIPreferences:TelegramUIPreferences", - "//submodules/RadialStatusNode:RadialStatusNode", - "//submodules/LegacyComponents:LegacyComponents", - "//submodules/LegacyDataImport/Impl:LegacyDataImportImpl", - ], - visibility = [ - "//visibility:public", - ], -) diff --git a/submodules/LegacyDataImport/Impl/BUILD b/submodules/LegacyDataImport/Impl/BUILD deleted file mode 100644 index 4bab57e0ce..0000000000 --- a/submodules/LegacyDataImport/Impl/BUILD +++ /dev/null @@ -1,22 +0,0 @@ - -objc_library( - name = "LegacyDataImportImpl", - enable_modules = True, - module_name = "LegacyDataImportImpl", - srcs = glob([ - "Sources/**/*.m", - "Sources/**/*.h", - ]), - hdrs = glob([ - "PublicHeaders/**/*.h", - ]), - includes = [ - "PublicHeaders", - ], - sdk_frameworks = [ - "Foundation", - ], - visibility = [ - "//visibility:public", - ], -) diff --git a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/LegacyDataImportImpl.h b/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/LegacyDataImportImpl.h deleted file mode 100644 index 7a94876eb4..0000000000 --- a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/LegacyDataImportImpl.h +++ /dev/null @@ -1,7 +0,0 @@ -#import - -#import -#import -#import - - diff --git a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGAutoDownloadPreferences.h b/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGAutoDownloadPreferences.h deleted file mode 100644 index 975ffbd435..0000000000 --- a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGAutoDownloadPreferences.h +++ /dev/null @@ -1,76 +0,0 @@ -#import - -typedef enum { - TGNetworkTypeUnknown, - TGNetworkTypeNone, - TGNetworkTypeGPRS, - TGNetworkTypeEdge, - TGNetworkType3G, - TGNetworkTypeLTE, - TGNetworkTypeWiFi, -} TGNetworkType; - -typedef enum { - TGAutoDownloadModeNone = 0, - - TGAutoDownloadModeCellularContacts = 1 << 0, - TGAutoDownloadModeWifiContacts = 1 << 1, - - TGAutoDownloadModeCellularPrivateChats = 1 << 2, - TGAutoDownloadModeWifiPrivateChats = 1 << 3, - - TGAutoDownloadModeCellularGroups = 1 << 4, - TGAutoDownloadModeWifiGroups = 1 << 5, - - TGAutoDownloadModeCellularChannels = 1 << 6, - TGAutoDownloadModeWifiChannels = 1 << 7, - - TGAutoDownloadModeAutosavePhotosAll = TGAutoDownloadModeCellularContacts | TGAutoDownloadModeCellularPrivateChats | TGAutoDownloadModeCellularGroups | TGAutoDownloadModeCellularChannels, - - TGAutoDownloadModeAllPrivateChats = TGAutoDownloadModeCellularContacts | TGAutoDownloadModeWifiContacts | TGAutoDownloadModeCellularPrivateChats | TGAutoDownloadModeWifiPrivateChats, - TGAutoDownloadModeAllGroups = TGAutoDownloadModeCellularGroups | TGAutoDownloadModeWifiGroups | TGAutoDownloadModeCellularChannels | TGAutoDownloadModeWifiChannels, - TGAutoDownloadModeAll = TGAutoDownloadModeCellularContacts | TGAutoDownloadModeWifiContacts | TGAutoDownloadModeCellularPrivateChats | TGAutoDownloadModeWifiPrivateChats | TGAutoDownloadModeCellularGroups | TGAutoDownloadModeWifiGroups | TGAutoDownloadModeCellularChannels | TGAutoDownloadModeWifiChannels -} TGAutoDownloadMode; - -typedef enum { - TGAutoDownloadChatContact, - TGAutoDownloadChatOtherPrivateChat, - TGAutoDownloadChatGroup, - TGAutoDownloadChatChannel -} TGAutoDownloadChat; - -@interface TGAutoDownloadPreferences : NSObject - -@property (nonatomic, readonly) bool disabled; - -@property (nonatomic, readonly) TGAutoDownloadMode photos; -@property (nonatomic, readonly) TGAutoDownloadMode videos; -@property (nonatomic, readonly) int32_t maximumVideoSize; -@property (nonatomic, readonly) TGAutoDownloadMode documents; -@property (nonatomic, readonly) int32_t maximumDocumentSize; -@property (nonatomic, readonly) TGAutoDownloadMode gifs; -@property (nonatomic, readonly) TGAutoDownloadMode voiceMessages; -@property (nonatomic, readonly) TGAutoDownloadMode videoMessages; - -- (instancetype)updateDisabled:(bool)disabled; -- (instancetype)updatePhotosMode:(TGAutoDownloadMode)mode; -- (instancetype)updateVideosMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize; -- (instancetype)updateDocumentsMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize; -- (instancetype)updateGifsMode:(TGAutoDownloadMode)mode; -- (instancetype)updateVoiceMessagesMode:(TGAutoDownloadMode)mode; -- (instancetype)updateVideoMessagesMode:(TGAutoDownloadMode)mode; - -+ (bool)shouldDownload:(TGAutoDownloadMode)mode inChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType; -- (bool)shouldDownloadPhotoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType; -- (bool)shouldDownloadVideoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType; -- (bool)shouldDownloadDocumentInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType; -- (bool)shouldDownloadGifInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType; -- (bool)shouldDownloadVoiceMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType; -- (bool)shouldDownloadVideoMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType; - -- (bool)isDefaultPreferences; - -+ (instancetype)defaultPreferences; -+ (instancetype)preferencesWithLegacyDownloadPrivatePhotos:(bool)privatePhotos groupPhotos:(bool)groupPhotos privateVoiceMessages:(bool)privateVoiceMessages groupVoiceMessages:(bool)groupVoiceMessages privateVideoMessages:(bool)privateVideoMessages groupVideoMessages:(bool)groupVideoMessages; - -@end diff --git a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGAutoDownloadPreferences.m b/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGAutoDownloadPreferences.m deleted file mode 100644 index 64c8cca6c7..0000000000 --- a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGAutoDownloadPreferences.m +++ /dev/null @@ -1,250 +0,0 @@ -#import - -@implementation TGAutoDownloadPreferences - -- (instancetype)initWithCoder:(NSCoder *)aDecoder -{ - self = [super init]; - if (self != nil) - { - _disabled = [aDecoder decodeBoolForKey:@"disabled"]; - _photos = [aDecoder decodeInt32ForKey:@"photos"]; - _videos = [aDecoder decodeInt32ForKey:@"videos"]; - _maximumVideoSize = [aDecoder decodeInt32ForKey:@"maxVideoSize"]; - _documents = [aDecoder decodeInt32ForKey:@"documents"]; - _maximumDocumentSize = [aDecoder decodeInt32ForKey:@"maxDocumentSize"]; - _voiceMessages = [aDecoder decodeInt32ForKey:@"voiceMessages"]; - _videoMessages = [aDecoder decodeInt32ForKey:@"videoMessages"]; - } - return self; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder -{ - [aCoder encodeBool:_disabled forKey:@"disabled"]; - [aCoder encodeInt32:_photos forKey:@"photos"]; - [aCoder encodeInt32:_videos forKey:@"videos"]; - [aCoder encodeInt32:_maximumVideoSize forKey:@"maxVideoSize"]; - [aCoder encodeInt32:_documents forKey:@"documents"]; - [aCoder encodeInt32:_maximumDocumentSize forKey:@"maxDocumentSize"]; - [aCoder encodeInt32:_voiceMessages forKey:@"voiceMessages"]; - [aCoder encodeInt32:_videoMessages forKey:@"videoMessages"]; -} - -+ (instancetype)defaultPreferences -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = TGAutoDownloadModeAll; - preferences->_videos = TGAutoDownloadModeNone; - preferences->_maximumVideoSize = 10; - preferences->_documents = TGAutoDownloadModeNone; - preferences->_maximumDocumentSize = 10; - preferences->_voiceMessages = TGAutoDownloadModeAll; - preferences->_videoMessages = TGAutoDownloadModeAll; - return preferences; -} - -+ (instancetype)preferencesWithLegacyDownloadPrivatePhotos:(bool)privatePhotos groupPhotos:(bool)groupPhotos privateVoiceMessages:(bool)privateVoiceMessages groupVoiceMessages:(bool)groupVoiceMessages privateVideoMessages:(bool)privateVideoMessages groupVideoMessages:(bool)groupVideoMessages -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - - if (privatePhotos) - preferences->_photos |= TGAutoDownloadModeAllPrivateChats; - if (groupPhotos) - preferences->_photos |= TGAutoDownloadModeAllGroups; - - if (privateVoiceMessages) - preferences->_voiceMessages |= TGAutoDownloadModeAllPrivateChats; - if (groupVoiceMessages) - preferences->_voiceMessages |= TGAutoDownloadModeAllGroups; - - if (privateVideoMessages) - preferences->_videoMessages |= TGAutoDownloadModeAllPrivateChats; - if (groupVideoMessages) - preferences->_videoMessages |= TGAutoDownloadModeAllGroups; - - preferences->_maximumVideoSize = 10; - preferences->_maximumDocumentSize = 10; - - return preferences; -} - -- (instancetype)updateDisabled:(bool)disabled -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_disabled = disabled; - preferences->_photos = _photos; - preferences->_videos = _videos; - preferences->_maximumVideoSize = _maximumVideoSize; - preferences->_documents = _documents; - preferences->_maximumDocumentSize = _maximumDocumentSize; - preferences->_voiceMessages = _voiceMessages; - preferences->_videoMessages = _videoMessages; - return preferences; -} - -- (instancetype)updatePhotosMode:(TGAutoDownloadMode)mode -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = mode; - preferences->_videos = _videos; - preferences->_maximumVideoSize = _maximumVideoSize; - preferences->_documents = _documents; - preferences->_maximumDocumentSize = _maximumDocumentSize; - preferences->_voiceMessages = _voiceMessages; - preferences->_videoMessages = _videoMessages; - return preferences; -} - -- (instancetype)updateVideosMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = _photos; - preferences->_videos = mode; - preferences->_maximumVideoSize = maximumSize; - preferences->_documents = _documents; - preferences->_maximumDocumentSize = _maximumDocumentSize; - preferences->_voiceMessages = _voiceMessages; - preferences->_videoMessages = _videoMessages; - return preferences; -} - -- (instancetype)updateDocumentsMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = _photos; - preferences->_videos = _videos; - preferences->_maximumVideoSize = _maximumVideoSize; - preferences->_documents = mode; - preferences->_maximumDocumentSize = maximumSize; - preferences->_voiceMessages = _voiceMessages; - preferences->_videoMessages = _videoMessages; - return preferences; -} - -- (instancetype)updateVoiceMessagesMode:(TGAutoDownloadMode)mode -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = _photos; - preferences->_videos = _videos; - preferences->_maximumVideoSize = _maximumVideoSize; - preferences->_documents = _documents; - preferences->_maximumDocumentSize = _maximumDocumentSize; - preferences->_voiceMessages = mode; - preferences->_videoMessages = _videoMessages; - return preferences; -} - -- (instancetype)updateVideoMessagesMode:(TGAutoDownloadMode)mode -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = _photos; - preferences->_videos = _videos; - preferences->_maximumVideoSize = _maximumVideoSize; - preferences->_documents = _documents; - preferences->_maximumDocumentSize = _maximumDocumentSize; - preferences->_voiceMessages = _voiceMessages; - preferences->_videoMessages = mode; - return preferences; -} - -+ (bool)shouldDownload:(TGAutoDownloadMode)mode inChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - bool isWiFi = networkType == TGNetworkTypeWiFi; - bool isCellular = !isWiFi && networkType != TGNetworkTypeNone; - - bool shouldDownload = false; - switch (chat) - { - case TGAutoDownloadChatContact: - if (isCellular) - shouldDownload = (mode & TGAutoDownloadModeCellularContacts) != 0; - else if (isWiFi) - shouldDownload = (mode & TGAutoDownloadModeWifiContacts) != 0; - break; - - case TGAutoDownloadChatOtherPrivateChat: - if (isCellular) - shouldDownload = (mode & TGAutoDownloadModeCellularPrivateChats) != 0; - else if (isWiFi) - shouldDownload = (mode & TGAutoDownloadModeWifiPrivateChats) != 0; - break; - - case TGAutoDownloadChatGroup: - if (isCellular) - shouldDownload = (mode & TGAutoDownloadModeCellularGroups) != 0; - else if (isWiFi) - shouldDownload = (mode & TGAutoDownloadModeWifiGroups) != 0; - break; - - case TGAutoDownloadChatChannel: - if (isCellular) - shouldDownload = (mode & TGAutoDownloadModeCellularChannels) != 0; - else if (isWiFi) - shouldDownload = (mode & TGAutoDownloadModeWifiChannels) != 0; - break; - - default: - break; - } - return shouldDownload; -} - -- (bool)shouldDownloadPhotoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - if (self.disabled) - return false; - - return [TGAutoDownloadPreferences shouldDownload:_photos inChat:chat networkType:networkType]; -} - -- (bool)shouldDownloadVideoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - if (self.disabled) - return false; - - return [TGAutoDownloadPreferences shouldDownload:_videos inChat:chat networkType:networkType]; -} - -- (bool)shouldDownloadDocumentInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - if (self.disabled) - return false; - - return [TGAutoDownloadPreferences shouldDownload:_documents inChat:chat networkType:networkType]; -} - -- (bool)shouldDownloadVoiceMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - if (self.disabled) - return false; - - return [TGAutoDownloadPreferences shouldDownload:_voiceMessages inChat:chat networkType:networkType]; -} - -- (bool)shouldDownloadVideoMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - if (self.disabled) - return false; - - return [TGAutoDownloadPreferences shouldDownload:_videoMessages inChat:chat networkType:networkType]; -} - -- (bool)isDefaultPreferences -{ - return [self isEqual:[TGAutoDownloadPreferences defaultPreferences]]; -} - -- (BOOL)isEqual:(id)object -{ - if (object == self) - return YES; - - if (!object || ![object isKindOfClass:[self class]]) - return NO; - - TGAutoDownloadPreferences *preferences = (TGAutoDownloadPreferences *)object; - return preferences.photos == _photos && preferences.videos == _videos && preferences.documents == _documents && preferences.voiceMessages == _voiceMessages && preferences.videoMessages == _videoMessages && preferences.maximumVideoSize == _maximumVideoSize && preferences.maximumDocumentSize == _maximumDocumentSize && preferences.disabled == _disabled; -} - -@end diff --git a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGPresentationAutoNightPreferences.h b/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGPresentationAutoNightPreferences.h deleted file mode 100644 index 1a403c5215..0000000000 --- a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGPresentationAutoNightPreferences.h +++ /dev/null @@ -1,31 +0,0 @@ -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -typedef enum -{ - TGPresentationAutoNightModeDisabled, - TGPresentationAutoNightModeBrightness, - TGPresentationAutoNightModeScheduled, - TGPresentationAutoNightModeSunsetSunrise -} TGPresentationAutoNightMode; - -@interface TGPresentationAutoNightPreferences : NSObject - -@property (nonatomic, readonly) TGPresentationAutoNightMode mode; - -@property (nonatomic, readonly) CGFloat brightnessThreshold; - -@property (nonatomic, readonly) int32_t scheduleStart; -@property (nonatomic, readonly) int32_t scheduleEnd; - -@property (nonatomic, readonly) CGFloat latitude; -@property (nonatomic, readonly) CGFloat longitude; -@property (nonatomic, readonly) NSString *cachedLocationName; - -@property (nonatomic, readonly) int32_t preferredPalette; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGPresentationAutoNightPreferences.m b/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGPresentationAutoNightPreferences.m deleted file mode 100644 index b53b768e38..0000000000 --- a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGPresentationAutoNightPreferences.m +++ /dev/null @@ -1,23 +0,0 @@ -#import - -@implementation TGPresentationAutoNightPreferences - -- (instancetype)initWithCoder:(NSCoder *)aDecoder { - self = [super init]; - if (self != nil) { - _mode = [aDecoder decodeInt32ForKey:@"m"]; - _brightnessThreshold = [aDecoder decodeDoubleForKey:@"b"]; - _scheduleStart = [aDecoder decodeInt32ForKey:@"ss"]; - _scheduleEnd = [aDecoder decodeInt32ForKey:@"se"]; - _latitude = [aDecoder decodeDoubleForKey:@"lat"]; - _longitude = [aDecoder decodeDoubleForKey:@"lon"]; - _cachedLocationName = [aDecoder decodeObjectForKey:@"loc"]; - _preferredPalette = [aDecoder decodeInt32ForKey:@"p"]; - } - return self; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder { -} - -@end diff --git a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGProxyItem.h b/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGProxyItem.h deleted file mode 100644 index 72c1b76fd3..0000000000 --- a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGProxyItem.h +++ /dev/null @@ -1,15 +0,0 @@ -#import - -@interface TGProxyItem : NSObject - -@property (nonatomic, readonly) NSString *server; -@property (nonatomic, readonly) int16_t port; -@property (nonatomic, readonly) NSString *username; -@property (nonatomic, readonly) NSString *password; -@property (nonatomic, readonly) NSString *secret; - -@property (nonatomic, readonly) bool isMTProxy; - -- (instancetype)initWithServer:(NSString *)server port:(int16_t)port username:(NSString *)username password:(NSString *)password secret:(NSString *)secret; - -@end diff --git a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGProxyItem.m b/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGProxyItem.m deleted file mode 100644 index 4dfc1d6c93..0000000000 --- a/submodules/LegacyDataImport/Impl/PublicHeaders/LegacyDataImportImpl/TGProxyItem.m +++ /dev/null @@ -1,73 +0,0 @@ -#import - -static bool TGObjectCompare(id obj1, id obj2) { - if (obj1 == nil && obj2 == nil) - return true; - - return [obj1 isEqual:obj2]; -} - -@implementation TGProxyItem - -- (instancetype)initWithServer:(NSString *)server port:(int16_t)port username:(NSString *)username password:(NSString *)password secret:(NSString *)secret -{ - self = [super init]; - if (self != nil) - { - _server = server; - _port = port; - _username = username; - _password = password; - _secret = secret; - } - return self; -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder -{ - return [self initWithServer:[aDecoder decodeObjectForKey:@"server"] port:(int16_t)[aDecoder decodeInt32ForKey:@"port"] username:[aDecoder decodeObjectForKey:@"user"] password:[aDecoder decodeObjectForKey:@"pass"] secret:[aDecoder decodeObjectForKey:@"secret"]]; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder -{ - [aCoder encodeObject:_server forKey:@"server"]; - [aCoder encodeInt32:_port forKey:@"port"]; - [aCoder encodeObject:_username forKey:@"user"]; - [aCoder encodeObject:_password forKey:@"pass"]; - [aCoder encodeObject:_secret forKey:@"secret"]; -} - -- (bool)isMTProxy -{ - return _secret.length > 0; -} - -- (BOOL)isEqual:(id)object -{ - if (object == self) - return true; - - if (!object || ![object isKindOfClass:[self class]]) - return false; - - TGProxyItem *proxy = (TGProxyItem *)object; - - if (![_server isEqualToString:proxy.server]) - return false; - - if (_port != proxy.port) - return false; - - if (!TGObjectCompare(_username ?: @"", proxy.username ?: @"")) - return false; - - if (!TGObjectCompare(_password ?: @"", proxy.password ?: @"")) - return false; - - if (!TGObjectCompare(_secret ?: @"", proxy.secret ?: @"")) - return false; - - return true; -} - -@end diff --git a/submodules/LegacyDataImport/Impl/Sources/TGAutoDownloadPreferences.m b/submodules/LegacyDataImport/Impl/Sources/TGAutoDownloadPreferences.m deleted file mode 100644 index 64c8cca6c7..0000000000 --- a/submodules/LegacyDataImport/Impl/Sources/TGAutoDownloadPreferences.m +++ /dev/null @@ -1,250 +0,0 @@ -#import - -@implementation TGAutoDownloadPreferences - -- (instancetype)initWithCoder:(NSCoder *)aDecoder -{ - self = [super init]; - if (self != nil) - { - _disabled = [aDecoder decodeBoolForKey:@"disabled"]; - _photos = [aDecoder decodeInt32ForKey:@"photos"]; - _videos = [aDecoder decodeInt32ForKey:@"videos"]; - _maximumVideoSize = [aDecoder decodeInt32ForKey:@"maxVideoSize"]; - _documents = [aDecoder decodeInt32ForKey:@"documents"]; - _maximumDocumentSize = [aDecoder decodeInt32ForKey:@"maxDocumentSize"]; - _voiceMessages = [aDecoder decodeInt32ForKey:@"voiceMessages"]; - _videoMessages = [aDecoder decodeInt32ForKey:@"videoMessages"]; - } - return self; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder -{ - [aCoder encodeBool:_disabled forKey:@"disabled"]; - [aCoder encodeInt32:_photos forKey:@"photos"]; - [aCoder encodeInt32:_videos forKey:@"videos"]; - [aCoder encodeInt32:_maximumVideoSize forKey:@"maxVideoSize"]; - [aCoder encodeInt32:_documents forKey:@"documents"]; - [aCoder encodeInt32:_maximumDocumentSize forKey:@"maxDocumentSize"]; - [aCoder encodeInt32:_voiceMessages forKey:@"voiceMessages"]; - [aCoder encodeInt32:_videoMessages forKey:@"videoMessages"]; -} - -+ (instancetype)defaultPreferences -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = TGAutoDownloadModeAll; - preferences->_videos = TGAutoDownloadModeNone; - preferences->_maximumVideoSize = 10; - preferences->_documents = TGAutoDownloadModeNone; - preferences->_maximumDocumentSize = 10; - preferences->_voiceMessages = TGAutoDownloadModeAll; - preferences->_videoMessages = TGAutoDownloadModeAll; - return preferences; -} - -+ (instancetype)preferencesWithLegacyDownloadPrivatePhotos:(bool)privatePhotos groupPhotos:(bool)groupPhotos privateVoiceMessages:(bool)privateVoiceMessages groupVoiceMessages:(bool)groupVoiceMessages privateVideoMessages:(bool)privateVideoMessages groupVideoMessages:(bool)groupVideoMessages -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - - if (privatePhotos) - preferences->_photos |= TGAutoDownloadModeAllPrivateChats; - if (groupPhotos) - preferences->_photos |= TGAutoDownloadModeAllGroups; - - if (privateVoiceMessages) - preferences->_voiceMessages |= TGAutoDownloadModeAllPrivateChats; - if (groupVoiceMessages) - preferences->_voiceMessages |= TGAutoDownloadModeAllGroups; - - if (privateVideoMessages) - preferences->_videoMessages |= TGAutoDownloadModeAllPrivateChats; - if (groupVideoMessages) - preferences->_videoMessages |= TGAutoDownloadModeAllGroups; - - preferences->_maximumVideoSize = 10; - preferences->_maximumDocumentSize = 10; - - return preferences; -} - -- (instancetype)updateDisabled:(bool)disabled -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_disabled = disabled; - preferences->_photos = _photos; - preferences->_videos = _videos; - preferences->_maximumVideoSize = _maximumVideoSize; - preferences->_documents = _documents; - preferences->_maximumDocumentSize = _maximumDocumentSize; - preferences->_voiceMessages = _voiceMessages; - preferences->_videoMessages = _videoMessages; - return preferences; -} - -- (instancetype)updatePhotosMode:(TGAutoDownloadMode)mode -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = mode; - preferences->_videos = _videos; - preferences->_maximumVideoSize = _maximumVideoSize; - preferences->_documents = _documents; - preferences->_maximumDocumentSize = _maximumDocumentSize; - preferences->_voiceMessages = _voiceMessages; - preferences->_videoMessages = _videoMessages; - return preferences; -} - -- (instancetype)updateVideosMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = _photos; - preferences->_videos = mode; - preferences->_maximumVideoSize = maximumSize; - preferences->_documents = _documents; - preferences->_maximumDocumentSize = _maximumDocumentSize; - preferences->_voiceMessages = _voiceMessages; - preferences->_videoMessages = _videoMessages; - return preferences; -} - -- (instancetype)updateDocumentsMode:(TGAutoDownloadMode)mode maximumSize:(int32_t)maximumSize -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = _photos; - preferences->_videos = _videos; - preferences->_maximumVideoSize = _maximumVideoSize; - preferences->_documents = mode; - preferences->_maximumDocumentSize = maximumSize; - preferences->_voiceMessages = _voiceMessages; - preferences->_videoMessages = _videoMessages; - return preferences; -} - -- (instancetype)updateVoiceMessagesMode:(TGAutoDownloadMode)mode -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = _photos; - preferences->_videos = _videos; - preferences->_maximumVideoSize = _maximumVideoSize; - preferences->_documents = _documents; - preferences->_maximumDocumentSize = _maximumDocumentSize; - preferences->_voiceMessages = mode; - preferences->_videoMessages = _videoMessages; - return preferences; -} - -- (instancetype)updateVideoMessagesMode:(TGAutoDownloadMode)mode -{ - TGAutoDownloadPreferences *preferences = [[TGAutoDownloadPreferences alloc] init]; - preferences->_photos = _photos; - preferences->_videos = _videos; - preferences->_maximumVideoSize = _maximumVideoSize; - preferences->_documents = _documents; - preferences->_maximumDocumentSize = _maximumDocumentSize; - preferences->_voiceMessages = _voiceMessages; - preferences->_videoMessages = mode; - return preferences; -} - -+ (bool)shouldDownload:(TGAutoDownloadMode)mode inChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - bool isWiFi = networkType == TGNetworkTypeWiFi; - bool isCellular = !isWiFi && networkType != TGNetworkTypeNone; - - bool shouldDownload = false; - switch (chat) - { - case TGAutoDownloadChatContact: - if (isCellular) - shouldDownload = (mode & TGAutoDownloadModeCellularContacts) != 0; - else if (isWiFi) - shouldDownload = (mode & TGAutoDownloadModeWifiContacts) != 0; - break; - - case TGAutoDownloadChatOtherPrivateChat: - if (isCellular) - shouldDownload = (mode & TGAutoDownloadModeCellularPrivateChats) != 0; - else if (isWiFi) - shouldDownload = (mode & TGAutoDownloadModeWifiPrivateChats) != 0; - break; - - case TGAutoDownloadChatGroup: - if (isCellular) - shouldDownload = (mode & TGAutoDownloadModeCellularGroups) != 0; - else if (isWiFi) - shouldDownload = (mode & TGAutoDownloadModeWifiGroups) != 0; - break; - - case TGAutoDownloadChatChannel: - if (isCellular) - shouldDownload = (mode & TGAutoDownloadModeCellularChannels) != 0; - else if (isWiFi) - shouldDownload = (mode & TGAutoDownloadModeWifiChannels) != 0; - break; - - default: - break; - } - return shouldDownload; -} - -- (bool)shouldDownloadPhotoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - if (self.disabled) - return false; - - return [TGAutoDownloadPreferences shouldDownload:_photos inChat:chat networkType:networkType]; -} - -- (bool)shouldDownloadVideoInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - if (self.disabled) - return false; - - return [TGAutoDownloadPreferences shouldDownload:_videos inChat:chat networkType:networkType]; -} - -- (bool)shouldDownloadDocumentInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - if (self.disabled) - return false; - - return [TGAutoDownloadPreferences shouldDownload:_documents inChat:chat networkType:networkType]; -} - -- (bool)shouldDownloadVoiceMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - if (self.disabled) - return false; - - return [TGAutoDownloadPreferences shouldDownload:_voiceMessages inChat:chat networkType:networkType]; -} - -- (bool)shouldDownloadVideoMessageInChat:(TGAutoDownloadChat)chat networkType:(TGNetworkType)networkType -{ - if (self.disabled) - return false; - - return [TGAutoDownloadPreferences shouldDownload:_videoMessages inChat:chat networkType:networkType]; -} - -- (bool)isDefaultPreferences -{ - return [self isEqual:[TGAutoDownloadPreferences defaultPreferences]]; -} - -- (BOOL)isEqual:(id)object -{ - if (object == self) - return YES; - - if (!object || ![object isKindOfClass:[self class]]) - return NO; - - TGAutoDownloadPreferences *preferences = (TGAutoDownloadPreferences *)object; - return preferences.photos == _photos && preferences.videos == _videos && preferences.documents == _documents && preferences.voiceMessages == _voiceMessages && preferences.videoMessages == _videoMessages && preferences.maximumVideoSize == _maximumVideoSize && preferences.maximumDocumentSize == _maximumDocumentSize && preferences.disabled == _disabled; -} - -@end diff --git a/submodules/LegacyDataImport/Impl/Sources/TGPresentationAutoNightPreferences.m b/submodules/LegacyDataImport/Impl/Sources/TGPresentationAutoNightPreferences.m deleted file mode 100644 index b53b768e38..0000000000 --- a/submodules/LegacyDataImport/Impl/Sources/TGPresentationAutoNightPreferences.m +++ /dev/null @@ -1,23 +0,0 @@ -#import - -@implementation TGPresentationAutoNightPreferences - -- (instancetype)initWithCoder:(NSCoder *)aDecoder { - self = [super init]; - if (self != nil) { - _mode = [aDecoder decodeInt32ForKey:@"m"]; - _brightnessThreshold = [aDecoder decodeDoubleForKey:@"b"]; - _scheduleStart = [aDecoder decodeInt32ForKey:@"ss"]; - _scheduleEnd = [aDecoder decodeInt32ForKey:@"se"]; - _latitude = [aDecoder decodeDoubleForKey:@"lat"]; - _longitude = [aDecoder decodeDoubleForKey:@"lon"]; - _cachedLocationName = [aDecoder decodeObjectForKey:@"loc"]; - _preferredPalette = [aDecoder decodeInt32ForKey:@"p"]; - } - return self; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder { -} - -@end diff --git a/submodules/LegacyDataImport/Impl/Sources/TGProxyItem.m b/submodules/LegacyDataImport/Impl/Sources/TGProxyItem.m deleted file mode 100644 index 4dfc1d6c93..0000000000 --- a/submodules/LegacyDataImport/Impl/Sources/TGProxyItem.m +++ /dev/null @@ -1,73 +0,0 @@ -#import - -static bool TGObjectCompare(id obj1, id obj2) { - if (obj1 == nil && obj2 == nil) - return true; - - return [obj1 isEqual:obj2]; -} - -@implementation TGProxyItem - -- (instancetype)initWithServer:(NSString *)server port:(int16_t)port username:(NSString *)username password:(NSString *)password secret:(NSString *)secret -{ - self = [super init]; - if (self != nil) - { - _server = server; - _port = port; - _username = username; - _password = password; - _secret = secret; - } - return self; -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder -{ - return [self initWithServer:[aDecoder decodeObjectForKey:@"server"] port:(int16_t)[aDecoder decodeInt32ForKey:@"port"] username:[aDecoder decodeObjectForKey:@"user"] password:[aDecoder decodeObjectForKey:@"pass"] secret:[aDecoder decodeObjectForKey:@"secret"]]; -} - -- (void)encodeWithCoder:(NSCoder *)aCoder -{ - [aCoder encodeObject:_server forKey:@"server"]; - [aCoder encodeInt32:_port forKey:@"port"]; - [aCoder encodeObject:_username forKey:@"user"]; - [aCoder encodeObject:_password forKey:@"pass"]; - [aCoder encodeObject:_secret forKey:@"secret"]; -} - -- (bool)isMTProxy -{ - return _secret.length > 0; -} - -- (BOOL)isEqual:(id)object -{ - if (object == self) - return true; - - if (!object || ![object isKindOfClass:[self class]]) - return false; - - TGProxyItem *proxy = (TGProxyItem *)object; - - if (![_server isEqualToString:proxy.server]) - return false; - - if (_port != proxy.port) - return false; - - if (!TGObjectCompare(_username ?: @"", proxy.username ?: @"")) - return false; - - if (!TGObjectCompare(_password ?: @"", proxy.password ?: @"")) - return false; - - if (!TGObjectCompare(_secret ?: @"", proxy.secret ?: @"")) - return false; - - return true; -} - -@end diff --git a/submodules/LegacyDataImport/Sources/LegacyBuffer.swift b/submodules/LegacyDataImport/Sources/LegacyBuffer.swift deleted file mode 100644 index cebc964f39..0000000000 --- a/submodules/LegacyDataImport/Sources/LegacyBuffer.swift +++ /dev/null @@ -1,197 +0,0 @@ -import Foundation - -class LegacyBuffer: CustomStringConvertible { - var data: UnsafeMutableRawPointer? - var _size: UInt = 0 - private var capacity: UInt = 0 - private let freeWhenDone: Bool - - var size: Int { - return Int(self._size) - } - - deinit { - if self.freeWhenDone { - free(self.data) - } - } - - init(memory: UnsafeMutableRawPointer?, size: Int, capacity: Int, freeWhenDone: Bool) { - self.data = memory - self._size = UInt(size) - self.capacity = UInt(capacity) - self.freeWhenDone = freeWhenDone - } - - init() { - self.data = nil - self._size = 0 - self.capacity = 0 - self.freeWhenDone = true - } - - convenience init(data: Data?) { - self.init() - - if let data = data { - data.withUnsafeBytes { bytes in - self.appendBytes(bytes, length: UInt(data.count)) - } - } - } - - func makeData() -> Data { - return self.withUnsafeMutablePointer { pointer, size -> Data in - if let pointer = pointer { - return Data(bytes: pointer.assumingMemoryBound(to: UInt8.self), count: Int(size)) - } else { - return Data() - } - } - } - - var description: String { - get { - var string = "" - if let data = self.data { - var i: UInt = 0 - let bytes = data.assumingMemoryBound(to: UInt8.self) - while i < _size && i < 8 { - string += String(format: "%02x", Int(bytes.advanced(by: Int(i)).pointee)) - i += 1 - } - if i < _size { - string += "...\(_size)b" - } - } else { - string += "" - } - return string - } - } - - func appendBytes(_ bytes: UnsafeRawPointer, length: UInt) { - if self.capacity < self._size + length { - self.capacity = self._size + length + 128 - if self.data == nil { - self.data = malloc(Int(self.capacity))! - } - else { - self.data = realloc(self.data, Int(self.capacity))! - } - } - - memcpy(self.data?.advanced(by: Int(self._size)), bytes, Int(length)) - self._size += length - } - - func appendBuffer(_ buffer: LegacyBuffer) { - if self.capacity < self._size + buffer._size { - self.capacity = self._size + buffer._size + 128 - if self.data == nil { - self.data = malloc(Int(self.capacity))! - } - else { - self.data = realloc(self.data, Int(self.capacity))! - } - } - - memcpy(self.data?.advanced(by: Int(self._size)), buffer.data, Int(buffer._size)) - } - - func appendInt32(_ value: Int32) { - var v = value - self.appendBytes(&v, length: 4) - } - - func appendInt64(_ value: Int64) { - var v = value - self.appendBytes(&v, length: 8) - } - - func appendDouble(_ value: Double) { - var v = value - self.appendBytes(&v, length: 8) - } - - func withUnsafeMutablePointer(_ f: (UnsafeMutableRawPointer?, UInt) -> R) -> R { - return f(self.data, self._size) - } -} - -class LegacyBufferReader { - private let buffer: LegacyBuffer - private(set) var offset: UInt = 0 - - init(_ buffer: LegacyBuffer) { - self.buffer = buffer - } - - func reset() { - self.offset = 0 - } - - func skip(_ count: Int) { - self.offset = min(self.buffer._size, self.offset + UInt(count)) - } - - func readInt32() -> Int32? { - if self.offset + 4 <= self.buffer._size { - let value: Int32 = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Int32.self).pointee - self.offset += 4 - return value - } - return nil - } - - func readInt64() -> Int64? { - if self.offset + 8 <= self.buffer._size { - let value: Int64 = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Int64.self).pointee - self.offset += 8 - return value - } - return nil - } - - func readDouble() -> Double? { - if self.offset + 8 <= self.buffer._size { - let value: Double = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Double.self).pointee - self.offset += 8 - return value - } - return nil - } - - func readBytesAsInt32(_ count: Int) -> Int32? { - if count == 0 { - return 0 - } - guard count > 0, count <= 4, self.offset + UInt(count) <= self.buffer._size else { - return nil - } - guard let bufferData = self.buffer.data else { - return nil - } - var value: Int32 = 0 - memcpy(&value, bufferData.advanced(by: Int(self.offset)), count) - self.offset += UInt(count) - return value - } - - func readBuffer(_ count: Int) -> LegacyBuffer? { - if count >= 0 && self.offset + UInt(count) <= self.buffer._size { - let buffer = LegacyBuffer() - buffer.appendBytes((self.buffer.data?.advanced(by: Int(self.offset)))!, length: UInt(count)) - self.offset += UInt(count) - return buffer - } - return nil - } - - func withReadBufferNoCopy(_ count: Int, _ f: (LegacyBuffer) -> T) -> T? { - if count >= 0 && self.offset + UInt(count) <= self.buffer._size { - return f(LegacyBuffer(memory: self.buffer.data!.advanced(by: Int(self.offset)), size: count, capacity: count, freeWhenDone: false)) - } - return nil - } -} diff --git a/submodules/LegacyDataImport/Sources/LegacyChatImport.swift b/submodules/LegacyDataImport/Sources/LegacyChatImport.swift deleted file mode 100644 index 9a50a1471a..0000000000 --- a/submodules/LegacyDataImport/Sources/LegacyChatImport.swift +++ /dev/null @@ -1,780 +0,0 @@ -import Foundation -import TelegramCore -import SyncCore -import SwiftSignalKit -import Postbox -import LegacyComponents - -private let reportedLayer_hash: Int32 = -717538193 -private let layer_hash: Int32 = 849537378 -private let seq_out_hash: Int32 = -737765753 -private let seq_in_hash: Int32 = -7646011 - -private let defaultPrime: Data = { - let bytes: [UInt8] = [ - 0xc7, 0x1c, 0xae, 0xb9, 0xc6, 0xb1, 0xc9, 0x04, 0x8e, 0x6c, 0x52, 0x2f, - 0x70, 0xf1, 0x3f, 0x73, 0x98, 0x0d, 0x40, 0x23, 0x8e, 0x3e, 0x21, 0xc1, - 0x49, 0x34, 0xd0, 0x37, 0x56, 0x3d, 0x93, 0x0f, 0x48, 0x19, 0x8a, 0x0a, - 0xa7, 0xc1, 0x40, 0x58, 0x22, 0x94, 0x93, 0xd2, 0x25, 0x30, 0xf4, 0xdb, - 0xfa, 0x33, 0x6f, 0x6e, 0x0a, 0xc9, 0x25, 0x13, 0x95, 0x43, 0xae, 0xd4, - 0x4c, 0xce, 0x7c, 0x37, 0x20, 0xfd, 0x51, 0xf6, 0x94, 0x58, 0x70, 0x5a, - 0xc6, 0x8c, 0xd4, 0xfe, 0x6b, 0x6b, 0x13, 0xab, 0xdc, 0x97, 0x46, 0x51, - 0x29, 0x69, 0x32, 0x84, 0x54, 0xf1, 0x8f, 0xaf, 0x8c, 0x59, 0x5f, 0x64, - 0x24, 0x77, 0xfe, 0x96, 0xbb, 0x2a, 0x94, 0x1d, 0x5b, 0xcd, 0x1d, 0x4a, - 0xc8, 0xcc, 0x49, 0x88, 0x07, 0x08, 0xfa, 0x9b, 0x37, 0x8e, 0x3c, 0x4f, - 0x3a, 0x90, 0x60, 0xbe, 0xe6, 0x7c, 0xf9, 0xa4, 0xa4, 0xa6, 0x95, 0x81, - 0x10, 0x51, 0x90, 0x7e, 0x16, 0x27, 0x53, 0xb5, 0x6b, 0x0f, 0x6b, 0x41, - 0x0d, 0xba, 0x74, 0xd8, 0xa8, 0x4b, 0x2a, 0x14, 0xb3, 0x14, 0x4e, 0x0e, - 0xf1, 0x28, 0x47, 0x54, 0xfd, 0x17, 0xed, 0x95, 0x0d, 0x59, 0x65, 0xb4, - 0xb9, 0xdd, 0x46, 0x58, 0x2d, 0xb1, 0x17, 0x8d, 0x16, 0x9c, 0x6b, 0xc4, - 0x65, 0xb0, 0xd6, 0xff, 0x9c, 0xa3, 0x92, 0x8f, 0xef, 0x5b, 0x9a, 0xe4, - 0xe4, 0x18, 0xfc, 0x15, 0xe8, 0x3e, 0xbe, 0xa0, 0xf8, 0x7f, 0xa9, 0xff, - 0x5e, 0xed, 0x70, 0x05, 0x0d, 0xed, 0x28, 0x49, 0xf4, 0x7b, 0xf9, 0x59, - 0xd9, 0x56, 0x85, 0x0c, 0xe9, 0x29, 0x85, 0x1f, 0x0d, 0x81, 0x15, 0xf6, - 0x35, 0xb1, 0x05, 0xee, 0x2e, 0x4e, 0x15, 0xd0, 0x4b, 0x24, 0x54, 0xbf, - 0x6f, 0x4f, 0xad, 0xf0, 0x34, 0xb1, 0x04, 0x03, 0x11, 0x9c, 0xd8, 0xe3, - 0xb9, 0x2f, 0xcc, 0x5b - ] - var data = Data(count: bytes.count) - data.withUnsafeMutableBytes { (dst: UnsafeMutablePointer) -> Void in - for i in 0 ..< bytes.count { - dst.advanced(by: i).pointee = bytes[i] - } - } - return data -}() - -@objc(TGEncryptionKeyData) private final class TGEncryptionKeyData: NSObject, NSCoding { - let keyId: Int64 - let key: Data - let firstSeqOut: Int32 - - init?(coder aDecoder: NSCoder) { - self.keyId = aDecoder.decodeInt64(forKey: "keyId") - self.key = (aDecoder.decodeObject(forKey: "key") as? Data) ?? Data() - self.firstSeqOut = aDecoder.decodeInt32(forKey: "firstSeqOut") - } - - func encode(with aCoder: NSCoder) { - assertionFailure() - } -} - -private struct SecretChatData { - let accessHash: Int64 - let handshakeState: Int32 - let rekeyState: SecretChatRekeySessionState? -} - -private func readSecretChatParticipantData(accountPeerId: PeerId, data: Data) -> (SecretChatRole, PeerId)? { - let reader = LegacyBufferReader(LegacyBuffer(data: data)) - - guard reader.readInt32() == Int32(bitPattern: 0xabcdef12) else { - return nil - } - guard let formatVersion = reader.readInt32(), formatVersion >= 2 else { - return nil - } - reader.skip(4) - - guard let adminId = reader.readInt32() else { - return nil - } - guard let count = reader.readInt32() else { - return nil - } - var ids: [Int32] = [] - for _ in 0 ..< Int(count) { - guard let id = reader.readInt32() else { - return nil - } - reader.skip(4) - reader.skip(4) - ids.append(id) - } - - guard let otherPeerId = ids.first else { - return nil - } - - return (adminId == accountPeerId.id ? .creator : .participant, PeerId(namespace: Namespaces.Peer.CloudUser, id: otherPeerId)) -} - -private func readSecretChatData(reader: LegacyBufferReader) -> SecretChatData? { - guard let version = reader.readBytesAsInt32(1) else { - return nil - } - if version != 3 { - return nil - } - reader.skip(8) - - guard let accessHash = reader.readInt64() else { - return nil - } - guard let _ = reader.readInt64() else { - return nil - } - guard let handshakeState = reader.readInt32() else { - return nil - } - guard let currentRekeyExchangeId = reader.readInt64() else { - return nil - } - guard let currentRekeyIsInitiatedByLocalClient = reader.readBytesAsInt32(1) else { - return nil - } - guard let currentRekeyNumberLength = reader.readInt32() else { - return nil - } - var currentRekeyNumber: Data? - if currentRekeyNumberLength > 0 { - guard let value = reader.readBuffer(Int(currentRekeyNumberLength))?.makeData() else { - return nil - } - currentRekeyNumber = value - } - guard let currentRekeyKeyLength = reader.readInt32() else { - return nil - } - var currentRekeyKey: Data? - if currentRekeyKeyLength > 0 { - guard let value = reader.readBuffer(Int(currentRekeyKeyLength))?.makeData() else { - return nil - } - currentRekeyKey = value - } - guard let currentRekeyKeyId = reader.readInt64() else { - return nil - } - - var rekeyState: SecretChatRekeySessionState? - if currentRekeyExchangeId != 0 { - let innerState: SecretChatRekeySessionData? - if currentRekeyIsInitiatedByLocalClient != 0, let currentRekeyNumber = currentRekeyNumber { - innerState = .requested(a: MemoryBuffer(data: currentRekeyNumber), config: SecretChatEncryptionConfig(g: 3, p: MemoryBuffer(data: defaultPrime), version: 0)) - } else if currentRekeyIsInitiatedByLocalClient == 0, let currentRekeyKey = currentRekeyKey, currentRekeyKeyId != 0 { - innerState = .accepted(key: MemoryBuffer(data: currentRekeyKey), keyFingerprint: currentRekeyKeyId) - } else { - innerState = nil - } - if let innerState = innerState { - rekeyState = SecretChatRekeySessionState(id: currentRekeyExchangeId, data: innerState) - } - } - - return SecretChatData(accessHash: accessHash, handshakeState: handshakeState, rekeyState: rekeyState) -} - -let registeredAttachmentParsers: Bool = { - let parsers: [(Int32, TGMediaAttachmentParser)] = [ - (TGActionMediaAttachmentType, TGActionMediaAttachment()), - (TGImageMediaAttachmentType, TGImageMediaAttachment()), - (TGLocationMediaAttachmentType, TGLocationMediaAttachment()), - (TGVideoMediaAttachmentType, TGVideoMediaAttachment()), - (Int32(bitPattern: 0xB90A5663), TGContactMediaAttachment()), - (Int32(bitPattern: 0xE6C64318), TGDocumentMediaAttachment()), - (TGAudioMediaAttachmentType, TGAudioMediaAttachment()), - (Int32(bitPattern: 0x8C2E3CCE), TGMessageEntitiesAttachment()), - (Int32(bitPattern: 0x944DE6B6), TGLocalMessageMetaMediaAttachment()), - (TGAuthorSignatureMediaAttachmentType, TGAuthorSignatureMediaAttachment()), - (TGInvoiceMediaAttachmentType, TGInvoiceMediaAttachment()), - (TGGameAttachmentType, TGGameMediaAttachment()), - (Int32(bitPattern: 0xA3F4C8F5), TGViaUserAttachment()), - (TGBotContextResultAttachmentType, TGBotContextResultAttachment()), - (TGReplyMarkupAttachmentType, TGReplyMarkupAttachment()), - (TGWebPageMediaAttachmentType, TGWebPageMediaAttachment()), - (TGReplyMessageMediaAttachmentType, TGReplyMessageMediaAttachment()), - (TGAudioMediaAttachmentType, TGAudioMediaAttachment()), - (Int32(bitPattern: 0xaa1050c1), TGForwardedMessageMediaAttachment()) - ] - for (id, parser) in parsers { - TGMessage.registerMediaAttachmentParser(id, parser: parser) - } - return true -}() - -private func parseSecretChatData(peerId: PeerId, data: Data, unreadCount: Int32) -> (SecretChatData, [MessageId.Namespace: PeerReadState], Int32)? { - let reader = LegacyBufferReader(LegacyBuffer(data: data)) - guard let magic = reader.readInt32() else { - return nil - } - var version: Int32 = 1 - if magic == 0x7acde441 { - guard let value = reader.readInt32() else { - return nil - } - version = value - } - - if version < 2 { - return nil - } - - for _ in 0 ..< 3 { - guard let length = reader.readInt32() else { - return nil - } - reader.skip(Int(length)) - } - - guard let hasEncryptedData = reader.readBytesAsInt32(1), hasEncryptedData == 1 else { - return nil - } - guard let secretChatData = readSecretChatData(reader: reader) else { - return nil - } - reader.skip(4) - reader.skip(4) - reader.skip(8) - reader.skip(4) - reader.skip(4) - reader.skip(4) - reader.skip(4) - guard let maxReadDate = reader.readInt32() else { - return nil - } - guard let maxOutgoingReadDate = reader.readInt32() else { - return nil - } - guard let messageDate = reader.readInt32() else { - return nil - } - guard let minMessageDate = reader.readInt32() else { - return nil - } - - let readStates: [MessageId.Namespace: PeerReadState] = [ - Namespaces.Message.SecretIncoming: .indexBased(maxIncomingReadIndex: MessageIndex(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: 1), timestamp: maxReadDate), maxOutgoingReadIndex: MessageIndex.lowerBound(peerId: peerId), count: 0, markedUnread: false), - Namespaces.Message.Local: .indexBased(maxIncomingReadIndex: MessageIndex.lowerBound(peerId: peerId), maxOutgoingReadIndex: MessageIndex(id: MessageId(peerId: peerId, namespace: Namespaces.Message.Local, id: 1), timestamp: maxOutgoingReadDate), count: 0, markedUnread: false) - ] - return (secretChatData, readStates, max(messageDate, minMessageDate)) -} - -private enum CustomPropertyKey { - case string(String) - case hash(Int32) -} - -private func loadLegacyPeerCustomProperyData(database: SqliteInterface, peerId: Int64, key: CustomPropertyKey) -> Data? { - var propertiesData: Data? - database.select("SELECT custom_properties FROM peers_v29 WHERE pid=\(peerId)", { cursor in - propertiesData = cursor.getData(at: 0) - return false - }) - if let propertiesData = propertiesData { - let keyHash: Int32 - switch key { - case let .string(string): - keyHash = HashFunctions.murMurHash32(string) - case let .hash(hash): - keyHash = hash - } - let reader = LegacyBufferReader(LegacyBuffer(data: propertiesData)) - - guard let _ = reader.readInt32() else { - return nil - } - guard let count = reader.readInt32() else { - return nil - } - for _ in 0 ..< Int(count) { - guard let valueKey = reader.readInt32() else { - return nil - } - guard let valueLength = reader.readInt32() else { - return nil - } - if valueKey == keyHash { - return reader.readBuffer(Int(valueLength))?.makeData() - } - reader.skip(Int(valueLength)) - } - } - return nil -} - -private func loadLegacyPeerCustomProperyInt32(database: SqliteInterface, peerId: Int64, key: CustomPropertyKey) -> Int32? { - guard let data = loadLegacyPeerCustomProperyData(database: database, peerId: peerId, key: key), data.count == 4 else { - return nil - } - var result: Int32 = 0 - withUnsafeMutablePointer(to: &result, { bytes -> Void in - data.copyBytes(to: UnsafeMutableRawPointer(bytes).assumingMemoryBound(to: UInt8.self), from: 0 ..< 4) - }) - return result -} - -private func loadLegacyMessages(account: TemporaryAccount, basePath: String, accountPeerId: PeerId, peerId: PeerId, userPeerId: PeerId, database: SqliteInterface, conversationId: Int64, expectedTotalCount: Int32) -> Signal { - return Signal { subscriber in - subscriber.putNext(0.0) - - var copyLocalFiles: [(MediaResource, String)] = [] - var messages: [StoreMessage] = [] - - Logger.shared.log("loadLegacyMessages", "begin peerId \(peerId) conversationId \(conversationId) count \(expectedTotalCount)") - - database.select("CREATE INDEX IF NOT EXISTS random_ids_mid ON random_ids_v29 (mid)", { _ in - return true - }) - - var messageIndex: Int32 = -1 - let reportBase = max(1, expectedTotalCount / 100) - - database.select("SELECT mid, message, media, from_id, dstate, date, flags, localMid, content_properties FROM messages_v29 WHERE cid=\(conversationId)", { cursor in - messageIndex += 1 - - #if DEBUG - //usleep(500000) - #endif - - if messageIndex % reportBase == 0 { - subscriber.putNext(min(1.0, Float(messageIndex) / Float(expectedTotalCount))) - } - - let messageId = cursor.getInt32(at: 0) - - //Logger.shared.log("loadLegacyMessages", "import message \(messageId)") - - var globallyUniqueId: Int64? - database.select("SELECT random_id FROM random_ids_v29 where mid=\(messageId)", { innerCursor in - globallyUniqueId = innerCursor.getInt64(at: 0) - return false - }) - - let text = cursor.getString(at: 1) - let fromId = cursor.getInt64(at: 3) - let deliveryState = cursor.getInt32(at: 4) - let timestamp = cursor.getInt32(at: 5) - let autoremoveTimeout = cursor.getInt32(at: 7) - let contentPropertiesData = cursor.getData(at: 8) - - let parsedAuthorId: PeerId - let parsedId: StoreMessageId - var parsedFlags: StoreMessageFlags = [] - var parsedAttributes: [MessageAttribute] = [] - var parsedMedia: [Media] = [] - var parsedGroupingKey: Int64? - - if fromId == accountPeerId.id { - parsedAuthorId = accountPeerId - parsedId = .Partial(peerId, Namespaces.Message.Local) - } else { - parsedAuthorId = userPeerId - parsedId = .Partial(peerId, Namespaces.Message.SecretIncoming) - parsedFlags.insert(.Incoming) - } - - if deliveryState != 0 { - return true - } - - if !contentPropertiesData.isEmpty { - if let contentProperties = TGMessage.parseContentProperties(contentPropertiesData) { - for (_, value) in contentProperties { - if let value = value as? TGMessageGroupedIdContentProperty { - parsedGroupingKey = value.groupedId - } - } - } - } - - //Logger.shared.log("loadLegacyMessages", "message \(messageId) read content properties") - - let media = cursor.getData(at: 2) - if let mediaList = TGMessage.parseMediaAttachments(media) { - for item in mediaList { - if let item = item as? TGImageMediaAttachment { - let mediaId = MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64()) - var representations: [TelegramMediaImageRepresentation] = [] - if let allSizes = item.imageInfo?.allSizes() as? [String: NSValue] { - - for (imageUrl, sizeValue) in allSizes { - var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64()) - var resourcePath: String? - if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: imageUrl, type: .image) { - resource = updatedResource - copyLocalFiles.append((updatedResource, path)) - resourcePath = path - } else if imageUrl.hasPrefix("file://"), let path = URL(string: imageUrl)?.path { - copyLocalFiles.append((resource, path)) - resourcePath = path - } - - var dimensions = sizeValue.cgSizeValue - if let resourcePath = resourcePath, let image = UIImage(contentsOfFile: resourcePath) { - dimensions = image.size - } - representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(dimensions), resource: resource, progressiveSizes: [])) - } - } - - if item.localImageId != 0 { - let fullSizePath = basePath + "/Documents/files/image-local-\(String(item.localImageId, radix: 16))/image.jpg" - if let image = UIImage(contentsOfFile: fullSizePath) { - let resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64()) - copyLocalFiles.append((resource, fullSizePath)) - representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(image.size), resource: resource, progressiveSizes: [])) - } - } - - parsedMedia.append(TelegramMediaImage(imageId: mediaId, representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])) - } else if let item = item as? TGVideoMediaAttachment { - let mediaId = MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64()) - var representations: [TelegramMediaImageRepresentation] = [] - if let allSizes = item.thumbnailInfo?.allSizes() as? [String: NSValue] { - for (imageUrl, sizeValue) in allSizes { - var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64()) - if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: imageUrl, type: .image) { - resource = updatedResource - copyLocalFiles.append((updatedResource, path)) - } else if imageUrl.hasPrefix("file://"), let path = URL(string: imageUrl)?.path { - copyLocalFiles.append((resource, path)) - } - representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(sizeValue.cgSizeValue), resource: resource, progressiveSizes: [])) - } - } - - var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64()) - - var attributes: [TelegramMediaFileAttribute] = [] - attributes.append(.Video(duration: Int(item.duration), size: PixelDimensions(item.dimensions), flags: item.roundMessage ? .instantRoundVideo : [])) - - var size: Int32 = 0 - if let videoUrl = item.videoInfo?.url(withQuality: 1, actualQuality: nil, actualSize: &size) { - if let path = pathFromLegacyLocalVideoUrl(basePath: basePath, url: videoUrl) { - copyLocalFiles.append((resource, path)) - } else if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: videoUrl, type: .video) { - resource = updatedResource - copyLocalFiles.append((updatedResource, path)) - } else if videoUrl.hasPrefix("file://"), let path = URL(string: videoUrl)?.path { - copyLocalFiles.append((resource, path)) - } - } - parsedMedia.append(TelegramMediaFile(fileId: mediaId, partialReference: nil, resource: resource, previewRepresentations: representations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: size == 0 ? nil : Int(size), attributes: attributes)) - } else if let item = item as? TGAudioMediaAttachment { - let mediaId = MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64()) - let representations: [TelegramMediaImageRepresentation] = [] - - var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64()) - - var attributes: [TelegramMediaFileAttribute] = [] - attributes.append(.Audio(isVoice: true, duration: Int(item.duration), title: nil, performer: nil, waveform: nil)) - - let size: Int32 = item.fileSize - let audioUrl = item.audioUri ?? "" - - if let path = pathFromLegacyLocalVideoUrl(basePath: basePath, url: audioUrl) { - copyLocalFiles.append((resource, path)) - } else if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: audioUrl, type: .audio) { - resource = updatedResource - copyLocalFiles.append((updatedResource, path)) - } else if audioUrl.hasPrefix("file://"), let path = URL(string: audioUrl)?.path { - copyLocalFiles.append((resource, path)) - } - parsedMedia.append(TelegramMediaFile(fileId: mediaId, partialReference: nil, resource: resource, previewRepresentations: representations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: size == 0 ? nil : Int(size), attributes: attributes)) - } else if let item = item as? TGDocumentMediaAttachment { - let mediaId = MediaId(namespace: Namespaces.Media.LocalImage, id: arc4random64()) - var representations: [TelegramMediaImageRepresentation] = [] - if let allSizes = (item.thumbnailInfo?.allSizes()) as? [String: NSValue] { - for (imageUrl, sizeValue) in allSizes { - var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64()) - if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: imageUrl, type: .image) { - resource = updatedResource - copyLocalFiles.append((updatedResource, path)) - } else if imageUrl.hasPrefix("file://"), let path = URL(string: imageUrl)?.path { - copyLocalFiles.append((resource, path)) - } else if let updatedResource = resourceFromLegacyImageUrl(imageUrl) { - resource = updatedResource - copyLocalFiles.append((resource, pathFromLegacyImageUrl(basePath: basePath, url: imageUrl))) - } - representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(sizeValue.cgSizeValue), resource: resource, progressiveSizes: [])) - } - } - - var resource: TelegramMediaResource = LocalFileMediaResource(fileId: arc4random64()) - - var attributes: [TelegramMediaFileAttribute] = [] - var fileName = "file" - if let itemAttributes = item.attributes { - for attribute in itemAttributes { - if let attribute = attribute as? TGDocumentAttributeFilename { - attributes.append(.FileName(fileName: attribute.filename ?? "file")) - fileName = attribute.filename ?? "file" - } else if let attribute = attribute as? TGDocumentAttributeAudio { - let title = attribute.title ?? "" - let performer = attribute.performer ?? "" - var waveform: MemoryBuffer? - if let data = attribute.waveform { - waveform = MemoryBuffer(data: data.bitstream()!) - } - attributes.append(.Audio(isVoice: attribute.isVoice, duration: Int(attribute.duration), title: title.isEmpty ? nil : title, performer: performer.isEmpty ? nil : performer, waveform: waveform)) - } else if let _ = attribute as? TGDocumentAttributeAnimated { - attributes.append(.Animated) - } else if let attribute = attribute as? TGDocumentAttributeVideo { - attributes.append(.Video(duration: Int(attribute.duration), size: PixelDimensions(attribute.size), flags: attribute.isRoundMessage ? .instantRoundVideo : [])) - } else if let attribute = attribute as? TGDocumentAttributeSticker { - var packReference: StickerPackReference? - if let reference = attribute.packReference as? TGStickerPackIdReference { - packReference = .id(id: reference.packId, accessHash: reference.packAccessHash) - } else if let reference = attribute.packReference as? TGStickerPackShortnameReference { - packReference = .name(reference.shortName ?? "") - } - attributes.append(.Sticker(displayText: attribute.alt ?? "", packReference: packReference, maskData: nil)) - } else if let attribute = attribute as? TGDocumentAttributeImageSize { - attributes.append(.ImageSize(size: PixelDimensions(attribute.size))) - } - } - } - - let documentUri = item.documentUri ?? "" - - let size: Int32 = item.size - if documentUri.hasPrefix("file://"), let path = URL(string: documentUri)?.path { - copyLocalFiles.append((resource, path)) - } else if let (path, updatedResource) = pathAndResourceFromEncryptedFileUrl(basePath: basePath, url: documentUri, type: .document(fileName: fileName)) { - resource = updatedResource - copyLocalFiles.append((resource, path)) - } else if item.localDocumentId != 0 { - copyLocalFiles.append((resource, pathFromLegacyFile(basePath: basePath, fileId: item.localDocumentId, isLocal: true, fileName: TGDocumentMediaAttachment.safeFileName(forFileName: fileName) ?? ""))) - } else if item.documentId != 0 { - copyLocalFiles.append((resource, pathFromLegacyFile(basePath: basePath, fileId: item.documentId, isLocal: false, fileName: TGDocumentMediaAttachment.safeFileName(forFileName: fileName) ?? ""))) - } - parsedMedia.append(TelegramMediaFile(fileId: mediaId, partialReference: nil, resource: resource, previewRepresentations: representations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: item.mimeType ?? "application/octet-stream", size: size == 0 ? nil : Int(size), attributes: attributes)) - } else if let item = item as? TGActionMediaAttachment { - if item.actionType == TGMessageActionEncryptedChatMessageLifetime, let actionData = item.actionData, let timeout = actionData["messageLifetime"] as? Int32 { - - parsedMedia.append(TelegramMediaAction(action: .messageAutoremoveTimeoutUpdated(timeout))) - } - } else if let item = item as? TGContactMediaAttachment { - parsedMedia.append(TelegramMediaContact(firstName: item.firstName ?? "", lastName: item.lastName ?? "", phoneNumber: item.phoneNumber ?? "", peerId: nil, vCardData: nil)) - } else if let item = item as? TGLocationMediaAttachment { - var venue: MapVenue? - if let v = item.venue { - venue = MapVenue(title: v.title ?? "", address: v.address ?? "", provider: v.provider == "" ? nil : v.provider, id: v.venueId == "" ? nil : v.venueId, type: v.type == "" ? nil : v.type) - } - parsedMedia.append(TelegramMediaMap(latitude: item.latitude, longitude: item.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: venue, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil)) - } - } - } - - //Logger.shared.log("loadLegacyMessages", "message \(messageId) read media") - - if autoremoveTimeout != 0 { - var countdownBeginTime: Int32? - database.select("SELECT date FROM selfdestruct_v29 where mid=\(messageId)", { innerCursor in - countdownBeginTime = innerCursor.getInt32(at: 0) - autoremoveTimeout - return false - }) - parsedAttributes.append(AutoremoveTimeoutMessageAttribute(timeout: autoremoveTimeout, countdownBeginTime: countdownBeginTime)) - } - - let (parsedTags, parsedGlobalTags) = tagsForStoreMessage(incoming: parsedFlags.contains(.Incoming), attributes: parsedAttributes, media: parsedMedia, textEntities: nil, isPinned: false) - messages.append(StoreMessage(id: parsedId, globallyUniqueId: globallyUniqueId, groupingKey: parsedGroupingKey, threadId: nil, timestamp: timestamp, flags: parsedFlags, tags: parsedTags, globalTags: parsedGlobalTags, localTags: [], forwardInfo: nil, authorId: parsedAuthorId, text: text, attributes: parsedAttributes, media: parsedMedia)) - - //Logger.shared.log("loadLegacyMessages", "message \(messageId) completed") - - return true - }) - - let disposable = (account.postbox.transaction { transaction -> Void in - //Logger.shared.log("loadLegacyMessages", "conversation \(conversationId) storing messages") - let _ = transaction.addMessages(messages, location: .UpperHistoryBlock) - - //Logger.shared.log("loadLegacyMessages", "conversation \(conversationId) copying \(copyLocalFiles.count) files") - - for (resource, path) in copyLocalFiles { - account.postbox.mediaBox.copyResourceData(resource.id, fromTempPath: path) - } - - Logger.shared.log("loadLegacyMessages", "conversation \(conversationId) done") - }).start(completed: { - subscriber.putCompletion() - }) - - return disposable - } -} - -private func importChannelBroadcastPreferences(account: TemporaryAccount, basePath: String, database: SqliteInterface) -> Signal { - return deferred { () -> Signal in - var peerIds: [Int64] = [] - database.select("SELECT cid FROM channel_conversations_v29", { cursor in - peerIds.append(cursor.getInt64(at: 0)) - return true - }) - var peerIdsWithMutedMessages: [Int64] = [] - for peerId in peerIds { - if let data = loadLegacyPeerCustomProperyData(database: database, peerId: peerId, key: .hash(0x374BF349)), !data.isEmpty { - let reader = LegacyBufferReader(LegacyBuffer(data: data)) - guard let version = reader.readBytesAsInt32(1) else { - continue - } - guard let _ = reader.readBytesAsInt32(1) else { - continue - } - if version >= 2 { - guard let messagesMuted = reader.readBytesAsInt32(1) else { - continue - } - if messagesMuted == 1 { - peerIdsWithMutedMessages.append(peerId) - } - } - } - } - - return .complete() - } -} - -func loadLegacySecretChats(account: TemporaryAccount, basePath: String, accountPeerId: PeerId, database: SqliteInterface) -> Signal { - return deferred { () -> Signal in - var peerIdToConversationId: [PeerId: Int64] = [:] - database.select("SELECT encrypted_id, cid FROM encrypted_cids_v29", { cursor in - peerIdToConversationId[PeerId(namespace: Namespaces.Peer.SecretChat, id: cursor.getInt32(at: 0))] = cursor.getInt64(at: 1) - return true - }) - var chatInfos: [(TelegramSecretChat, SecretChatState, Int32?, [MessageId.Namespace: PeerReadState], Int64)] = [] - for (peerId, conversationId) in peerIdToConversationId { - database.select("SELECT chat_photo, unread_count, participants, date FROM convesations_v29 WHERE cid=\(conversationId)", { cursor in - guard let (secretChatData, readStates, minMessageDate) = parseSecretChatData(peerId: peerId, data: cursor.getData(at: 0), unreadCount: cursor.getInt32(at: 1)) else { - return false - } - guard let (role, userPeerId) = readSecretChatParticipantData(accountPeerId: accountPeerId, data: cursor.getData(at: 2)) else { - return false - } - let chatMessageDate = cursor.getInt32(at: 3) - let messageDate = min(minMessageDate, chatMessageDate) - - let messageLifetime = loadLegacyPeerCustomProperyInt32(database: database, peerId: conversationId, key: .string("messageLifetime")) ?? 0 - - let state: SecretChatState - var seqOut: Int32? - - switch secretChatData.handshakeState { - case 1: //requested - guard let a = loadLegacyPeerCustomProperyData(database: database, peerId: conversationId, key: .string("a")), !a.isEmpty else { - return false - } - state = SecretChatState(role: .creator, embeddedState: .handshake(.requested(g: 3, p: MemoryBuffer(data: defaultPrime), a: MemoryBuffer(data: a))), keychain: SecretChatKeychain(keys: []), keyFingerprint: nil, messageAutoremoveTimeout: nil) - case 2: //accepting - return false - case 3: //terminated - state = SecretChatState(role: .creator, embeddedState: .terminated, keychain: SecretChatKeychain(keys: []), keyFingerprint: nil, messageAutoremoveTimeout: nil) - case 4: - guard let sha1Fingerprint = loadLegacyPeerCustomProperyData(database: database, peerId: conversationId, key: .string("encryptionKeySha1")) else { - return false - } - guard let sha256Fingerprint = loadLegacyPeerCustomProperyData(database: database, peerId: conversationId, key: .string("encryptionKeySha256")) else { - return false - } - - guard let keysData = loadLegacyPeerCustomProperyData(database: database, peerId: conversationId, key: .string("encryptionKeys")) else { - return false - } - guard let keysArray = NSKeyedUnarchiver.unarchiveObject(with: keysData) as? [TGEncryptionKeyData] else { - return false - } - let parsedKeys: [SecretChatKey] = keysArray.map({ key in - return SecretChatKey(fingerprint: key.keyId, key: MemoryBuffer(data: key.key), validity: .sequenceBasedIndexRange(fromCanonicalIndex: key.firstSeqOut), useCount: 1) - }) - let requestedLayerValue = loadLegacyPeerCustomProperyInt32(database: database, peerId: conversationId, key: .hash(reportedLayer_hash)) ?? 0 - let appliedSeqInValue = loadLegacyPeerCustomProperyInt32(database: database, peerId: conversationId, key: .hash(seq_in_hash)) ?? 0 - guard let seqOutValue = loadLegacyPeerCustomProperyInt32(database: database, peerId: conversationId, key: .hash(seq_out_hash)) else { - return false - } - seqOut = seqOutValue - guard let activeLayerValue = loadLegacyPeerCustomProperyInt32(database: database, peerId: conversationId, key: .hash(layer_hash)) else { - return false - } - guard let activeLayer = SecretChatSequenceBasedLayer(rawValue: activeLayerValue) else { - return false - } - let rekeyState: SecretChatRekeySessionState? = secretChatData.rekeyState - let embeddedState: SecretChatEmbeddedState = .sequenceBasedLayer(SecretChatSequenceBasedLayerState(layerNegotiationState: SecretChatLayerNegotiationState(activeLayer: activeLayer, locallyRequestedLayer: requestedLayerValue == 0 ? nil : requestedLayerValue, remotelyRequestedLayer: nil), rekeyState: rekeyState, baseIncomingOperationIndex: 0, baseOutgoingOperationIndex: 0, topProcessedCanonicalIncomingOperationIndex: appliedSeqInValue == 0 ? nil : max(0, appliedSeqInValue - 1))) - state = SecretChatState(role: role, embeddedState: embeddedState, keychain: SecretChatKeychain(keys: parsedKeys), keyFingerprint: SecretChatKeyFingerprint(sha1: SecretChatKeySha1Fingerprint(digest: sha1Fingerprint), sha256: SecretChatKeySha256Fingerprint(digest: sha256Fingerprint)), messageAutoremoveTimeout: messageLifetime == 0 ? nil : messageLifetime) - default: - return false - } - - let secretChat = TelegramSecretChat(id: peerId, creationDate: messageDate, regularPeerId: userPeerId, accessHash: secretChatData.accessHash, role: role, embeddedState: state.embeddedState.peerState, messageAutoremoveTimeout: messageLifetime == 0 ? nil : messageLifetime) - - chatInfos.append((secretChat, state, seqOut, readStates, conversationId)) - - return false - }) - } - var userPeers: [PeerId: Peer] = [:] - var presences: [PeerId: PeerPresence] = [:] - for info in chatInfos { - if let (peer, presence) = loadLegacyUser(database: database, id: info.0.regularPeerId.id) { - userPeers[peer.id] = peer - presences[peer.id] = presence - } - } - - let storedChats = account.postbox.transaction { transaction -> Void in - updatePeers(transaction: transaction, peers: Array(userPeers.values), update: { _, updated in - return updated - }) - transaction.updatePeerPresencesInternal(presences: presences, merge: { _, updated in return updated }) - for (peer, state, seqOutValue, readStates, _) in chatInfos { - if userPeers[peer.regularPeerId] == nil { - continue - } - updatePeers(transaction: transaction, peers: [peer], update: { _, updated in - return updated - }) - transaction.setPeerChatState(peer.id, state: state) - switch state.embeddedState { - case .sequenceBasedLayer: - if let seqOutValue = seqOutValue { - transaction.operationLogResetIndices(peerId: peer.id, tag: OperationLogTags.SecretOutgoing, nextTagLocalIndex: seqOutValue + 1) - } - default: - break - } - transaction.resetIncomingReadStates([peer.id: readStates]) - } - } - |> ignoreValues - - let _ = registeredAttachmentParsers - - var countByConversationId: [Int64: Int32] = [:] - var totalCount: Int32 = 0 - - for info in chatInfos { - database.select("SELECT COUNT(*) FROM messages_v29 WHERE cid=\(info.4)", { cursor in - let count = cursor.getInt32(at: 0) - countByConversationId[info.4] = count - totalCount += count - return true - }) - } - - var storedMessagesSignals: Signal = .single(0.0) - var cumulativeCount: Int32 = 0 - for info in chatInfos { - let localBaseline = cumulativeCount - let localCount = countByConversationId[info.4] ?? 0 - storedMessagesSignals = storedMessagesSignals - |> then( - loadLegacyMessages(account: account, basePath: basePath, accountPeerId: accountPeerId, peerId: info.0.id, userPeerId: info.0.regularPeerId, database: database, conversationId: info.4, expectedTotalCount: localCount) - |> map { localProgress -> Float in - if totalCount <= 0 { - return 0.0 - } - let globalCount = localBaseline + Int32(localProgress * Float(localCount)) - return Float(globalCount) / Float(totalCount) - } - ) - cumulativeCount += countByConversationId[info.4] ?? 0 - } - - return storedChats - |> map { _ -> Float in return 0.0 } - |> then(storedMessagesSignals) - } -} diff --git a/submodules/LegacyDataImport/Sources/LegacyDataImport.swift b/submodules/LegacyDataImport/Sources/LegacyDataImport.swift deleted file mode 100644 index 4676e4b16a..0000000000 --- a/submodules/LegacyDataImport/Sources/LegacyDataImport.swift +++ /dev/null @@ -1,245 +0,0 @@ -import Foundation -import UIKit -import TelegramCore -import SyncCore -import SwiftSignalKit -import Postbox -import MtProtoKit -import LegacyDataImportImpl - -public enum AccountImportError: Error { - case generic -} - -public enum AccountImportProgressType { - case generic - case messages - case media -} - -private func importedAccountData(basePath: String, documentsPath: String, accountManager: AccountManager, account: TemporaryAccount, database: SqliteInterface) -> Signal<(AccountImportProgressType, Float), AccountImportError> { - return deferred { () -> Signal<(AccountImportProgressType, Float), AccountImportError> in - let keychain = MTFileBasedKeychain(name: "Telegram", documentsPath: documentsPath) - guard let masterDatacenterId = keychain.object(forKey: "defaultDatacenterId", group: "persistent") as? Int else { - return .fail(.generic) - } - let keychainContents = keychain.contents(forGroup: "persistent") - - let importKeychain = account.postbox.transaction { transaction -> Void in - for (key, value) in keychainContents { - let data = NSKeyedArchiver.archivedData(withRootObject: value) - transaction.setKeychainEntry(data, forKey: "persistent" + ":" + key) - } - } - |> ignoreValues - |> castError(AccountImportError.self) - - let importData = importPreferencesData(documentsPath: documentsPath, masterDatacenterId: Int32(masterDatacenterId), account: account, database: database) - |> mapToSignal { accountUserId -> Signal<(AccountImportProgressType, Float), AccountImportError> in - return importDatabaseData(accountManager: accountManager, account: account, basePath: basePath, database: database, accountUserId: accountUserId) - } - - return importKeychain - |> map { _ -> (AccountImportProgressType, Float) in return (.generic, 0.0) } - |> then(importData) - } -} - -private func importPreferencesData(documentsPath: String, masterDatacenterId: Int32, account: TemporaryAccount, database: SqliteInterface) -> Signal { - return deferred { () -> Signal in - let defaultsPath = documentsPath + "/standard.defaults" - var parsedAccountUserId: Int32? - if let data = try? Data(contentsOf: URL(fileURLWithPath: defaultsPath)), let dict = NSKeyedUnarchiver.unarchiveObject(with: data) as? [String: Any], let id = dict["telegraphUserId"] as? Int { - parsedAccountUserId = Int32(id) - } - if parsedAccountUserId == nil { - if let id = UserDefaults.standard.object(forKey: "telegraphUserId") as? Int { - parsedAccountUserId = Int32(id) - } - } - - if let parsedAccountUserId = parsedAccountUserId { - return account.postbox.transaction { transaction -> Int32 in - transaction.setState(AuthorizedAccountState(isTestingEnvironment: false, masterDatacenterId: masterDatacenterId, peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: parsedAccountUserId), state: nil)) - return parsedAccountUserId - } - |> castError(AccountImportError.self) - } else { - return .fail(.generic) - } - } -} - -private func importDatabaseData(accountManager: AccountManager, account: TemporaryAccount, basePath: String, database: SqliteInterface, accountUserId: Int32) -> Signal<(AccountImportProgressType, Float), AccountImportError> { - return deferred { () -> Signal<(AccountImportProgressType, Float), AccountImportError> in - var importedAccountUser: Signal = .complete() - if let (user, presence) = loadLegacyUser(database: database, id: accountUserId) { - importedAccountUser = account.postbox.transaction { transaction -> Void in - updatePeers(transaction: transaction, peers: [user], update: { _, updated in updated }) - transaction.updatePeerPresencesInternal(presences: [user.id: presence], merge: { _, updated in return updated }) - } - |> ignoreValues - |> castError(AccountImportError.self) - } - - let importedSecretChats = loadLegacySecretChats(account: account, basePath: basePath, accountPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: accountUserId), database: database) - |> castError(AccountImportError.self) - - /*let importedFiles = loadLegacyFiles(account: account, basePath: basePath, accountPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: accountUserId), database: database) - |> castError(AccountImportError.self)*/ - - let importedLegacyPreferences = importLegacyPreferences(accountManager: accountManager, account: account, documentsPath: basePath + "/Documents", database: database) - |> castError(AccountImportError.self) - - return importedAccountUser - |> map { _ -> (AccountImportProgressType, Float) in return (.generic, 0.0) } - |> then( - importedLegacyPreferences - |> map { _ -> (AccountImportProgressType, Float) in return (.generic, 0.0) } - ) - |> then( - importedSecretChats - |> map { value -> (AccountImportProgressType, Float) in return (.messages, value) } - ) - } -} - -public enum ImportedLegacyAccountEvent { - case progress(AccountImportProgressType, Float) - case result(AccountRecordId?) -} - -public func importedLegacyAccount(basePath: String, accountManager: AccountManager, encryptionParameters: ValueBoxEncryptionParameters, present: @escaping (UIViewController) -> Void) -> Signal { - let queue = Queue() - return deferred { () -> Signal in - let documentsPath = basePath + "/Documents" - if FileManager.default.fileExists(atPath: documentsPath + "/importcompleted") { - return .single(.result(nil)) - } - - let unlockedDatabasePathAndKey: Signal<(String, Data?)?, AccountImportError> - if FileManager.default.fileExists(atPath: documentsPath + "/tgdata.db.y") { - let databasePath = documentsPath + "/tgdata.db.y" - let unlockDatabase = Signal<(String, Data?)?, AccountImportError> { subscriber in - let alertController = UIAlertController(title: nil, message: "Enter your passcode", preferredStyle: .alert) - - let confirmAction = UIAlertAction(title: "Enter", style: .default) { _ in - let passcode = alertController.textFields?[0].text - - func checkPasscode(_ value: String) -> Bool { - guard let database = SqliteInterface(databasePath: databasePath) else { - return false - } - let key = value.data(using: .utf8)! - if !database.unlock(password: hexString(key).data(using: .utf8)!) { - return false - } - - return true - } - - if checkPasscode(passcode ?? "") { - subscriber.putNext((databasePath, (passcode ?? "").data(using: .utf8)!)) - subscriber.putCompletion() - } else { - let alertController = UIAlertController(title: nil, message: "Invalid passcode. Please try again.", preferredStyle: .alert) - - let confirmAction = UIAlertAction(title: "OK", style: .default) { _ in - subscriber.putCompletion() - } - - alertController.addAction(confirmAction) - - present(alertController) - } - } - - let cancelAction = UIAlertAction(title: "Skip", style: .cancel) { _ in - subscriber.putNext(nil) - subscriber.putCompletion() - } - - alertController.addTextField { textField in - textField.placeholder = "Passcode" - } - - alertController.addAction(confirmAction) - alertController.addAction(cancelAction) - - present(alertController) - return EmptyDisposable - } - |> runOn(Queue.mainQueue()) - - unlockedDatabasePathAndKey = (unlockDatabase - |> mapToSignal { result -> Signal<(String, Data?)?, AccountImportError> in - if let result = result { - return .single(result) - } else { - let askAgain = Signal<(String, Data?)?, AccountImportError> { subscriber in - let alertController = UIAlertController(title: "Warning", message: "If you continue without entering your passcode, all your secret chats will be lost.", preferredStyle: .alert) - - let confirmAction = UIAlertAction(title: "Skip", style: .destructive) { _ in - subscriber.putError(.generic) - } - - let cancelAction = UIAlertAction(title: "Try Again", style: .cancel) { _ in - subscriber.putCompletion() - } - - alertController.addAction(confirmAction) - alertController.addAction(cancelAction) - - present(alertController) - return EmptyDisposable - } - |> runOn(Queue.mainQueue()) - return askAgain - } - }) - |> restart - |> take(1) - } else if FileManager.default.fileExists(atPath: documentsPath + "/tgdata.db") { - unlockedDatabasePathAndKey = .single((documentsPath + "/tgdata.db", nil)) - } else { - return .single(.result(nil)) - } - - return unlockedDatabasePathAndKey - |> mapToSignal { pathAndKey -> Signal in - guard let pathAndKey = pathAndKey else { - return .fail(.generic) - } - - guard let database = SqliteInterface(databasePath: pathAndKey.0) else { - return .fail(.generic) - } - - if let key = pathAndKey.1 { - if !database.unlock(password: hexString(key).data(using: .utf8)!) { - return .fail(.generic) - } - } - - return temporaryAccount(manager: accountManager, rootPath: rootPathForBasePath(basePath), encryptionParameters: encryptionParameters) - |> castError(AccountImportError.self) - |> mapToSignal { account -> Signal in - let actions = importedAccountData(basePath: basePath, documentsPath: documentsPath, accountManager: accountManager, account: account, database: database) - var result = actions - |> map { typeAndProgress -> ImportedLegacyAccountEvent in - return .progress(typeAndProgress.0, typeAndProgress.1) - } - #if DEBUG - //result = result - //|> then(.never()) - #endif - - result = result - |> then(.single(.result(account.id))) - - return result - } - } - } - |> runOn(queue) -} diff --git a/submodules/LegacyDataImport/Sources/LegacyDataImportSplash.swift b/submodules/LegacyDataImport/Sources/LegacyDataImportSplash.swift deleted file mode 100644 index f121307d0e..0000000000 --- a/submodules/LegacyDataImport/Sources/LegacyDataImportSplash.swift +++ /dev/null @@ -1,89 +0,0 @@ -import Foundation -import Display -import AsyncDisplayKit -import TelegramPresentationData -import RadialStatusNode - -public protocol LegacyDataImportSplash: WindowCoveringView { - var progress: (AccountImportProgressType, Float) { get set } - var serviceAction: (() -> Void)? { get set } -} - -private final class LegacyDataImportSplashImpl: WindowCoveringView, LegacyDataImportSplash { - private let theme: PresentationTheme? - private let strings: PresentationStrings? - - public var progress: (AccountImportProgressType, Float) = (.generic, 0.0) { - didSet { - if self.progress.0 != oldValue.0 { - if let size = self.validSize { - switch self.progress.0 { - case .generic: - self.textNode.attributedText = NSAttributedString(string: self.strings?.AppUpgrade_Running ?? "Optimizing...", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black) - case .media: - self.textNode.attributedText = NSAttributedString(string: "Optimizing cache", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black) - case .messages: - self.textNode.attributedText = NSAttributedString(string: "Optimizing database", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black) - } - self.updateLayout(size) - } - } - self.progressNode.transitionToState(.progress(color: self.theme?.list.itemAccentColor ?? UIColor(rgb: 0x007ee5), lineWidth: 2.0, value: CGFloat(max(0.025, self.progress.1)), cancelEnabled: false, animateRotation: true), animated: false, completion: {}) - } - } - - public var serviceAction: (() -> Void)? - - private let progressNode: RadialStatusNode - private let textNode: ImmediateTextNode - - private var validSize: CGSize? - - public init(theme: PresentationTheme?, strings: PresentationStrings?) { - self.theme = theme - self.strings = strings - - self.progressNode = RadialStatusNode(backgroundNodeColor: theme?.list.plainBackgroundColor ?? .white) - self.textNode = ImmediateTextNode() - self.textNode.maximumNumberOfLines = 0 - self.textNode.textAlignment = .center - self.textNode.attributedText = NSAttributedString(string: self.strings?.AppUpgrade_Running ?? "Optimizing...", font: Font.regular(17.0), textColor: self.theme?.list.itemPrimaryTextColor ?? .black) - - super.init(frame: CGRect()) - - self.backgroundColor = self.theme?.list.plainBackgroundColor ?? .white - - self.addSubnode(self.progressNode) - self.progressNode.isUserInteractionEnabled = false - self.addSubnode(self.textNode) - self.textNode.isUserInteractionEnabled = false - - self.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:)))) - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override public func updateLayout(_ size: CGSize) { - self.validSize = size - - let progressSize = CGSize(width: 60.0, height: 60.0) - - let textSize = self.textNode.updateLayout(CGSize(width: size.width - 20.0, height: .greatestFiniteMagnitude)) - - let progressFrame = CGRect(origin: CGPoint(x: floor((size.width - progressSize.width) / 2.0), y: floor((size.height - progressSize.height - 15.0 - textSize.height) / 2.0)), size: progressSize) - self.progressNode.frame = progressFrame - self.textNode.frame = CGRect(origin: CGPoint(x: floor((size.width - textSize.width) / 2.0), y: progressFrame.maxY + 15.0), size: textSize) - } - - @objc private func longPressGesture(_ recognizer: UILongPressGestureRecognizer) { - if case .began = recognizer.state { - self.serviceAction?() - } - } -} - -public func makeLegacyDataImportSplash(theme: PresentationTheme?, strings: PresentationStrings?) -> LegacyDataImportSplash { - return LegacyDataImportSplashImpl(theme: theme, strings: strings) -} diff --git a/submodules/LegacyDataImport/Sources/LegacyFileImport.swift b/submodules/LegacyDataImport/Sources/LegacyFileImport.swift deleted file mode 100644 index 56308641f2..0000000000 --- a/submodules/LegacyDataImport/Sources/LegacyFileImport.swift +++ /dev/null @@ -1,189 +0,0 @@ -import Foundation -import TelegramCore -import SyncCore -import SwiftSignalKit -import Postbox -import LegacyComponents - -private func importMediaFromMessageData(_ data: Data, basePath: String, copyLocalFiles: inout [(MediaResource, String)], cache: TGCache) { - if let message = TGMessage(keyValueCoder: PSKeyValueDecoder(data: data)) { - if let mediaAttachments = message.mediaAttachments { - importMediaFromMediaList(mediaAttachments, basePath: basePath, copyLocalFiles: ©LocalFiles, cache: cache) - } - } -} - -private func importMediaFromMediaData(_ data: Data, basePath: String, copyLocalFiles: inout [(MediaResource, String)], cache: TGCache) { - if let mediaAttachments = TGMessage.parseMediaAttachments(data) { - importMediaFromMediaList(mediaAttachments, basePath: basePath, copyLocalFiles: ©LocalFiles, cache: cache) - } -} - -private func importMediaFromMediaList(_ mediaAttachments: [Any], basePath: String, copyLocalFiles: inout [(MediaResource, String)], cache: TGCache) { - for media in mediaAttachments { - if let media = media as? TGDocumentMediaAttachment { - var fileName = "file" - if let itemAttributes = media.attributes { - for attribute in itemAttributes { - if let attribute = attribute as? TGDocumentAttributeFilename { - fileName = attribute.filename ?? "file" - } - } - } - - if media.documentId != 0 { - let filePath = pathFromLegacyFile(basePath: basePath, fileId: media.documentId, isLocal: false, fileName: TGDocumentMediaAttachment.safeFileName(forFileName: fileName) ?? "") - if FileManager.default.fileExists(atPath: filePath) { - copyLocalFiles.append((CloudDocumentMediaResource(datacenterId: Int(media.datacenterId), fileId: media.documentId, accessHash: media.accessHash, size: nil, fileReference: nil, fileName: nil), filePath)) - } - } - } else if let media = media as? TGVideoMediaAttachment { - if media.videoId != 0, let videoUrl = media.videoInfo?.url(withQuality: 1, actualQuality: nil, actualSize: nil) { - if let (id, accessHash, datacenterId, path) = pathFromLegacyVideoUrl(basePath: basePath, url: videoUrl) { - copyLocalFiles.append((CloudDocumentMediaResource(datacenterId: Int(datacenterId), fileId: id, accessHash: accessHash, size: nil, fileReference: nil, fileName: nil), path)) - } - } - } else if let media = media as? TGImageMediaAttachment { - if let allSizes = media.imageInfo?.allSizes() as? [String: NSValue] { - for (imageUrl, _) in allSizes { - if let path = cache.path(forCachedData: imageUrl), let resource = resourceFromLegacyImageUrl(imageUrl), FileManager.default.fileExists(atPath: path) { - copyLocalFiles.append((resource, path)) - } - } - } - } - } -} - -private func makeMessageSortKey(tag: Int32, conversationId: Int64, space: Int8, timestamp: Int32, messageId: Int32) -> Data { - let key = ValueBoxKey(length: 4 + 8 + 1 + 4 + 4) - key.setInt32(0, value: tag.byteSwapped) - key.setInt64(4, value: conversationId.byteSwapped) - key.setInt8(4 + 8, value: space) - key.setInt32(4 + 8 + 1, value: timestamp) - key.setInt32(4 + 8 + 1 + 4, value: messageId.byteSwapped) - return Data(bytes: key.memory, count: key.length) -} - -func loadLegacyFiles(account: TemporaryAccount, basePath: String, accountPeerId: PeerId, database: SqliteInterface) -> Signal { - return Signal { subscriber in - let _ = registeredAttachmentParsers - - subscriber.putNext(0.0) - - var channelIds: [Int64] = [] - database.select("SELECT DISTINCT cid FROM channel_message_tags_v29", { cursor in - channelIds.append(cursor.getInt64(at: 0)) - return true - }) - print(database.explain("SELECT DISTINCT cid FROM channel_message_tags_v29")) - - var channelMessageIds: [(Int64, Int32)] = [] - - print(database.explain("SELECT mid FROM channel_message_tags_v29 WHERE tag_sort_key<100 AND tag_sort_key>0 ORDER BY tag_sort_key DESC LIMIT 4000")) - - if !channelIds.isEmpty { - /* - TGSharedMediaCacheItemTypePhoto = 0, - TGSharedMediaCacheItemTypeVideo = 1, - TGSharedMediaCacheItemTypeFile = 2, - TGSharedMediaCacheItemTypePhotoVideo = 3, - TGSharedMediaCacheItemTypePhotoVideoFile = 4, - TGSharedMediaCacheItemTypeAudio = 5, - TGSharedMediaCacheItemTypeLink = 6, - TGSharedMediaCacheItemTypeSticker = 7, - TGSharedMediaCacheItemTypeGif = 8, - TGSharedMediaCacheItemTypeVoiceVideoMessage = 9 - */ - let tags: [Int32] = [ - 2, // File - 5, // Audio - 3, // PhotoVideo - ] - database.withStatement("SELECT mid FROM channel_message_tags_v29 WHERE tag_sort_key? ORDER BY tag_sort_key DESC LIMIT 4000", { select in - for channelId in channelIds { - for tag in tags { - select([.data(makeMessageSortKey(tag: tag, conversationId: channelId, space: 0, timestamp: Int32.max - 1, messageId: 0)), .data(makeMessageSortKey(tag: tag, conversationId: channelId, space: 0, timestamp: 0, messageId: 0))], { cursor in - channelMessageIds.append((channelId, cursor.getInt32(at: 0))) - return true - }) - select([.data(makeMessageSortKey(tag: tag, conversationId: channelId, space: 1, timestamp: Int32.max - 1, messageId: 0)), .data(makeMessageSortKey(tag: tag, conversationId: channelId, space: 1, timestamp: 0, messageId: 0))], { cursor in - channelMessageIds.append((channelId, cursor.getInt32(at: 0))) - return true - }) - } - } - }) - } - - var chatMessageIds: [Int32] = [] - let mediaTypes: [Int32] = [ - 1, // video - 2, // image - 3, // file - ] - for type in mediaTypes { - database.select("SELECT mids FROM media_cache_v29 WHERE media_type=\(type) ORDER BY date DESC LIMIT 32000", { cursor in - let midsData = cursor.getData(at: 0) - let reader = LegacyBufferReader(LegacyBuffer(data: midsData)) - while true { - if let mid = reader.readInt32() { - chatMessageIds.append(mid) - } else { - break - } - } - return true - }) - } - - var copyLocalFiles: [(MediaResource, String)] = [] - - let totalCount = channelMessageIds.count + chatMessageIds.count - let reportBase = max(1, totalCount / 100) - - var itemIndex = -1 - - let cache = TGCache(cachesPath: basePath + "/Caches")! - - if !channelMessageIds.isEmpty { - database.withStatement("SELECT data FROM channel_messages_v29 WHERE cid=? AND mid=?", { select in - for (peerId, messageId) in channelMessageIds { - itemIndex += 1 - if itemIndex % reportBase == 0 { - subscriber.putNext(Float(itemIndex) / Float(totalCount)) - } - select([.int64(peerId), .int32(messageId)], { cursor in - let data = cursor.getData(at: 0) - importMediaFromMessageData(data, basePath: basePath, copyLocalFiles: ©LocalFiles, cache: cache) - return true - }) - } - }) - } - - if !chatMessageIds.isEmpty { - database.withStatement("SELECT media FROM messages_v29 WHERE mid=?", { select in - for messageId in chatMessageIds { - itemIndex += 1 - if itemIndex % reportBase == 0 { - subscriber.putNext(Float(itemIndex) / Float(totalCount)) - } - select([.int32(messageId)], { cursor in - let data = cursor.getData(at: 0) - importMediaFromMediaData(data, basePath: basePath, copyLocalFiles: ©LocalFiles, cache: cache) - return true - }) - } - }) - } - - for (resource, path) in copyLocalFiles { - account.postbox.mediaBox.copyResourceData(resource.id, fromTempPath: path) - } - - subscriber.putCompletion() - - return EmptyDisposable - } -} diff --git a/submodules/LegacyDataImport/Sources/LegacyPreferencesImport.swift b/submodules/LegacyDataImport/Sources/LegacyPreferencesImport.swift deleted file mode 100644 index 019bb540ac..0000000000 --- a/submodules/LegacyDataImport/Sources/LegacyPreferencesImport.swift +++ /dev/null @@ -1,438 +0,0 @@ -import Foundation -import UIKit -import TelegramCore -import SyncCore -import SwiftSignalKit -import MtProtoKit -import TelegramUIPreferences -import LegacyComponents -import TelegramNotices -import LegacyDataImportImpl - -@objc(TGPresentationState) private final class TGPresentationState: NSObject, NSCoding { - let pallete: Int32 - let userInfo: Int32 - let fontSize: Int32 - - init?(coder aDecoder: NSCoder) { - self.pallete = aDecoder.decodeInt32(forKey: "p") - self.userInfo = aDecoder.decodeInt32(forKey: "u") - self.fontSize = aDecoder.decodeInt32(forKey: "f") - } - - func encode(with aCoder: NSCoder) { - assertionFailure() - } -} - -private enum PreferencesProvider { - case dict([String: Any]) - case standard(UserDefaults) - - subscript(_ key: String) -> Any? { - get { - switch self { - case let .dict(dict): - return dict[key] - case let .standard(standard): - return standard.object(forKey: key) - } - } - } -} - -private func loadLegacyCustomProperyData(database: SqliteInterface, key: String) -> Data? { - var result: Data? - database.select("SELECT value FROM service_v29 WHERE key=\(HashFunctions.murMurHash32(key))", { cursor in - result = cursor.getData(at: 0) - return false - }) - return result -} - -private func convertLegacyProxyPort(_ value: Int) -> Int32 { - if value < 0 { - return Int32(UInt16(bitPattern: Int16(clamping: value))) - } else { - return Int32(clamping: value) - } -} - -func importLegacyPreferences(accountManager: AccountManager, account: TemporaryAccount, documentsPath: String, database: SqliteInterface) -> Signal { - return deferred { () -> Signal in - var presentationState: TGPresentationState? - if let value = NSKeyedUnarchiver.unarchiveObject(withFile: documentsPath + "/presentation.dat") as? TGPresentationState { - presentationState = value - } - - var autoNightPreferences: TGPresentationAutoNightPreferences? - if let value = NSKeyedUnarchiver.unarchiveObject(withFile: documentsPath + "/autonight.dat") as? TGPresentationAutoNightPreferences { - autoNightPreferences = value - } - - let autoDownloadPreferences: TGAutoDownloadPreferences? = NSKeyedUnarchiver.unarchiveObject(withFile: documentsPath + "/autoDownload.pref") as? TGAutoDownloadPreferences - - let preferencesProvider: PreferencesProvider - let defaultsPath = documentsPath + "/standard.defaults" - - let standardPreferences = PreferencesProvider.standard(UserDefaults.standard) - if let data = try? Data(contentsOf: URL(fileURLWithPath: defaultsPath)), let dict = NSKeyedUnarchiver.unarchiveObject(with: data) as? [String: Any] { - preferencesProvider = .dict(dict) - } else { - preferencesProvider = standardPreferences - } - - var showCallsTab: Bool? - if let data = try? Data(contentsOf: URL(fileURLWithPath: documentsPath + "/enablecalls.tab")), !data.isEmpty { - showCallsTab = data.withUnsafeBytes { (bytes: UnsafePointer) -> Bool in - return bytes.pointee != 0 - } - } - - let parsedAutoplayGifs: Bool? = preferencesProvider["autoPlayAnimations"] as? Bool - let soundEnabled: Bool? = preferencesProvider["soundEnabled"] as? Bool - let vibrationEnabled: Bool? = preferencesProvider["vibrationEnabled"] as? Bool - let bannerEnabled: Bool? = preferencesProvider["bannerEnabled"] as? Bool - let callsDataUsageMode: Int? = preferencesProvider["callsDataUsageMode"] as? Int - let callsDisableCallKit: Bool? = preferencesProvider["callsDisableCallKit"] as? Bool - let callsUseProxy: Bool? = preferencesProvider["callsUseProxy"] as? Bool - let contactsInhibitSync: Bool? = preferencesProvider["contactsInhibitSync"] as? Bool - let stickersSuggestMode: Int? = preferencesProvider["stickersSuggestMode"] as? Int - - let allowSecretWebpages: Bool? = preferencesProvider["allowSecretWebpages"] as? Bool - let allowSecretWebpagesInitialized: Bool? = preferencesProvider["allowSecretWebpagesInitialized"] as? Bool - let secretInlineBotsInitialized: Bool? = preferencesProvider["secretInlineBotsInitialized"] as? Bool - - let musicPlayerOrderType: Int? = standardPreferences["musicPlayerOrderType_v1"] as? Int - let musicPlayerRepeatType: Int? = standardPreferences["musicPlayerRepeatType_v1"] as? Int - - let instantPageFontSize: Float? = standardPreferences["instantPage_fontMultiplier_v0"] as? Float - let instantPageFontSerif: Int? = standardPreferences["instantPage_fontSerif_v0"] as? Int - let instantPageTheme: Int? = standardPreferences["instantPage_theme_v0"] as? Int - let instantPageAutoNightMode: Int? = standardPreferences["instantPage_autoNightTheme_v0"] as? Int - - let proxyList = NSKeyedUnarchiver.unarchiveObject(withFile: documentsPath + "/proxies.data") as? [TGProxyItem] - var selectedProxy: (ProxyServerSettings, Bool)? - if let data = loadLegacyCustomProperyData(database: database, key: "socksProxyData"), let dict = NSKeyedUnarchiver.unarchiveObject(with: data) as? [String: Any], let host = dict["ip"] as? String, let port = dict["port"] as? Int { - let inactive = (dict["inactive"] as? Bool) ?? true - var connection: ProxyServerConnection? - if let secretString = dict["secret"] as? String { - let secret = MTProxySecret.parse(secretString) - if let secret = secret { - connection = .mtp(secret: secret.serialize()) - } - } else { - connection = .socks5(username: (dict["username"] as? String) ?? "", password: (dict["password"] as? String) ?? "") - } - if let connection = connection { - selectedProxy = (ProxyServerSettings(host: host, port: convertLegacyProxyPort(port), connection: connection), !inactive) - } - } - - var passcodeChallenge: PostboxAccessChallengeData? - if let data = try? Data(contentsOf: URL(fileURLWithPath: documentsPath + "/x.y")) { - let reader = LegacyBufferReader(LegacyBuffer(data: data)) - if let mode = reader.readBytesAsInt32(1), let length = reader.readInt32(), let passwordData = reader.readBuffer(Int(length))?.makeData(), let passwordText = String(data: passwordData, encoding: .utf8) { - var lockTimeout: Int32? - if let value = UserDefaults.standard.object(forKey: "Passcode_lockTimeout") as? Int { - if value == 0 { - lockTimeout = nil - } else { - lockTimeout = max(60, Int32(clamping: value)) - } - } else { - lockTimeout = 1 * 60 * 60 - } - - if mode == 3 { - passcodeChallenge = .numericalPassword(value: passwordText) - } else if mode == 4 { - passcodeChallenge = PostboxAccessChallengeData.plaintextPassword(value: passwordText) - } - } - } - - var passcodeEnableBiometrics: Bool = true - if let value = UserDefaults.standard.object(forKey: "Passcode_useTouchId") as? Bool { - passcodeEnableBiometrics = value - } - - var localization: TGLocalization? - if let nativeDocumentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first { - localization = NSKeyedUnarchiver.unarchiveObject(withFile: nativeDocumentsPath + "/localization") as? TGLocalization - } - - return accountManager.transaction { transaction -> Signal in - transaction.updateSharedData(ApplicationSpecificSharedDataKeys.presentationThemeSettings, { current in - var settings = (current as? PresentationThemeSettings) ?? PresentationThemeSettings.defaultSettings - if let presentationState = presentationState { - switch presentationState.pallete { - case 1: - settings.theme = .builtin(.day) - - if presentationState.userInfo != 0 { - //themeSpecificAccentColors: current.themeSpecificAccentColors - //settings.themeAccentColor = presentationState.userInfo - } - settings.themeSpecificChatWallpapers[settings.theme.index] = .color(0xffffff) - case 2: - settings.theme = .builtin(.night) - settings.themeSpecificChatWallpapers[settings.theme.index] = .color(0x000000) - case 3: - settings.theme = .builtin(.nightAccent) - settings.themeSpecificChatWallpapers[settings.theme.index] = .color(0x18222d) - default: - settings.theme = .builtin(.dayClassic) - settings.themeSpecificChatWallpapers[settings.theme.index] = .builtin(WallpaperSettings()) - } - let fontSizeMap: [Int32: PresentationFontSize] = [ - 14: .extraSmall, - 15: .small, - 16: .medium, - 17: .regular, - 19: .large, - 23: .extraLarge, - 26: .extraLargeX2 - ] - settings.fontSize = fontSizeMap[presentationState.fontSize] ?? .regular - - if presentationState.userInfo != 0 { - //themeSpecificAccentColors: current.themeSpecificAccentColors - //settings.themeAccentColor = presentationState.userInfo - } - } - - if let autoNightPreferences = autoNightPreferences { - let nightTheme: PresentationBuiltinThemeReference - switch autoNightPreferences.preferredPalette { - case 1: - nightTheme = .night - default: - nightTheme = .nightAccent - } - switch autoNightPreferences.mode { - case TGPresentationAutoNightModeSunsetSunrise: - settings.automaticThemeSwitchSetting = AutomaticThemeSwitchSetting(trigger: .timeBased(setting: .automatic(latitude: Double(autoNightPreferences.latitude), longitude: Double(autoNightPreferences.longitude), localizedName: autoNightPreferences.cachedLocationName)), theme: .builtin(nightTheme)) - case TGPresentationAutoNightModeScheduled: - settings.automaticThemeSwitchSetting = AutomaticThemeSwitchSetting(trigger: .timeBased(setting: .manual(fromSeconds: autoNightPreferences.scheduleStart, toSeconds: autoNightPreferences.scheduleEnd)), theme: .builtin(nightTheme)) - case TGPresentationAutoNightModeBrightness: - settings.automaticThemeSwitchSetting = AutomaticThemeSwitchSetting(trigger: .brightness(threshold: Double(autoNightPreferences.brightnessThreshold)), theme: .builtin(nightTheme)) - default: - break - } - } - - return settings - }) - - transaction.updateSharedData(ApplicationSpecificSharedDataKeys.automaticMediaDownloadSettings, { current in - var settings: MediaAutoDownloadSettings = current as? MediaAutoDownloadSettings ?? .defaultSettings - - if let preferences = autoDownloadPreferences, !preferences.isDefaultPreferences() { - settings.cellular.enabled = !preferences.disabled - settings.wifi.enabled = !preferences.disabled - } - - if let parsedAutoplayGifs = parsedAutoplayGifs { - settings.autoplayGifs = parsedAutoplayGifs - } - - return settings - }) - - transaction.updateSharedData(ApplicationSpecificSharedDataKeys.inAppNotificationSettings, { current in - var settings: InAppNotificationSettings = current as? InAppNotificationSettings ?? .defaultSettings - if let soundEnabled = soundEnabled { - settings.playSounds = soundEnabled - } - if let vibrationEnabled = vibrationEnabled { - settings.vibrate = vibrationEnabled - } - if let bannerEnabled = bannerEnabled { - settings.displayPreviews = bannerEnabled - } - return settings - }) - - transaction.updateSharedData(ApplicationSpecificSharedDataKeys.voiceCallSettings, { current in - var settings: VoiceCallSettings = current as? VoiceCallSettings ?? .defaultSettings - if let callsDataUsageMode = callsDataUsageMode { - switch callsDataUsageMode { - case 1: - settings.dataSaving = .cellular - case 2: - settings.dataSaving = .always - default: - settings.dataSaving = .never - } - } - if let callsDisableCallKit = callsDisableCallKit, callsDisableCallKit { - settings.enableSystemIntegration = false - } - return settings - }) - - transaction.updateSharedData(ApplicationSpecificSharedDataKeys.callListSettings, { current in - var settings: CallListSettings = current as? CallListSettings ?? .defaultSettings - if let showCallsTab = showCallsTab { - settings.showTab = showCallsTab - } - return settings - }) - - transaction.updateSharedData(ApplicationSpecificSharedDataKeys.presentationPasscodeSettings, { current in - var settings: PresentationPasscodeSettings = current as? PresentationPasscodeSettings ?? .defaultSettings - if let passcodeChallenge = passcodeChallenge { - transaction.setAccessChallengeData(passcodeChallenge) - settings.enableBiometrics = passcodeEnableBiometrics - } - return settings - }) - - transaction.updateSharedData(ApplicationSpecificSharedDataKeys.stickerSettings, { current in - var settings: StickerSettings = current as? StickerSettings ?? .defaultSettings - if let stickersSuggestMode = stickersSuggestMode { - switch stickersSuggestMode { - case 1: - settings.emojiStickerSuggestionMode = .installed - case 2: - settings.emojiStickerSuggestionMode = .none - default: - settings.emojiStickerSuggestionMode = .all - } - } - return settings - }) - - transaction.updateSharedData(ApplicationSpecificSharedDataKeys.musicPlaybackSettings, { current in - var settings: MusicPlaybackSettings = current as? MusicPlaybackSettings ?? .defaultSettings - if let musicPlayerOrderType = musicPlayerOrderType { - switch musicPlayerOrderType { - case 1: - settings.order = .reversed - case 2: - settings.order = .random - default: - settings.order = .regular - } - } - if let musicPlayerRepeatType = musicPlayerRepeatType { - switch musicPlayerRepeatType { - case 1: - settings.looping = .all - case 2: - settings.looping = .item - default: - settings.looping = .none - } - } - return settings - }) - - transaction.updateSharedData(ApplicationSpecificSharedDataKeys.instantPagePresentationSettings, { current in - let settings: InstantPagePresentationSettings = current as? InstantPagePresentationSettings ?? .defaultSettings - if let instantPageFontSize = instantPageFontSize { - switch instantPageFontSize { - case 0.85: - settings.fontSize = .small - case 1.15: - settings.fontSize = .large - case 1.30: - settings.fontSize = .xlarge - case 1.50: - settings.fontSize = .xxlarge - default: - settings.fontSize = .standard - } - } - if let instantPageFontSerif = instantPageFontSerif { - settings.forceSerif = instantPageFontSerif == 1 - } - if let instantPageTheme = instantPageTheme { - switch instantPageTheme { - case 1: - settings.themeType = .sepia - case 2: - settings.themeType = .gray - case 3: - settings.themeType = .dark - default: - settings.themeType = .light - } - } - if let instantPageAutoNightMode = instantPageAutoNightMode { - settings.autoNightMode = instantPageAutoNightMode == 1 - } - return settings - }) - - if let localization = localization { - transaction.updateSharedData(SharedDataKeys.localizationSettings, { _ in - var entries: [LocalizationEntry] = [] - for (key, value) in localization.dict() { - entries.append(LocalizationEntry.string(key: key, value: value)) - } - return LocalizationSettings(primaryComponent: LocalizationComponent(languageCode: localization.code, localizedName: "", localization: Localization(version: 0, entries: entries), customPluralizationCode: nil), secondaryComponent: nil) - }) - } - - transaction.updateSharedData(SharedDataKeys.proxySettings, { current in - var settings: ProxySettings = current as? ProxySettings ?? .defaultSettings - if let callsUseProxy = callsUseProxy { - settings.useForCalls = callsUseProxy - } - - if let proxyList = proxyList { - for item in proxyList { - let connection: ProxyServerConnection? - if item.isMTProxy, let secret = item.secret { - let parsedSecret = MTProxySecret.parse(secret) - if let parsedSecret = parsedSecret { - connection = .mtp(secret: parsedSecret.serialize()) - } else { - connection = nil - } - } else if !item.isMTProxy { - connection = .socks5(username: item.username ?? "", password: item.password ?? "") - } else { - connection = nil - } - if let connection = connection { - settings.servers.append(ProxyServerSettings(host: item.server, port: convertLegacyProxyPort(Int(item.port)), connection: connection)) - } - } - } - - if let (server, active) = selectedProxy { - if !settings.servers.contains(server) { - settings.servers.insert(server, at: 0) - } - settings.activeServer = server - settings.enabled = active - } - - return settings - }) - - if let secretInlineBotsInitialized = secretInlineBotsInitialized, secretInlineBotsInitialized { - ApplicationSpecificNotice.setSecretChatInlineBotUsage(transaction: transaction) - } - - if let allowSecretWebpagesInitialized = allowSecretWebpagesInitialized, allowSecretWebpagesInitialized, let allowSecretWebpages = allowSecretWebpages { - ApplicationSpecificNotice.setSecretChatLinkPreviews(transaction: transaction, value: allowSecretWebpages) - } - - return account.postbox.transaction { transaction -> Void in - transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { current in - var settings = current as? ContactsSettings ?? ContactsSettings.defaultSettings - if let contactsInhibitSync = contactsInhibitSync, contactsInhibitSync { - settings.synchronizeContacts = false - } - return settings - }) - } - } - |> switchToLatest - |> ignoreValues - } -} diff --git a/submodules/LegacyDataImport/Sources/LegacyResourceImport.swift b/submodules/LegacyDataImport/Sources/LegacyResourceImport.swift deleted file mode 100644 index 4fc129c16f..0000000000 --- a/submodules/LegacyDataImport/Sources/LegacyResourceImport.swift +++ /dev/null @@ -1,137 +0,0 @@ -import Foundation -import TelegramCore -import SyncCore -import SwiftSignalKit -import LegacyComponents - -func resourceFromLegacyImageUrl(_ fileRef: String) -> TelegramMediaResource? { - if fileRef.isEmpty { - return nil - } - let components = fileRef.components(separatedBy: "_") - if components.count != 4 { - return nil - } - - guard let datacenterId = Int32(components[0]) else { - return nil - } - guard let volumeId = Int64(components[1]) else { - return nil - } - guard let localId = Int32(components[2]) else { - return nil - } - guard let secret = Int64(components[3]) else { - return nil - } - - return CloudFileMediaResource(datacenterId: Int(datacenterId), volumeId: volumeId, localId: localId, secret: secret, size: nil, fileReference: nil) -} - -func pathFromLegacyImageUrl(basePath: String, url: String) -> String { - let cache = TGCache(cachesPath: basePath + "/Caches")! - return cache.path(forCachedData: url) -} - -func pathFromLegacyVideoUrl(basePath: String, url: String) -> (id: Int64, accessHash: Int64, datacenterId: Int32, path: String)? { - if !url.hasPrefix("video:") { - return nil - } - //[videoInfo addVideoWithQuality:1 url:[[NSString alloc] initWithFormat:@"video:%lld:%lld:%d:%d", videoMedia.videoId, videoMedia.accessHash, concreteResult.document.datacenterId, concreteResult.document.size] size:concreteResult.document.size]; - let components = url.components(separatedBy: ":") - if components.count != 5 { - return nil - } - guard let videoId = Int64(components[1]) else { - return nil - } - guard let accessHash = Int64(components[2]) else { - return nil - } - guard let datacenterId = Int32(components[3]) else { - return nil - } - let documentsPath = basePath + "/Documents" - let videoPath = documentsPath + "/video/remote\(String(videoId, radix: 16)).mov" - return (videoId, accessHash, datacenterId, videoPath) -} - -func pathFromLegacyLocalVideoUrl(basePath: String, url: String) -> String? { - let documentsPath = basePath + "/Documents" - if !url.hasPrefix("local-video:") { - return nil - } - let videoPath = documentsPath + "/video/" + String(url[url.index(url.startIndex, offsetBy: "local-video:".count)...]) - return videoPath -} - -func pathFromLegacyFile(basePath: String, fileId: Int64, isLocal: Bool, fileName: String) -> String { - let documentsPath = basePath + "/Documents" - let filePath = documentsPath + "/files/" + (isLocal ? "local" : "") + "\(String(fileId, radix: 16))/\(fileName)" - return filePath -} - -enum EncryptedFileType { - case image - case video - case document(fileName: String) - case audio -} - -func pathAndResourceFromEncryptedFileUrl(basePath: String, url: String, type: EncryptedFileType) -> (String, TelegramMediaResource)? { - let cache = TGCache(cachesPath: basePath + "/Caches")! - - if url.hasPrefix("encryptedThumbnail:") { - let path = cache.path(forCachedData: url)! - return (path, LocalFileMediaResource(fileId: arc4random64())) - } - - if !url.hasPrefix("mt-encrypted-file://?") { - return nil - } - guard let dict = TGStringUtils.argumentDictionary(inUrlString: String(url[url.index(url.startIndex, offsetBy: "mt-encrypted-file://?".count)...])) else { - return nil - } - guard let idString = dict["id"] as? String, let id = Int64(idString) else { - return nil - } - guard let datacenterIdString = dict["dc"] as? String, let datacenterId = Int32(datacenterIdString) else { - return nil - } - guard let accessHashString = dict["accessHash"] as? String, let accessHash = Int64(accessHashString) else { - return nil - } - guard let sizeString = dict["size"] as? String, let size = Int32(sizeString) else { - return nil - } - guard let decryptedSizeString = dict["decryptedSize"] as? String, let decryptedSize = Int32(decryptedSizeString) else { - return nil - } - guard let keyFingerprintString = dict["fingerprint"] as? String, let _ = Int32(keyFingerprintString) else { - return nil - } - guard let keyString = dict["key"] as? String else { - return nil - } - let keyData = dataWithHexString(keyString) - guard keyData.count == 64 else { - return nil - } - - let resource = SecretFileMediaResource(fileId: id, accessHash: accessHash, containerSize: size, decryptedSize: decryptedSize, datacenterId: Int(datacenterId), key: SecretFileEncryptionKey(aesKey: keyData.subdata(in: 0 ..< 32), aesIv: keyData.subdata(in: 32 ..< 64))) - - let filePath: String - switch type { - case .video: - filePath = basePath + "Documents/video/remote\(String(id, radix: 16)).mov" - case .image: - filePath = cache.path(forCachedData: url) - case let .document(fileName): - filePath = basePath + "Documents/files/\(String(id, radix: 16))/\(TGDocumentMediaAttachment.safeFileName(forFileName: fileName)!)" - case .audio: - filePath = basePath + "Documents/audio/\(String(id, radix: 16))" - } - - return (filePath, resource) -} diff --git a/submodules/LegacyDataImport/Sources/LegacyUserDataImport.swift b/submodules/LegacyDataImport/Sources/LegacyUserDataImport.swift deleted file mode 100644 index 79c198549d..0000000000 --- a/submodules/LegacyDataImport/Sources/LegacyUserDataImport.swift +++ /dev/null @@ -1,47 +0,0 @@ -import Foundation -import UIKit -import TelegramCore -import SyncCore -import SwiftSignalKit - -func loadLegacyUser(database: SqliteInterface, id: Int32) -> (TelegramUser, TelegramUserPresence)? { - var result: (TelegramUser, TelegramUserPresence)? - database.select("SELECT uid, first_name, last_name, phone_number, access_hash, photo_small, photo_big, last_seen, username FROM users_v29 WHERE uid=\(id)", { cursor in - let accessHash = cursor.getInt64(at: 4) - let firstName = cursor.getString(at: 1) - let lastName = cursor.getString(at: 2) - let username = cursor.getString(at: 8) - let phone = cursor.getString(at: 3) - - let photoSmall = cursor.getString(at: 5) - let photoBig = cursor.getString(at: 6) - var photo: [TelegramMediaImageRepresentation] = [] - if let resource = resourceFromLegacyImageUrl(photoSmall) { - photo.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 80, height: 80), resource: resource, progressiveSizes: [])) - } - if let resource = resourceFromLegacyImageUrl(photoBig) { - photo.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 600, height: 600), resource: resource, progressiveSizes: [])) - } - - let user = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: cursor.getInt32(at: 0)), accessHash: accessHash == 0 ? nil : .personal(accessHash), firstName: firstName.isEmpty ? nil : firstName, lastName: lastName.isEmpty ? nil : lastName, username: username.isEmpty ? nil : username, phone: phone.isEmpty ? nil : phone, photo: photo, botInfo: nil, restrictionInfo: nil, flags: []) - - let status: UserPresenceStatus - let lastSeen = cursor.getInt32(at: 7) - if lastSeen == -2 { - status = .recently - } else if lastSeen == -3 { - status = .lastWeek - } else if lastSeen == -4 { - status = .lastMonth - } else if lastSeen <= 0 { - status = .none - } else { - status = .present(until: lastSeen) - } - - let presence = TelegramUserPresence(status: status, lastActivity: 0) - result = (user, presence) - return false - }) - return result -} diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift index a4ebc8517e..ed09858c52 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift @@ -361,48 +361,6 @@ public func legacyEnqueueGifMessage(account: Account, data: Data, correlationId: } |> runOn(Queue.concurrentDefaultQueue()) } -public func legacyEnqueueVideoMessage(account: Account, data: Data, correlationId: Int64? = nil) -> Signal { - return Signal { subscriber in - if let previewImage = UIImage(data: data) { - let dimensions = previewImage.size - var previewRepresentations: [TelegramMediaImageRepresentation] = [] - - let thumbnailSize = dimensions.aspectFitted(CGSize(width: 320.0, height: 320.0)) - let thumbnailImage = TGScaleImageToPixelSize(previewImage, thumbnailSize)! - if let thumbnailData = thumbnailImage.jpegData(compressionQuality: 0.4) { - let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max)) - account.postbox.mediaBox.storeResourceData(resource.id, data: thumbnailData) - previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(thumbnailSize), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)) - } - - var randomId: Int64 = 0 - arc4random_buf(&randomId, 8) - let tempFilePath = NSTemporaryDirectory() + "\(randomId).mp4" - - let _ = try? FileManager.default.removeItem(atPath: tempFilePath) - let _ = try? data.write(to: URL(fileURLWithPath: tempFilePath), options: [.atomic]) - - let resource = LocalFileGifMediaResource(randomId: Int64.random(in: Int64.min ... Int64.max), path: tempFilePath) - let fileName: String = "video.mp4" - - let finalDimensions = TGMediaVideoConverter.dimensions(for: dimensions, adjustments: nil, preset: TGMediaVideoConversionPresetAnimation) - - var fileAttributes: [TelegramMediaFileAttribute] = [] - fileAttributes.append(.Video(duration: 0.0, size: PixelDimensions(finalDimensions), flags: [.supportsStreaming], preloadSize: nil, coverTime: nil, videoCodec: nil)) - fileAttributes.append(.FileName(fileName: fileName)) - fileAttributes.append(.Animated) - - let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes, alternativeRepresentations: []) - subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])) - subscriber.putCompletion() - } else { - subscriber.putError(Void()) - } - - return EmptyDisposable - } |> runOn(Queue.concurrentDefaultQueue()) -} - public struct LegacyAssetPickerEnqueueMessage { public var message: EnqueueMessage public var uniqueId: String? diff --git a/submodules/ListMessageItem/Sources/ListMessageItem.swift b/submodules/ListMessageItem/Sources/ListMessageItem.swift index 3a764bd287..e02baf6996 100644 --- a/submodules/ListMessageItem/Sources/ListMessageItem.swift +++ b/submodules/ListMessageItem/Sources/ListMessageItem.swift @@ -4,34 +4,33 @@ import AsyncDisplayKit import Display import TelegramCore import SwiftSignalKit -import Postbox import TelegramPresentationData import AccountContext import TelegramUIPreferences import ItemListUI public final class ListMessageItemInteraction { - public let openMessage: (Message, ChatControllerInteractionOpenMessageMode) -> Bool - public let openMessageContextMenu: (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void - public let toggleMessagesSelection: ([MessageId], Bool) -> Void - public let toggleMediaPlayback: ((Message) -> Void)? - let openUrl: (String, Bool, Bool?, Message?) -> Void - let openInstantPage: (Message, ChatMessageItemAssociatedData?) -> Void - let longTap: (ChatControllerInteractionLongTapAction, Message?) -> Void - let getHiddenMedia: () -> [MessageId: [Media]] + public let openMessage: (EngineRawMessage, ChatControllerInteractionOpenMessageMode) -> Bool + public let openMessageContextMenu: (EngineRawMessage, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void + public let toggleMessagesSelection: ([EngineMessage.Id], Bool) -> Void + public let toggleMediaPlayback: ((EngineRawMessage) -> Void)? + let openUrl: (String, Bool, Bool?, EngineRawMessage?) -> Void + let openInstantPage: (EngineRawMessage, ChatMessageItemAssociatedData?) -> Void + let longTap: (ChatControllerInteractionLongTapAction, EngineRawMessage?) -> Void + let getHiddenMedia: () -> [EngineMessage.Id: [EngineRawMedia]] public var searchTextHighightState: String? public var preferredStoryHighQuality: Bool = false public init( - openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, - openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void, - toggleMediaPlayback: ((Message) -> Void)?, - toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, - openUrl: @escaping (String, Bool, Bool?, Message?) -> Void, - openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, - longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, - getHiddenMedia: @escaping () -> [MessageId: [Media]] + openMessage: @escaping (EngineRawMessage, ChatControllerInteractionOpenMessageMode) -> Bool, + openMessageContextMenu: @escaping (EngineRawMessage, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void, + toggleMediaPlayback: ((EngineRawMessage) -> Void)?, + toggleMessagesSelection: @escaping ([EngineMessage.Id], Bool) -> Void, + openUrl: @escaping (String, Bool, Bool?, EngineRawMessage?) -> Void, + openInstantPage: @escaping (EngineRawMessage, ChatMessageItemAssociatedData?) -> Void, + longTap: @escaping (ChatControllerInteractionLongTapAction, EngineRawMessage?) -> Void, + getHiddenMedia: @escaping () -> [EngineMessage.Id: [EngineRawMedia]] ) { self.openMessage = openMessage self.openMessageContextMenu = openMessageContextMenu @@ -51,7 +50,7 @@ public final class ListMessageItemInteraction { openUrl: { _, _, _, _ in }, openInstantPage: { _, _ in }, longTap: { _, _ in - }, getHiddenMedia: { () -> [MessageId : [Media]] in + }, getHiddenMedia: { () -> [EngineMessage.Id : [EngineRawMedia]] in return [:] }) } @@ -67,7 +66,7 @@ public final class ListMessageItem: ListViewItem, ItemListItem { let context: AccountContext let chatLocation: ChatLocation let interaction: ListMessageItemInteraction - let message: Message? + let message: EngineRawMessage? let translateToLanguage: String? public let selection: ChatHistoryMessageSelection public let selectionSide: ListMessageItemSelectionSide @@ -94,7 +93,7 @@ public final class ListMessageItem: ListViewItem, ItemListItem { context: AccountContext, chatLocation: ChatLocation, interaction: ListMessageItemInteraction, - message: Message?, + message: EngineRawMessage?, translateToLanguage: String? = nil, selection: ChatHistoryMessageSelection, selectionSide: ListMessageItemSelectionSide = .right, diff --git a/submodules/ListMessageItem/Sources/ListMessageNode.swift b/submodules/ListMessageItem/Sources/ListMessageNode.swift index 19d1b2ee17..625908c2f7 100644 --- a/submodules/ListMessageItem/Sources/ListMessageNode.swift +++ b/submodules/ListMessageItem/Sources/ListMessageNode.swift @@ -2,7 +2,7 @@ import Foundation import UIKit import Display import AsyncDisplayKit -import Postbox +import TelegramCore import AccountContext public class ListMessageNode: ListViewItemNode { @@ -28,7 +28,7 @@ public class ListMessageNode: ListViewItemNode { } } - public func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + public func transitionNode(id: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { return nil } diff --git a/submodules/LocalMediaResources/BUILD b/submodules/LocalMediaResources/BUILD index b0f3f832fe..cc0d5b719a 100644 --- a/submodules/LocalMediaResources/BUILD +++ b/submodules/LocalMediaResources/BUILD @@ -11,7 +11,6 @@ swift_library( ], deps = [ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/ImageCompression:ImageCompression", "//submodules/PersistentStringHash:PersistentStringHash", diff --git a/submodules/LocalMediaResources/Sources/MediaResources.swift b/submodules/LocalMediaResources/Sources/MediaResources.swift index 6e4d1490bf..9cf14404ee 100644 --- a/submodules/LocalMediaResources/Sources/MediaResources.swift +++ b/submodules/LocalMediaResources/Sources/MediaResources.swift @@ -1,27 +1,26 @@ import Foundation import UIKit -import Postbox import TelegramCore import PersistentStringHash -public final class VideoMediaResourceAdjustments: PostboxCoding, Equatable { - public let data: MemoryBuffer - public let digest: MemoryBuffer +public final class VideoMediaResourceAdjustments: EnginePostboxCoding, Equatable { + public let data: EngineMemoryBuffer + public let digest: EngineMemoryBuffer public let isStory: Bool - public init(data: MemoryBuffer, digest: MemoryBuffer, isStory: Bool = false) { + public init(data: EngineMemoryBuffer, digest: EngineMemoryBuffer, isStory: Bool = false) { self.data = data self.digest = digest self.isStory = isStory } - public init(decoder: PostboxDecoder) { + public init(decoder: EnginePostboxDecoder) { self.data = decoder.decodeBytesForKey("d")! self.digest = decoder.decodeBytesForKey("h")! self.isStory = decoder.decodeBoolForKey("s", orElse: false) } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeBytes(self.data, forKey: "d") encoder.encodeBytes(self.digest, forKey: "h") encoder.encodeBool(self.isStory, forKey: "s") @@ -34,7 +33,7 @@ public final class VideoMediaResourceAdjustments: PostboxCoding, Equatable { public struct VideoLibraryMediaResourceId { public let localIdentifier: String - public let adjustmentsDigest: MemoryBuffer? + public let adjustmentsDigest: EngineMemoryBuffer? public var uniqueId: String { if let adjustmentsDigest = self.adjustmentsDigest { @@ -49,11 +48,11 @@ public struct VideoLibraryMediaResourceId { } } -public enum VideoLibraryMediaResourceConversion: PostboxCoding, Equatable { +public enum VideoLibraryMediaResourceConversion: EnginePostboxCoding, Equatable { case passthrough case compress(VideoMediaResourceAdjustments?) - public init(decoder: PostboxDecoder) { + public init(decoder: EnginePostboxDecoder) { switch decoder.decodeInt32ForKey("v", orElse: 0) { case 0: self = .passthrough @@ -64,7 +63,7 @@ public enum VideoLibraryMediaResourceConversion: PostboxCoding, Equatable { } } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { switch self { case .passthrough: encoder.encodeInt32(0, forKey: "v") @@ -113,28 +112,28 @@ public final class VideoLibraryMediaResource: TelegramMediaResource { self.conversion = conversion } - public required init(decoder: PostboxDecoder) { + public required init(decoder: EnginePostboxDecoder) { self.localIdentifier = decoder.decodeStringForKey("i", orElse: "") self.conversion = (decoder.decodeObjectForKey("conv", decoder: { VideoLibraryMediaResourceConversion(decoder: $0) }) as? VideoLibraryMediaResourceConversion) ?? .compress(nil) } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeString(self.localIdentifier, forKey: "i") encoder.encodeObject(self.conversion, forKey: "conv") } - public var id: MediaResourceId { - var adjustmentsDigest: MemoryBuffer? + public var id: EngineRawMediaResourceId { + var adjustmentsDigest: EngineMemoryBuffer? switch self.conversion { case .passthrough: break case let .compress(adjustments): adjustmentsDigest = adjustments?.digest } - return MediaResourceId(VideoLibraryMediaResourceId(localIdentifier: self.localIdentifier, adjustmentsDigest: adjustmentsDigest).uniqueId) + return EngineRawMediaResourceId(VideoLibraryMediaResourceId(localIdentifier: self.localIdentifier, adjustmentsDigest: adjustmentsDigest).uniqueId) } - public func isEqual(to: MediaResource) -> Bool { + public func isEqual(to: EngineRawMediaResource) -> Bool { if let to = to as? VideoLibraryMediaResource { return self.localIdentifier == to.localIdentifier && self.conversion == to.conversion } else { @@ -180,7 +179,7 @@ public final class LocalFileVideoMediaResource: TelegramMediaResource { self.adjustments = adjustments } - public required init(decoder: PostboxDecoder) { + public required init(decoder: EnginePostboxDecoder) { self.randomId = decoder.decodeInt64ForKey("i", orElse: 0) let paths = decoder.decodeStringArrayForKey("ps") if !paths.isEmpty { @@ -191,7 +190,7 @@ public final class LocalFileVideoMediaResource: TelegramMediaResource { self.adjustments = decoder.decodeObjectForKey("a", decoder: { VideoMediaResourceAdjustments(decoder: $0) }) as? VideoMediaResourceAdjustments } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeInt64(self.randomId, forKey: "i") encoder.encodeStringArray(self.paths, forKey: "ps") if let adjustments = self.adjustments { @@ -201,11 +200,11 @@ public final class LocalFileVideoMediaResource: TelegramMediaResource { } } - public var id: MediaResourceId { - return MediaResourceId(LocalFileVideoMediaResourceId(randomId: self.randomId).uniqueId) + public var id: EngineRawMediaResourceId { + return EngineRawMediaResourceId(LocalFileVideoMediaResourceId(randomId: self.randomId).uniqueId) } - public func isEqual(to: MediaResource) -> Bool { + public func isEqual(to: EngineRawMediaResource) -> Bool { if let to = to as? LocalFileVideoMediaResource { return self.randomId == to.randomId && self.paths == to.paths && self.adjustments == to.adjustments } else { @@ -245,7 +244,7 @@ public final class LocalFileAudioMediaResource: TelegramMediaResource { self.trimRange = trimRange } - public required init(decoder: PostboxDecoder) { + public required init(decoder: EnginePostboxDecoder) { self.randomId = decoder.decodeInt64ForKey("i", orElse: 0) self.path = decoder.decodeStringForKey("p", orElse: "") @@ -256,7 +255,7 @@ public final class LocalFileAudioMediaResource: TelegramMediaResource { } } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeInt64(self.randomId, forKey: "i") encoder.encodeString(self.path, forKey: "p") @@ -269,11 +268,11 @@ public final class LocalFileAudioMediaResource: TelegramMediaResource { } } - public var id: MediaResourceId { - return MediaResourceId(LocalFileAudioMediaResourceId(randomId: self.randomId).uniqueId) + public var id: EngineRawMediaResourceId { + return EngineRawMediaResourceId(LocalFileAudioMediaResourceId(randomId: self.randomId).uniqueId) } - public func isEqual(to: MediaResource) -> Bool { + public func isEqual(to: EngineRawMediaResource) -> Bool { if let to = to as? LocalFileAudioMediaResource { return self.randomId == to.randomId && self.path == to.path && self.trimRange == to.trimRange } else { @@ -327,7 +326,7 @@ public class PhotoLibraryMediaResource: TelegramMediaResource { self.forceHd = forceHd } - public required init(decoder: PostboxDecoder) { + public required init(decoder: EnginePostboxDecoder) { self.localIdentifier = decoder.decodeStringForKey("i", orElse: "") self.uniqueId = decoder.decodeInt64ForKey("uid", orElse: 0) self.width = decoder.decodeOptionalInt32ForKey("w") @@ -337,7 +336,7 @@ public class PhotoLibraryMediaResource: TelegramMediaResource { self.forceHd = decoder.decodeBoolForKey("hd", orElse: false) } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeString(self.localIdentifier, forKey: "i") encoder.encodeInt64(self.uniqueId, forKey: "uid") if let width = self.width { @@ -363,11 +362,11 @@ public class PhotoLibraryMediaResource: TelegramMediaResource { encoder.encodeBool(self.forceHd, forKey: "hd") } - public var id: MediaResourceId { - return MediaResourceId(PhotoLibraryMediaResourceId(localIdentifier: self.localIdentifier, resourceId: self.uniqueId).uniqueId) + public var id: EngineRawMediaResourceId { + return EngineRawMediaResourceId(PhotoLibraryMediaResourceId(localIdentifier: self.localIdentifier, resourceId: self.uniqueId).uniqueId) } - public func isEqual(to: MediaResource) -> Bool { + public func isEqual(to: EngineRawMediaResource) -> Bool { if let to = to as? PhotoLibraryMediaResource { if self.localIdentifier != to.localIdentifier { return false @@ -426,21 +425,21 @@ public final class LocalFileGifMediaResource: TelegramMediaResource { self.path = path } - public required init(decoder: PostboxDecoder) { + public required init(decoder: EnginePostboxDecoder) { self.randomId = decoder.decodeInt64ForKey("i", orElse: 0) self.path = decoder.decodeStringForKey("p", orElse: "") } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeInt64(self.randomId, forKey: "i") encoder.encodeString(self.path, forKey: "p") } - public var id: MediaResourceId { - return MediaResourceId(LocalFileGifMediaResourceId(randomId: self.randomId).uniqueId) + public var id: EngineRawMediaResourceId { + return EngineRawMediaResourceId(LocalFileGifMediaResourceId(randomId: self.randomId).uniqueId) } - public func isEqual(to: MediaResource) -> Bool { + public func isEqual(to: EngineRawMediaResource) -> Bool { if let to = to as? LocalFileGifMediaResource { return self.randomId == to.randomId && self.path == to.path } else { @@ -475,21 +474,21 @@ public class BundleResource: TelegramMediaResource { self.path = path } - public required init(decoder: PostboxDecoder) { + public required init(decoder: EnginePostboxDecoder) { self.nameHash = decoder.decodeInt64ForKey("h", orElse: 0) self.path = decoder.decodeStringForKey("p", orElse: "") } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeInt64(self.nameHash, forKey: "h") encoder.encodeString(self.path, forKey: "p") } - public var id: MediaResourceId { - return MediaResourceId(BundleResourceId(nameHash: self.nameHash).uniqueId) + public var id: EngineRawMediaResourceId { + return EngineRawMediaResourceId(BundleResourceId(nameHash: self.nameHash).uniqueId) } - public func isEqual(to: MediaResource) -> Bool { + public func isEqual(to: EngineRawMediaResource) -> Bool { if let to = to as? BundleResource { return self.nameHash == to.nameHash } else { diff --git a/submodules/MediaResources/BUILD b/submodules/MediaResources/BUILD index 16e9f6ac37..5ce6f52464 100644 --- a/submodules/MediaResources/BUILD +++ b/submodules/MediaResources/BUILD @@ -11,7 +11,6 @@ swift_library( ], deps = [ "//submodules/TelegramCore:TelegramCore", - "//submodules/Postbox:Postbox", "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/TelegramUIPreferences:TelegramUIPreferences", ], diff --git a/submodules/MediaResources/Sources/CachedResourceRepresentations.swift b/submodules/MediaResources/Sources/CachedResourceRepresentations.swift index e18def94d7..2483da6dd4 100644 --- a/submodules/MediaResources/Sources/CachedResourceRepresentations.swift +++ b/submodules/MediaResources/Sources/CachedResourceRepresentations.swift @@ -1,11 +1,11 @@ import Foundation import UIKit import SwiftSignalKit -import Postbox +import TelegramCore -public final class CachedStickerAJpegRepresentation: CachedMediaResourceRepresentation { +public final class CachedStickerAJpegRepresentation: EngineRawCachedMediaResourceRepresentation { public let size: CGSize? - public let keepDuration: CachedMediaRepresentationKeepDuration = .general + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public var uniqueId: String { if let size = self.size { @@ -19,7 +19,7 @@ public final class CachedStickerAJpegRepresentation: CachedMediaResourceRepresen self.size = size } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if let to = to as? CachedStickerAJpegRepresentation { return self.size == to.size } else { @@ -33,8 +33,8 @@ public enum CachedScaledImageRepresentationMode: Int32 { case aspectFit = 1 } -public final class CachedScaledImageRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedScaledImageRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public let size: CGSize public let mode: CachedScaledImageRepresentationMode @@ -48,7 +48,7 @@ public final class CachedScaledImageRepresentation: CachedMediaResourceRepresent self.mode = mode } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if let to = to as? CachedScaledImageRepresentation { return self.size == to.size && self.mode == to.mode } else { @@ -57,8 +57,8 @@ public final class CachedScaledImageRepresentation: CachedMediaResourceRepresent } } -public final class CachedVideoFirstFrameRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedVideoFirstFrameRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public var uniqueId: String { return "first-frame" @@ -67,7 +67,7 @@ public final class CachedVideoFirstFrameRepresentation: CachedMediaResourceRepre public init() { } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if to is CachedVideoFirstFrameRepresentation { return true } else { @@ -76,8 +76,8 @@ public final class CachedVideoFirstFrameRepresentation: CachedMediaResourceRepre } } -public final class CachedVideoPrefixFirstFrameRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedVideoPrefixFirstFrameRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public var uniqueId: String { return "prefix-first-frame" @@ -89,7 +89,7 @@ public final class CachedVideoPrefixFirstFrameRepresentation: CachedMediaResourc self.prefixLength = prefixLength } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if let to = to as? CachedVideoPrefixFirstFrameRepresentation { if self.prefixLength != to.prefixLength { return false @@ -101,8 +101,8 @@ public final class CachedVideoPrefixFirstFrameRepresentation: CachedMediaResourc } } -public final class CachedScaledVideoFirstFrameRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedScaledVideoFirstFrameRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public let size: CGSize @@ -114,7 +114,7 @@ public final class CachedScaledVideoFirstFrameRepresentation: CachedMediaResourc self.size = size } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if let to = to as? CachedScaledVideoFirstFrameRepresentation { return self.size == to.size } else { @@ -123,8 +123,8 @@ public final class CachedScaledVideoFirstFrameRepresentation: CachedMediaResourc } } -public final class CachedBlurredWallpaperRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedBlurredWallpaperRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public var uniqueId: String { return "blurred-wallpaper" @@ -133,7 +133,7 @@ public final class CachedBlurredWallpaperRepresentation: CachedMediaResourceRepr public init() { } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if to is CachedBlurredWallpaperRepresentation { return true } else { @@ -142,8 +142,8 @@ public final class CachedBlurredWallpaperRepresentation: CachedMediaResourceRepr } } -public final class CachedAlbumArtworkRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedAlbumArtworkRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public let size: CGSize? @@ -159,7 +159,7 @@ public final class CachedAlbumArtworkRepresentation: CachedMediaResourceRepresen self.size = size } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if let to = to as? CachedAlbumArtworkRepresentation { return self.size == to.size } else { @@ -168,8 +168,8 @@ public final class CachedAlbumArtworkRepresentation: CachedMediaResourceRepresen } } -public final class CachedEmojiThumbnailRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedEmojiThumbnailRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public let outline: Bool @@ -181,7 +181,7 @@ public final class CachedEmojiThumbnailRepresentation: CachedMediaResourceRepres self.outline = outline } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if let to = to as? CachedEmojiThumbnailRepresentation { return self.outline == to.outline } else { @@ -190,8 +190,8 @@ public final class CachedEmojiThumbnailRepresentation: CachedMediaResourceRepres } } -public final class CachedEmojiRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedEmojiRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public let tile: UInt8 public let outline: Bool @@ -205,7 +205,7 @@ public final class CachedEmojiRepresentation: CachedMediaResourceRepresentation self.outline = outline } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if let to = to as? CachedEmojiRepresentation { return self.tile == to.tile && self.outline == to.outline } else { @@ -239,8 +239,8 @@ public enum EmojiFitzModifier: Int32, Equatable { } } -public final class CachedAnimatedStickerFirstFrameRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedAnimatedStickerFirstFrameRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public let width: Int32 public let height: Int32 @@ -261,7 +261,7 @@ public final class CachedAnimatedStickerFirstFrameRepresentation: CachedMediaRes } } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if let other = to as? CachedAnimatedStickerFirstFrameRepresentation { if other.width != self.width { return false @@ -279,8 +279,8 @@ public final class CachedAnimatedStickerFirstFrameRepresentation: CachedMediaRes } } -public final class CachedAnimatedStickerRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .shortLived +public final class CachedAnimatedStickerRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .shortLived public let width: Int32 public let height: Int32 @@ -301,7 +301,7 @@ public final class CachedAnimatedStickerRepresentation: CachedMediaResourceRepre self.fitzModifier = fitzModifier } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if let other = to as? CachedAnimatedStickerRepresentation { if other.width != self.width { return false @@ -319,8 +319,8 @@ public final class CachedAnimatedStickerRepresentation: CachedMediaResourceRepre } } -public final class CachedVideoStickerRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .shortLived +public final class CachedVideoStickerRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .shortLived public let width: Int32 public let height: Int32 @@ -336,7 +336,7 @@ public final class CachedVideoStickerRepresentation: CachedMediaResourceRepresen self.height = height } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if let other = to as? CachedVideoStickerRepresentation { if other.width != self.width { return false @@ -351,8 +351,8 @@ public final class CachedVideoStickerRepresentation: CachedMediaResourceRepresen } } -public final class CachedPreparedPatternWallpaperRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedPreparedPatternWallpaperRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public var uniqueId: String { return "prepared-pattern-wallpaper" @@ -361,7 +361,7 @@ public final class CachedPreparedPatternWallpaperRepresentation: CachedMediaReso public init() { } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if to is CachedPreparedPatternWallpaperRepresentation { return true } else { @@ -371,8 +371,8 @@ public final class CachedPreparedPatternWallpaperRepresentation: CachedMediaReso } -public final class CachedPreparedSvgRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .general +public final class CachedPreparedSvgRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .general public var uniqueId: String { return "prepared-svg" @@ -381,7 +381,7 @@ public final class CachedPreparedSvgRepresentation: CachedMediaResourceRepresent public init() { } - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if to is CachedPreparedSvgRepresentation { return true } else { diff --git a/submodules/PassportUI/Sources/LegacySecureIdAttachmentMenu.swift b/submodules/PassportUI/Sources/LegacySecureIdAttachmentMenu.swift index a3ef9dc4fc..2264149d6d 100644 --- a/submodules/PassportUI/Sources/LegacySecureIdAttachmentMenu.swift +++ b/submodules/PassportUI/Sources/LegacySecureIdAttachmentMenu.swift @@ -76,7 +76,7 @@ func presentLegacySecureIdAttachmentMenu(context: AccountContext, present: @esca |> runOn(.mainQueue()) |> delay(0.1, queue: .mainQueue())).start() - let _ = (processedLegacySecureIdAttachmentItems(postbox: context.account.postbox, signal: signal) + let _ = (processedLegacySecureIdAttachmentItems(signal: signal) |> mapToSignal { resources -> Signal<([TelegramMediaResource], SecureIdRecognizedDocumentData?), NoError> in switch type { case .generic, .idCard: @@ -116,7 +116,7 @@ private enum AttachmentItem { case iCloud(URL) } -private func processedLegacySecureIdAttachmentItems(postbox: Postbox, signal: SSignal) -> Signal<[TelegramMediaResource], NoError> { +private func processedLegacySecureIdAttachmentItems(signal: SSignal) -> Signal<[TelegramMediaResource], NoError> { let nativeSignal = Signal { subscriber in let disposable = signal.start(next: { next in if let dict = next as? [String: Any], let image = dict["image"] as? UIImage { diff --git a/submodules/PhotoResources/Sources/PhotoResources.swift b/submodules/PhotoResources/Sources/PhotoResources.swift index 86a270792e..e4305b2f2c 100644 --- a/submodules/PhotoResources/Sources/PhotoResources.swift +++ b/submodules/PhotoResources/Sources/PhotoResources.swift @@ -844,24 +844,6 @@ private func chatMessageVideoDatas(postbox: Postbox, userLocation: MediaResource return signal } -public func rawMessagePhoto(postbox: Postbox, userLocation: MediaResourceUserLocation, photoReference: ImageMediaReference) -> Signal { - return chatMessagePhotoDatas(postbox: postbox, userLocation: userLocation, photoReference: photoReference, autoFetchFullSize: true) - |> map { value -> UIImage? in - let thumbnailData = value._0 - let fullSizeData = value._1 - let fullSizeComplete = value._3 - if let fullSizeData = fullSizeData { - if fullSizeComplete { - return UIImage(data: fullSizeData)?.precomposed() - } - } - if let thumbnailData = thumbnailData { - return UIImage(data: thumbnailData)?.precomposed() - } - return nil - } -} - public func chatMessagePhoto(postbox: Postbox, userLocation: MediaResourceUserLocation, userContentType customUserContentType: MediaResourceUserContentType? = nil, photoReference: ImageMediaReference, synchronousLoad: Bool = false, highQuality: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { return chatMessagePhotoInternal(photoData: chatMessagePhotoDatas(postbox: postbox, userLocation: userLocation, customUserContentType: customUserContentType, photoReference: photoReference, tryAdditionalRepresentations: true, synchronousLoad: synchronousLoad), synchronousLoad: synchronousLoad) |> map { _, _, generate in @@ -1766,79 +1748,6 @@ public func mediaGridMessagePhoto(account: Account, userLocation: MediaResourceU } } -public func gifPaneVideoThumbnail(account: Account, videoReference: FileMediaReference) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { - if let smallestRepresentation = smallestImageRepresentation(videoReference.media.previewRepresentations) { - let thumbnailResource = smallestRepresentation.resource - - let thumbnail = Signal { subscriber in - let data = account.postbox.mediaBox.resourceData(thumbnailResource).start(next: { data in - subscriber.putNext(data) - }, completed: { - subscriber.putCompletion() - }) - let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: videoReference.resourceReference(thumbnailResource)).start() - return ActionDisposable { - data.dispose() - fetched.dispose() - } - } - - return thumbnail - |> map { data in - let thumbnailData = try? Data(contentsOf: URL(fileURLWithPath: data.path)) - return { arguments in - guard let context = DrawingContext(size: arguments.drawingSize, clear: true) else { - return nil - } - - let drawingRect = arguments.drawingRect - let fittedSize = arguments.imageSize.aspectFilled(arguments.boundingSize).fitted(arguments.imageSize) - let fittedRect = CGRect(origin: CGPoint(x: drawingRect.origin.x + (drawingRect.size.width - fittedSize.width) / 2.0, y: drawingRect.origin.y + (drawingRect.size.height - fittedSize.height) / 2.0), size: fittedSize) - - var thumbnailImage: CGImage? - if let thumbnailData = thumbnailData, let imageSource = CGImageSourceCreateWithData(thumbnailData as CFData, nil), let image = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) { - thumbnailImage = image - } - - var blurredThumbnailImage: UIImage? - if let thumbnailImage = thumbnailImage { - let thumbnailSize = CGSize(width: thumbnailImage.width, height: thumbnailImage.height) - let thumbnailContextSize = thumbnailSize.aspectFitted(CGSize(width: 150.0, height: 150.0)) - if let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) { - thumbnailContext.withFlippedContext { c in - c.interpolationQuality = .none - c.draw(thumbnailImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize)) - } - imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes) - - blurredThumbnailImage = thumbnailContext.generateImage() - } - } - - context.withFlippedContext { c in - c.setBlendMode(.copy) - if arguments.boundingSize != arguments.imageSize { - c.fill(arguments.drawingRect) - } - - c.setBlendMode(.copy) - if let blurredThumbnailImage = blurredThumbnailImage, let cgImage = blurredThumbnailImage.cgImage { - c.interpolationQuality = .low - drawImage(context: c, image: cgImage, orientation: .up, in: fittedRect) - c.setBlendMode(.normal) - } - } - - addCorners(context, arguments: arguments) - - return context - } - } - } else { - return .never() - } -} - public func mediaGridMessageVideo(postbox: Postbox, userLocation: MediaResourceUserLocation, userContentType customUserContentType: MediaResourceUserContentType? = nil, videoReference: FileMediaReference, hlsFiles: [(playlist: TelegramMediaFile, video: TelegramMediaFile)] = [], onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, overlayColor: UIColor? = nil, nilForEmptyResult: Bool = false, useMiniThumbnailIfAvailable: Bool = false, blurred: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { return internalMediaGridMessageVideo(postbox: postbox, userLocation: userLocation, customUserContentType: customUserContentType, videoReference: videoReference, hlsFiles: hlsFiles, onlyFullSize: onlyFullSize, useLargeThumbnail: useLargeThumbnail, synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail, overlayColor: overlayColor, nilForEmptyResult: nilForEmptyResult, useMiniThumbnailIfAvailable: useMiniThumbnailIfAvailable) |> map { @@ -2703,25 +2612,6 @@ public func chatMessageImageFile(account: Account, userLocation: MediaResourceUs } } -public func preloadedBotIcon(account: Account, fileReference: FileMediaReference) -> Signal { - let signal = Signal { subscriber in - let fetched = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: MediaResourceUserContentType(file: fileReference.media), reference: fileReference.resourceReference(fileReference.media.resource)).start() - let dataDisposable = account.postbox.mediaBox.resourceData(fileReference.media.resource, option: .incremental(waitUntilFetchStatus: false)).start(next: { data in - if data.complete { - subscriber.putNext(true) - subscriber.putCompletion() - } else { - subscriber.putNext(false) - } - }) - return ActionDisposable { - fetched.dispose() - dataDisposable.dispose() - } - } - return signal -} - public func instantPageImageFile(account: Account, userLocation: MediaResourceUserLocation, fileReference: FileMediaReference, fetched: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { return chatMessageFileDatas(account: account, userLocation: userLocation, fileReference: fileReference, progressive: false, fetched: fetched) |> map { value in diff --git a/submodules/PlatformRestrictionMatching/Sources/PlatformRestrictionMatching.swift b/submodules/PlatformRestrictionMatching/Sources/PlatformRestrictionMatching.swift index cdafe9a37c..79e6ffaa8a 100644 --- a/submodules/PlatformRestrictionMatching/Sources/PlatformRestrictionMatching.swift +++ b/submodules/PlatformRestrictionMatching/Sources/PlatformRestrictionMatching.swift @@ -1,8 +1,7 @@ import Foundation import TelegramCore -import Postbox -public extension Message { +public extension EngineRawMessage { func isRestricted(platform: String, contentSettings: ContentSettings) -> Bool { return self.restrictionReason(platform: platform, contentSettings: contentSettings) != nil } diff --git a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index c11551e0ef..1e58c28be8 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -142,7 +142,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { jsonString += "]}}" if let data = jsonString.data(using: .utf8), let json = JSON(data: data) { - addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium_gift.promo_screen_show", data: json) + strongSelf.context.engine.accountData.addAppLogEvent(type: "premium_gift.promo_screen_show", data: json) } } @@ -568,7 +568,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { controller?.dismiss(animated: true, completion: nil) } - addAppLogEvent(postbox: accountContext.account.postbox, type: "premium_gift.promo_screen_tap", data: ["item": perk.identifier]) + accountContext.engine.accountData.addAppLogEvent(type: "premium_gift.promo_screen_tap", data: ["item": perk.identifier]) } )) i += 1 @@ -900,7 +900,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { let (currency, amount) = product.storeProduct.priceCurrencyAndAmount let duration = product.months - addAppLogEvent(postbox: self.context.account.postbox, type: "premium_gift.promo_screen_accept") + self.context.engine.accountData.addAppLogEvent(type: "premium_gift.promo_screen_accept") self.inProgress = true self.updateInProgress(true) @@ -968,7 +968,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { } if let errorText = errorText { - addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium_gift.promo_screen_fail") + strongSelf.context.engine.accountData.addAppLogEvent(type: "premium_gift.promo_screen_fail") let alertController = textAlertController(context: strongSelf.context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]) strongSelf.present(alertController) diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index d4bef601c4..c7c0c12e3e 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -1682,7 +1682,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { jsonString += "]}}" if let context = screenContext.context, let data = jsonString.data(using: .utf8), let json = JSON(data: data) { - addAppLogEvent(postbox: context.account.postbox, type: "premium.promo_screen_show", data: json) + context.engine.accountData.addAppLogEvent(type: "premium.promo_screen_show", data: json) } } }) @@ -2260,7 +2260,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { } updateIsFocused(true) - addAppLogEvent(postbox: accountContext.account.postbox, type: "premium.promo_screen_tap", data: ["item": perk.identifier]) + accountContext.engine.accountData.addAppLogEvent(type: "premium.promo_screen_tap", data: ["item": perk.identifier]) }, highlighting: accountContext != nil ? .default : .disabled )))) @@ -3262,7 +3262,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { } if let context = self.screenContext.context { - addAppLogEvent(postbox: context.account.postbox, type: "premium.promo_screen_accept") + context.engine.accountData.addAppLogEvent(type: "premium.promo_screen_accept") } self.inProgress = true @@ -3316,7 +3316,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { self.updated(transition: .immediate) if let context = self.screenContext.context { - addAppLogEvent(postbox: context.account.postbox, type: "premium.promo_screen_fail") + context.engine.accountData.addAppLogEvent(type: "premium.promo_screen_fail") } let errorText = presentationData.strings.Premium_Purchase_ErrorUnknown @@ -3368,7 +3368,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { if let errorText = errorText { if let context = self.screenContext.context { - addAppLogEvent(postbox: context.account.postbox, type: "premium.promo_screen_fail") + context.engine.accountData.addAppLogEvent(type: "premium.promo_screen_fail") } let alertController = textAlertController(sharedContext: self.screenContext.sharedContext, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]) diff --git a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift index f7517c7427..d2c0a1b293 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift @@ -296,15 +296,15 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat switch mode { case .peers: - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_cloud_cancel") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_cloud_cancel") case .groups: - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_groups_cancel") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_groups_cancel") case .messages: - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_messages_cancel") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_messages_cancel") case .phone: - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_phone_cancel") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_phone_cancel") case .password: - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_2fa_cancel") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_2fa_cancel") } } @@ -437,10 +437,10 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat let controller = deleteAccountDataController(context: context, mode: nextMode, twoStepAuthData: twoStepAuthData) replaceTopControllerImpl?(controller) } else { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_confirmation_show") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_confirmation_show") presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.DeleteAccount_ConfirmationAlertTitle, text: presentationData.strings.DeleteAccount_ConfirmationAlertText, actions: [TextAlertAction(type: .destructiveAction, title: presentationData.strings.DeleteAccount_ConfirmationAlertDelete, action: { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.final") + context.engine.accountData.addAppLogEvent(type: "deactivate.final") invokeAppLogEventsSynchronization(postbox: context.account.postbox) @@ -473,7 +473,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat }) }) }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_confirmation_cancel") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_confirmation_cancel") dismissImpl?() })], actionLayout: .vertical)) @@ -581,15 +581,15 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat switch mode { case .peers: - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_cloud_show") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_cloud_show") case .groups: - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_groups_show") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_groups_show") case .messages: - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_messages_show") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_messages_show") case .phone: - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_phone_show") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_phone_show") case .password: - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_2fa_show") + context.engine.accountData.addAppLogEvent(type: "deactivate.step_2fa_show") } return controller diff --git a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift index 0e23345ba7..af79d8966e 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift @@ -181,7 +181,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo let supportPeerDisposable = MetaDisposable() let arguments = DeleteAccountOptionsArguments(changePhoneNumber: { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_phone_change_tap") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_phone_change_tap") let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.engine.account.peerId)) |> deliverOnMainQueue).start(next: { accountPeer in @@ -195,7 +195,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo dismissImpl?() }) }, addAccount: { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_add_account_tap") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_add_account_tap") let _ = (activeAccountsAndPeers(context: context) |> take(1) @@ -233,11 +233,11 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo } }) }, setupPrivacy: { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_privacy_tap") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_privacy_tap") replaceTopControllerImpl?(makePrivacyAndSecurityController(context: context), false) }, setupTwoStepAuth: { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_2fa_tap") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_2fa_tap") if let data = twoStepAuthData { switch data { @@ -263,7 +263,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo let controller = twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: false, data: twoStepAuthData.flatMap({ Signal.single(.access(configuration: $0)) }))) replaceTopControllerImpl?(controller, false) }, setPasscode: { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_passcode_tap") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_passcode_tap") let _ = passcodeOptionsAccessController(context: context, pushController: { controller in replaceTopControllerImpl?(controller, false) @@ -276,18 +276,18 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo }) dismissImpl?() }, clearCache: { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_cache_tap") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_clear_cache_tap") pushControllerImpl?(StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in return storageUsageExceptionsScreen(context: context, category: category) })) dismissImpl?() }, clearSyncedContacts: { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_contacts_tap") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_clear_contacts_tap") replaceTopControllerImpl?(dataPrivacyController(context: context), false) }, deleteChats: { - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_delete_chats_tap") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_delete_chats_tap") let presentationData = context.sharedContext.currentPresentationData.with { $0 } @@ -325,7 +325,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo openFaq(resolvedUrlPromise) }, contactSupport: { [weak navigationController] in - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_support_tap") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_support_tap") let presentationData = context.sharedContext.currentPresentationData.with { $0 } @@ -394,7 +394,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo ] ) alertController.dismissed = { _ in - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_support_cancel") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_support_cancel") } presentControllerImpl?(alertController, nil) }, deleteAccount: { @@ -464,7 +464,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo let _ = controller?.dismiss() } - addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_show") + context.engine.accountData.addAppLogEvent(type: "deactivate.options_show") return controller } diff --git a/submodules/SettingsUI/Sources/ThemePickerController.swift b/submodules/SettingsUI/Sources/ThemePickerController.swift index 986b79cc0b..5da8ce64b3 100644 --- a/submodules/SettingsUI/Sources/ThemePickerController.swift +++ b/submodules/SettingsUI/Sources/ThemePickerController.swift @@ -363,10 +363,10 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme var selectAccentColorImpl: ((TelegramBaseTheme?, PresentationThemeAccentColor?) -> Void)? var openAccentColorPickerImpl: ((PresentationThemeReference, Bool) -> Void)? - let _ = telegramWallpapers(postbox: context.account.postbox, network: context.account.network).start() + let _ = context.engine.themes.wallpapers().start() let cloudThemes = Promise<[TelegramTheme]>() - let updatedCloudThemes = telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager) + let updatedCloudThemes = context.engine.themes.themes(accountManager: context.sharedContext.accountManager) cloudThemes.set(updatedCloudThemes) let removedThemeIndexesPromise = Promise>(Set()) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift index bc300e2812..799c42fb69 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift @@ -565,7 +565,7 @@ public func themeAutoNightSettingsController(context: AccountContext) -> ViewCon }) let cloudThemes = Promise<[TelegramTheme]>() - let updatedCloudThemes = telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager) + let updatedCloudThemes = context.engine.themes.themes(accountManager: context.sharedContext.accountManager) cloudThemes.set(updatedCloudThemes) let signal = combineLatest(context.sharedContext.presentationData |> deliverOnMainQueue, sharedData |> deliverOnMainQueue, cloudThemes.get() |> deliverOnMainQueue, stagingSettingsPromise.get() |> deliverOnMainQueue) diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewController.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewController.swift index a251af569a..80bcb63874 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewController.swift @@ -284,7 +284,7 @@ public final class ThemePreviewController: ViewController { switch theme { case let .cloud(info): resolvedWallpaper = info.resolvedWallpaper - return telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager) + return context.engine.themes.themes(accountManager: context.sharedContext.accountManager) |> take(1) |> map { themes -> Bool in if let _ = themes.first(where: { $0.id == info.theme.id }) { @@ -317,7 +317,7 @@ public final class ThemePreviewController: ViewController { }, scale: 1.0) let themeThumbnailData = themeThumbnail?.jpegData(compressionQuality: 0.6) - return telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager) + return context.engine.themes.themes(accountManager: context.sharedContext.accountManager) |> take(1) |> mapToSignal { themes -> Signal<(PresentationThemeReference, Bool), NoError> in let similarTheme = themes.first(where: { $0.isCreator && $0.title == info.title }) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index 9fcf97c4a6..965bca3666 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -520,7 +520,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The var selectAccentColorImpl: ((PresentationThemeAccentColor?) -> Void)? var openAccentColorPickerImpl: ((PresentationThemeReference, Bool) -> Void)? - let _ = telegramWallpapers(postbox: context.account.postbox, network: context.account.network).start() + let _ = context.engine.themes.wallpapers().start() let currentAppIcon: PresentationAppIcon? var appIcons = context.sharedContext.applicationBindings.getAvailableAlternateIcons() @@ -540,7 +540,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The currentAppIconName.set(currentAppIcon?.name ?? "Blue") let cloudThemes = Promise<[TelegramTheme]>() - let updatedCloudThemes = telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager) + let updatedCloudThemes = context.engine.themes.themes(accountManager: context.sharedContext.accountManager) cloudThemes.set(updatedCloudThemes) let removedThemeIndexesPromise = Promise>(Set()) diff --git a/submodules/SpotlightSupport/BUILD b/submodules/SpotlightSupport/BUILD deleted file mode 100644 index ff77db99c2..0000000000 --- a/submodules/SpotlightSupport/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") - -swift_library( - name = "SpotlightSupport", - module_name = "SpotlightSupport", - srcs = glob([ - "Sources/**/*.swift", - ]), - deps = [ - "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", - "//submodules/SyncCore:SyncCore", - "//submodules/TelegramCore:TelegramCore", - "//submodules/Display:Display", - ], - visibility = [ - "//visibility:public", - ], -) diff --git a/submodules/StatisticsUI/Sources/StoryIconNode.swift b/submodules/StatisticsUI/Sources/StoryIconNode.swift index 7fec70ab34..7246e29bc6 100644 --- a/submodules/StatisticsUI/Sources/StoryIconNode.swift +++ b/submodules/StatisticsUI/Sources/StoryIconNode.swift @@ -4,7 +4,6 @@ import Display import AsyncDisplayKit import ComponentFlow import SwiftSignalKit -import Postbox import TelegramCore import PhotoResources import AvatarStoryIndicatorComponent @@ -15,7 +14,7 @@ final class StoryIconNode: ASDisplayNode { private let imageNode = TransformImageNode() private let storyIndicator = ComponentView() - init(context: AccountContext, theme: PresentationTheme, peer: Peer, storyItem: EngineStoryItem) { + init(context: AccountContext, theme: PresentationTheme, peer: EngineRawPeer, storyItem: EngineStoryItem) { self.imageNode.displaysAsynchronously = false super.init() @@ -29,7 +28,7 @@ final class StoryIconNode: ASDisplayNode { self.imageNode.frame = bounds.insetBy(dx: 3.0, dy: 3.0) self.frame = bounds - let media: Media? + let media: EngineRawMedia? switch storyItem.media { case let .image(image): media = image diff --git a/submodules/StickerPackPreviewUI/BUILD b/submodules/StickerPackPreviewUI/BUILD index 67a5eab359..32e8851557 100644 --- a/submodules/StickerPackPreviewUI/BUILD +++ b/submodules/StickerPackPreviewUI/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/AccountContext:AccountContext", diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 538b72044c..4a968b8c6f 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import AsyncDisplayKit -import Postbox import TelegramCore import SwiftSignalKit import AccountContext @@ -802,19 +801,19 @@ private final class StickerPackContainer: ASDisplayNode { private func emojiSuggestionPeekContent(itemLayer: CALayer, file: TelegramMediaFile) -> Signal<(UIView, CGRect, PeekControllerContent)?, NoError> { let context = self.context - var collectionId: ItemCollectionId? + var collectionId: EngineItemCollectionId? for attribute in file.attributes { if case let .CustomEmoji(_, _, _, packReference) = attribute { switch packReference { case let .id(id, _): - collectionId = ItemCollectionId(namespace: Namespaces.ItemCollection.CloudEmojiPacks, id: id) + collectionId = EngineItemCollectionId(namespace: Namespaces.ItemCollection.CloudEmojiPacks, id: id) default: break } } } - var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + var bubbleUpEmojiOrStickersets: [EngineItemCollectionId] = [] if let collectionId { bubbleUpEmojiOrStickersets.append(collectionId) } @@ -859,9 +858,9 @@ private final class StickerPackContainer: ASDisplayNode { case let .CustomEmoji(_, _, displayText, stickerPackReference): text = displayText - var packId: ItemCollectionId? + var packId: EngineItemCollectionId? if case let .id(id, _) = stickerPackReference { - packId = ItemCollectionId(namespace: Namespaces.ItemCollection.CloudEmojiPacks, id: id) + packId = EngineItemCollectionId(namespace: Namespaces.ItemCollection.CloudEmojiPacks, id: id) } emojiAttribute = ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: packId, fileId: file.fileId.id, file: file) break loop @@ -1468,12 +1467,12 @@ private final class StickerPackContainer: ASDisplayNode { } if installedCount == self.currentStickerPacks.count { - var removedPacks: Signal<[(info: ItemCollectionInfo, index: Int, items: [ItemCollectionItem])], NoError> = .single([]) + var removedPacks: Signal<[(info: EngineRawItemCollectionInfo, index: Int, items: [EngineRawItemCollectionItem])], NoError> = .single([]) for (info, _, _) in self.currentStickerPacks { removedPacks = removedPacks - |> mapToSignal { current -> Signal<[(info: ItemCollectionInfo, index: Int, items: [ItemCollectionItem])], NoError> in + |> mapToSignal { current -> Signal<[(info: EngineRawItemCollectionInfo, index: Int, items: [EngineRawItemCollectionItem])], NoError> in return self.context.engine.stickers.removeStickerPackInteractively(id: info.id, option: .delete) - |> map { result -> [(info: ItemCollectionInfo, index: Int, items: [ItemCollectionItem])] in + |> map { result -> [(info: EngineRawItemCollectionInfo, index: Int, items: [EngineRawItemCollectionItem])] in if let result = result { return current + [(info, result.0, result.1)] } else { @@ -2968,13 +2967,6 @@ public final class StickerPackScreenImpl: ViewController, StickerPackScreen { } return .single(result) } - |> mapToSignal { peer -> Signal in - if let peer = peer { - return .single(peer._asPeer()) - } else { - return .single(nil) - } - } |> deliverOnMainQueue).start(next: { peer in guard let strongSelf = self else { return @@ -2982,7 +2974,7 @@ public final class StickerPackScreenImpl: ViewController, StickerPackScreen { if let peer { if let parentNavigationController = strongSelf.parentNavigationController { strongSelf.controllerNode.dismiss() - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: parentNavigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)), keepStack: .always, animated: true)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: parentNavigationController, context: strongSelf.context, chatLocation: .peer(peer), keepStack: .always, animated: true)) } } else { strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.Resolve_ErrorNotFound, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) diff --git a/submodules/StickerResources/Sources/StickerResources.swift b/submodules/StickerResources/Sources/StickerResources.swift index 229dbc7f6b..d435924b58 100644 --- a/submodules/StickerResources/Sources/StickerResources.swift +++ b/submodules/StickerResources/Sources/StickerResources.swift @@ -260,74 +260,6 @@ public func chatMessageAnimatedStickerBackingData(postbox: Postbox, fileReferenc } } -public func chatMessageLegacySticker(account: Account, userLocation: MediaResourceUserLocation, file: TelegramMediaFile, small: Bool, fitSize: CGSize, fetched: Bool = false, onlyFullSize: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { - let signal = chatMessageStickerDatas(postbox: account.postbox, userLocation: userLocation, file: file, small: small, fetched: fetched, onlyFullSize: onlyFullSize, synchronousLoad: false) - return signal |> map { value in - let fullSizeData = value._1 - let fullSizeComplete = value._2 - return { preArguments in - var fullSizeImage: (UIImage, UIImage)? - if let fullSizeData = fullSizeData, fullSizeComplete { - if let image = imageFromAJpeg(data: fullSizeData) { - fullSizeImage = image - } - } - - if let fullSizeImage = fullSizeImage { - var updatedFitSize = fitSize - if updatedFitSize.width.isEqual(to: 1.0) { - updatedFitSize = fullSizeImage.0.size - } - - let contextSize = fullSizeImage.0.size.aspectFitted(updatedFitSize) - - let arguments = TransformImageArguments(corners: preArguments.corners, imageSize: contextSize, boundingSize: contextSize, intrinsicInsets: preArguments.intrinsicInsets) - - guard let context = DrawingContext(size: arguments.drawingSize, clear: true) else { - return nil - } - - let thumbnailImage: CGImage? = nil - - var blurredThumbnailImage: UIImage? - if let thumbnailImage = thumbnailImage { - let thumbnailSize = CGSize(width: thumbnailImage.width, height: thumbnailImage.height) - let thumbnailContextSize = thumbnailSize.aspectFitted(CGSize(width: 150.0, height: 150.0)) - if let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) { - thumbnailContext.withFlippedContext { c in - c.interpolationQuality = .none - c.draw(thumbnailImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize)) - } - imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes) - - blurredThumbnailImage = thumbnailContext.generateImage() - } - } - - context.withFlippedContext { c in - c.setBlendMode(.copy) - if let blurredThumbnailImage = blurredThumbnailImage { - c.interpolationQuality = .low - c.draw(blurredThumbnailImage.cgImage!, in: arguments.drawingRect) - } - - if let cgImage = fullSizeImage.0.cgImage, let cgImageAlpha = fullSizeImage.1.cgImage { - c.setBlendMode(.normal) - c.interpolationQuality = .medium - - let mask = CGImage(maskWidth: cgImageAlpha.width, height: cgImageAlpha.height, bitsPerComponent: cgImageAlpha.bitsPerComponent, bitsPerPixel: cgImageAlpha.bitsPerPixel, bytesPerRow: cgImageAlpha.bytesPerRow, provider: cgImageAlpha.dataProvider!, decode: nil, shouldInterpolate: true) - - c.draw(cgImage.masking(mask!)!, in: arguments.drawingRect) - } - } - - return context - } else { - return nil - } - } - } -} public func chatMessageSticker(account: Account, userLocation: MediaResourceUserLocation, file: TelegramMediaFile, small: Bool, fetched: Bool = false, onlyFullSize: Bool = false, thumbnail: Bool = false, synchronousLoad: Bool = false, colorSpace: CGColorSpace? = nil) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { return chatMessageSticker(postbox: account.postbox, userLocation: userLocation, file: file, small: small, fetched: fetched, onlyFullSize: onlyFullSize, thumbnail: thumbnail, synchronousLoad: synchronousLoad, colorSpace: colorSpace) diff --git a/submodules/SvgRendering/BUILD b/submodules/SvgRendering/BUILD deleted file mode 100644 index 20e1b4b487..0000000000 --- a/submodules/SvgRendering/BUILD +++ /dev/null @@ -1,14 +0,0 @@ -load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") - -swift_library( - name = "SvgRendering", - module_name = "SvgRendering", - srcs = glob([ - "Sources/**/*.swift", - ]), - deps = [ - ], - visibility = [ - "//visibility:public", - ], -) diff --git a/submodules/SvgRendering/Sources/SvgParser.swift b/submodules/SvgRendering/Sources/SvgParser.swift deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/submodules/TelegramCallsUI/Sources/LegacyCallControllerNode.swift b/submodules/TelegramCallsUI/Sources/LegacyCallControllerNode.swift index 90c82ea124..1bb34d814e 100644 --- a/submodules/TelegramCallsUI/Sources/LegacyCallControllerNode.swift +++ b/submodules/TelegramCallsUI/Sources/LegacyCallControllerNode.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import AsyncDisplayKit -import Postbox import TelegramCore import SwiftSignalKit import TelegramPresentationData diff --git a/submodules/TelegramCore/Sources/ApiUtils/ChatContextResult.swift b/submodules/TelegramCore/Sources/ApiUtils/ChatContextResult.swift index 2a56151233..81b3454c13 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/ChatContextResult.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/ChatContextResult.swift @@ -5,10 +5,6 @@ import TelegramApi import MtProtoKit -public enum ChatContextResultMessageDecodingError: Error { - case generic -} - public enum ChatContextResultMessage: PostboxCoding, Equatable, Codable { enum CodingKeys: String, CodingKey { case data diff --git a/submodules/TelegramCore/Sources/ApiUtils/CloudMediaResourceParameters.swift b/submodules/TelegramCore/Sources/ApiUtils/CloudMediaResourceParameters.swift deleted file mode 100644 index e9e165bf24..0000000000 --- a/submodules/TelegramCore/Sources/ApiUtils/CloudMediaResourceParameters.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation - -public enum CloudMediaResourceLocation: Equatable { - case photo(id: Int64, accessHash: Int64, fileReference: Data, thumbSize: String) - case file(id: Int64, accessHash: Int64, fileReference: Data, thumbSize: String) - case peerPhoto(peer: PeerReference, fullSize: Bool, volumeId: Int64, localId: Int64) - case stickerPackThumbnail(packReference: StickerPackReference, volumeId: Int64, localId: Int64) -} diff --git a/submodules/TelegramCore/Sources/Authorization.swift b/submodules/TelegramCore/Sources/Authorization.swift index 5bc16112de..61c1d41955 100644 --- a/submodules/TelegramCore/Sources/Authorization.swift +++ b/submodules/TelegramCore/Sources/Authorization.swift @@ -1321,16 +1321,6 @@ public func authorizeWithPasskey(accountManager: AccountManager switchToLatest } -public enum AuthorizationStateReset { - case empty -} - -public func resetAuthorizationState(account: UnauthorizedAccount, to value: AuthorizationStateReset) -> Signal { - return account.postbox.transaction { transaction -> Void in - if let state = transaction.getState() as? UnauthorizedAccountState { - transaction.setState(UnauthorizedAccountState(isTestingEnvironment: state.isTestingEnvironment, masterDatacenterId: state.masterDatacenterId, contents: .empty)) - } - } -} - public func togglePreviousCodeEntry(account: UnauthorizedAccount) -> Signal { return account.postbox.transaction { transaction -> Void in if let state = transaction.getState() as? UnauthorizedAccountState { diff --git a/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift b/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift index c6e524f8b8..494ff54652 100644 --- a/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift +++ b/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift @@ -671,7 +671,7 @@ final class MediaReferenceRevalidationContext { } |> map { [$0] } } else { - signal = telegramWallpapers(postbox: postbox, network: network, forceUpdate: true) + signal = _internal_telegramWallpapers(postbox: postbox, network: network, forceUpdate: true) |> last |> mapError { _ -> RevalidateMediaReferenceError in } @@ -697,7 +697,7 @@ final class MediaReferenceRevalidationContext { func themes(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramTheme], RevalidateMediaReferenceError> { return self.genericItem(key: .themes, background: background, request: { next, error in - return (telegramThemes(postbox: postbox, network: network, accountManager: nil, forceUpdate: true) + return (_internal_telegramThemes(postbox: postbox, network: network, accountManager: nil, forceUpdate: true) |> take(1) |> mapError { _ -> RevalidateMediaReferenceError in }).start(next: { value in diff --git a/submodules/TelegramCore/Sources/Network/NetworkStatsContext.swift b/submodules/TelegramCore/Sources/Network/NetworkStatsContext.swift index 9b23e2aafa..5c5f0d885f 100644 --- a/submodules/TelegramCore/Sources/Network/NetworkStatsContext.swift +++ b/submodules/TelegramCore/Sources/Network/NetworkStatsContext.swift @@ -87,7 +87,7 @@ final class NetworkStatsContext { for (targetKey, averageStats) in self.averageTargetStats { if averageStats.count >= 1000 || averageStats.size >= 4 * 1024 * 1024 { if let postbox = self.postbox { - addAppLogEvent(postbox: postbox, type: "download", data: .dictionary([ + _internal_addAppLogEvent(postbox: postbox, type: "download", data: .dictionary([ "n": .number(Double(targetKey.networkType.rawValue)), "d": .number(Double(targetKey.datacenterId)), "b": .number(averageStats.networkBps / Double(averageStats.count)), diff --git a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift index 9d7be75ab7..13fdd45ad0 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift @@ -408,37 +408,6 @@ public func enqueueMessages(account: Account, peerId: PeerId, messages: [Enqueue } } -public func enqueueMessagesToMultiplePeers(account: Account, peerIds: [PeerId], threadIds: [PeerId: Int64], messages: [EnqueueMessage]) -> Signal<[MessageId], NoError> { - let signal: Signal<[(Bool, EnqueueMessage)], NoError> - if let transformOutgoingMessageMedia = account.transformOutgoingMessageMedia { - signal = opportunisticallyTransformOutgoingMedia(network: account.network, postbox: account.postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messages: messages, userInteractive: true) - } else { - signal = .single(messages.map { (false, $0) }) - } - return signal - |> mapToSignal { messages -> Signal<[MessageId], NoError> in - return account.postbox.transaction { transaction -> [MessageId] in - var messageIds: [MessageId] = [] - for peerId in peerIds { - var replyToMessageId: EngineMessageReplySubject? - if let threadIds = threadIds[peerId] { - replyToMessageId = EngineMessageReplySubject(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadIds)), quote: nil, innerSubject: nil) - } - var messages = messages - if let replyToMessageId = replyToMessageId { - messages = messages.map { ($0.0, $0.1.withUpdatedReplyToMessageId(replyToMessageId)) } - } - for id in enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: messages, disableAutoremove: false, transformGroupingKeysWithPeerId: true) { - if let id = id { - messageIds.append(id) - } - } - } - return messageIds - } - } -} - public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal { return account.postbox.transaction { transaction -> Void in var removeMessageIds: [MessageId] = [] diff --git a/submodules/TelegramCore/Sources/PendingMessages/StandaloneUploadedMedia.swift b/submodules/TelegramCore/Sources/PendingMessages/StandaloneUploadedMedia.swift index 1362d20c6e..4c2f0cfdd0 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/StandaloneUploadedMedia.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/StandaloneUploadedMedia.swift @@ -8,12 +8,6 @@ public enum StandaloneUploadMediaError { case generic } -public struct StandaloneUploadSecretFile { - let file: Api.InputEncryptedFile - let size: Int32 - let key: SecretFileEncryptionKey -} - public enum StandaloneUploadMediaThumbnailResult { case pending case file(Api.InputFile) diff --git a/submodules/TelegramCore/Sources/Settings/ContentPrivacySettings.swift b/submodules/TelegramCore/Sources/Settings/ContentPrivacySettings.swift deleted file mode 100644 index 02487dc5c5..0000000000 --- a/submodules/TelegramCore/Sources/Settings/ContentPrivacySettings.swift +++ /dev/null @@ -1,20 +0,0 @@ -import Foundation -import Postbox -import SwiftSignalKit -import MtProtoKit - - -public func updateContentPrivacySettings(postbox: Postbox, _ f: @escaping (ContentPrivacySettings) -> ContentPrivacySettings) -> Signal { - return postbox.transaction { transaction -> Void in - var updated: ContentPrivacySettings? - transaction.updatePreferencesEntry(key: PreferencesKeys.contentPrivacySettings, { current in - if let current = current?.get(ContentPrivacySettings.self) { - updated = f(current) - return PreferencesEntry(updated) - } else { - updated = f(ContentPrivacySettings.defaultSettings) - return PreferencesEntry(updated) - } - }) - } -} diff --git a/submodules/TelegramCore/Sources/SplitTest.swift b/submodules/TelegramCore/Sources/SplitTest.swift index 84f6211ee6..4bce45abdd 100644 --- a/submodules/TelegramCore/Sources/SplitTest.swift +++ b/submodules/TelegramCore/Sources/SplitTest.swift @@ -24,7 +24,7 @@ extension SplitTest { public func addEvent(_ event: Self.Event, data: JSON = []) { if let bucket = self.bucket { //TODO: merge additional data - addAppLogEvent(postbox: self.postbox, type: event.rawValue, data: ["bucket": bucket]) + _internal_addAppLogEvent(postbox: self.postbox, type: event.rawValue, data: ["bucket": bucket]) } } } diff --git a/submodules/TelegramCore/Sources/State/CallSessionManager.swift b/submodules/TelegramCore/Sources/State/CallSessionManager.swift index f5eb58ef58..3c5bfd89ba 100644 --- a/submodules/TelegramCore/Sources/State/CallSessionManager.swift +++ b/submodules/TelegramCore/Sources/State/CallSessionManager.swift @@ -1423,10 +1423,6 @@ private final class CallSessionManagerContext { } } -public enum CallRequestError { - case generic -} - public final class CallSessionManager { public static func getStableIncomingUUID(stableId: Int64) -> UUID { return StableIncomingUUIDs.shared.with { impl in diff --git a/submodules/TelegramCore/Sources/State/SynchronizeAppLogEventsOperation.swift b/submodules/TelegramCore/Sources/State/SynchronizeAppLogEventsOperation.swift index 2a537b4eca..25aa617acf 100644 --- a/submodules/TelegramCore/Sources/State/SynchronizeAppLogEventsOperation.swift +++ b/submodules/TelegramCore/Sources/State/SynchronizeAppLogEventsOperation.swift @@ -4,7 +4,7 @@ import SwiftSignalKit import MtProtoKit -public func addAppLogEvent(postbox: Postbox, time: Double = Date().timeIntervalSince1970, type: String, peerId: PeerId? = nil, data: JSON = .dictionary([:])) { +func _internal_addAppLogEvent(postbox: Postbox, time: Double = Date().timeIntervalSince1970, type: String, peerId: PeerId? = nil, data: JSON = .dictionary([:])) { let tag: PeerOperationLogTag = OperationLogTags.SynchronizeAppLogEvents let peerId = PeerId(0) let _ = (postbox.transaction { transaction in diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ArchivedStickerPacksInfo.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ArchivedStickerPacksInfo.swift deleted file mode 100644 index 351efd445d..0000000000 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ArchivedStickerPacksInfo.swift +++ /dev/null @@ -1,42 +0,0 @@ -import Foundation -import Postbox - -public struct ArchivedStickerPacksInfoId { - public let rawValue: MemoryBuffer - public let id: Int32 - - init(_ rawValue: MemoryBuffer) { - self.rawValue = rawValue - assert(rawValue.length == 4) - var idValue: Int32 = 0 - memcpy(&idValue, rawValue.memory, 4) - self.id = idValue - } - - init(_ id: Int32) { - self.id = id - var idValue: Int32 = id - self.rawValue = MemoryBuffer(memory: malloc(4)!, capacity: 4, length: 4, freeWhenDone: true) - memcpy(self.rawValue.memory, &idValue, 4) - } -} - -public final class ArchivedStickerPacksInfo: Codable { - public let count: Int32 - - init(count: Int32) { - self.count = count - } - - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: StringCodingKey.self) - - self.count = try container.decode(Int32.self, forKey: "c") - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: StringCodingKey.self) - - try container.encode(self.count, forKey: "c") - } -} diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_AutodownloadSettings.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_AutodownloadSettings.swift index 0af53f8312..5e4d50bd4d 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_AutodownloadSettings.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_AutodownloadSettings.swift @@ -1,11 +1,5 @@ import Postbox -public enum AutodownloadPreset { - case low - case medium - case high -} - public struct AutodownloadPresetSettings: Codable { public let disabled: Bool public let photoSizeMax: Int64 diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_LocalMediaPlaybackInfoAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_LocalMediaPlaybackInfoAttribute.swift deleted file mode 100644 index ecc83d4a59..0000000000 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_LocalMediaPlaybackInfoAttribute.swift +++ /dev/null @@ -1,18 +0,0 @@ -import Foundation -import Postbox - -public class LocalMediaPlaybackInfoAttribute: MessageAttribute { - public let data: Data - - public init(data: Data) { - self.data = data - } - - required public init(decoder: PostboxDecoder) { - self.data = decoder.decodeDataForKey("d") ?? Data() - } - - public func encode(_ encoder: PostboxEncoder) { - encoder.encodeData(self.data, forKey: "d") - } -} diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_NewSessionReview.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_NewSessionReview.swift index 71e3094910..639434860b 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_NewSessionReview.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_NewSessionReview.swift @@ -114,23 +114,6 @@ public func newSessionReviews(postbox: Postbox) -> Signal<[NewSessionReview], No } } -public func addNewSessionReview(postbox: Postbox, item: NewSessionReview) -> Signal { - return postbox.transaction { transaction -> Void in - guard let entry = CodableEntry(item) else { - return - } - transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.NewSessionReviews, item: OrderedItemListEntry(id: NewSessionReview.Id(id: item.id).rawValue, contents: entry), removeTailIfCountExceeds: 200) - } - |> ignoreValues -} - -public func clearNewSessionReviews(postbox: Postbox) -> Signal { - return postbox.transaction { transaction -> Void in - transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.NewSessionReviews, items: []) - } - |> ignoreValues -} - public func removeNewSessionReviews(postbox: Postbox, ids: [Int64]) -> Signal { return postbox.transaction { transaction -> Void in for id in ids { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index c999ba735b..ad6480a0d2 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -653,34 +653,6 @@ public enum TelegramMediaFileAttribute: PostboxCoding, Equatable { } } -public enum TelegramMediaFileReference: PostboxCoding, Equatable { - case cloud(fileId: Int64, accessHash: Int64, fileReference: Data?) - - public init(decoder: PostboxDecoder) { - switch decoder.decodeInt32ForKey("_v", orElse: 0) { - case 0: - self = .cloud(fileId: decoder.decodeInt64ForKey("i", orElse: 0), accessHash: decoder.decodeInt64ForKey("h", orElse: 0), fileReference: decoder.decodeBytesForKey("fr")?.makeData()) - default: - self = .cloud(fileId: 0, accessHash: 0, fileReference: nil) - assertionFailure() - } - } - - public func encode(_ encoder: PostboxEncoder) { - switch self { - case let .cloud(imageId, accessHash, fileReference): - encoder.encodeInt32(0, forKey: "_v") - encoder.encodeInt64(imageId, forKey: "i") - encoder.encodeInt64(accessHash, forKey: "h") - if let fileReference = fileReference { - encoder.encodeBytes(MemoryBuffer(data: fileReference), forKey: "fr") - } else { - encoder.encodeNil(forKey: "fr") - } - } - } -} - public enum TelegramMediaFileDecodingError: Error { case generic } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_VoipConfiguration.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_VoipConfiguration.swift index c91b598a8b..76f3957519 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_VoipConfiguration.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_VoipConfiguration.swift @@ -1,12 +1,6 @@ import Foundation import Postbox -public enum VoiceCallP2PMode: Int32 { - case never = 0 - case contacts = 1 - case always = 2 -} - public struct VoipConfiguration: Codable, Equatable { public var serializedData: String? diff --git a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift index aeda4da023..7b4e1d2a21 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift @@ -15,6 +15,10 @@ public extension TelegramEngine { return _internal_acceptTermsOfService(account: self.account, id: id) } + public func addAppLogEvent(time: Double = Date().timeIntervalSince1970, type: String, data: JSON = .dictionary([:])) { + _internal_addAppLogEvent(postbox: self.account.postbox, time: time, type: type, peerId: nil, data: data) + } + public func requestChangeAccountPhoneNumberVerification(apiId: Int32, apiHash: String, phoneNumber: String, pushNotificationConfiguration: AuthorizationCodePushNotificationConfiguration?, firebaseSecretStream: Signal<[String: String], NoError>) -> Signal { return _internal_requestChangeAccountPhoneNumberVerification(account: self.account, apiId: apiId, apiHash: apiHash, phoneNumber: phoneNumber, pushNotificationConfiguration: pushNotificationConfiguration, firebaseSecretStream: firebaseSecretStream) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Auth/TwoStepVerification.swift b/submodules/TelegramCore/Sources/TelegramEngine/Auth/TwoStepVerification.swift index d0e005a8ae..1fd31b354e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Auth/TwoStepVerification.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Auth/TwoStepVerification.swift @@ -337,13 +337,6 @@ func _internal_requestTwoStepVerificationPasswordRecoveryCode(network: Network) } } -public enum RecoverTwoStepVerificationPasswordError { - case generic - case codeExpired - case limitExceeded - case invalidCode -} - func _internal_cachedTwoStepPasswordToken(postbox: Postbox) -> Signal { return postbox.transaction { transaction -> TemporaryTwoStepPasswordToken? in let key = ValueBoxKey(length: 1) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift index c82eabeb16..711546a2fc 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift @@ -3415,10 +3415,6 @@ func _internal_revokeConferenceInviteLink(account: Account, reference: InternalG } } -public enum ConfirmAddConferenceParticipantError { - case generic -} - func _internal_pollConferenceCallBlockchain(network: Network, reference: InternalGroupCallReference, subChainId: Int, offset: Int, limit: Int) -> Signal<(blocks: [Data], nextOffset: Int)?, NoError> { return network.request(Api.functions.phone.getGroupCallChainBlocks(call: reference.apiInputGroupCall, subChainId: Int32(subChainId), offset: Int32(offset), limit: Int32(limit))) |> map(Optional.init) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift index cb765c543f..e874239521 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift @@ -202,10 +202,6 @@ func _internal_sendAppStoreReceipt(postbox: Postbox, network: Network, stateMana } } -public enum RestoreAppStoreReceiptError { - case generic -} - func _internal_canPurchasePremium(postbox: Postbox, network: Network, purpose: AppStoreTransactionPurpose) -> Signal { return apiInputStorePaymentPurpose(postbox: postbox, purpose: purpose) |> mapToSignal { purpose -> Signal in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift index 8629381181..efa36b984c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift @@ -4,18 +4,6 @@ import SwiftSignalKit import TelegramApi -public struct ChatListFilteringConfiguration: Equatable { - public let isEnabled: Bool - - public init(appConfiguration: AppConfiguration) { - var isEnabled = false - if let data = appConfiguration.data, let value = data["dialog_filters_enabled"] as? Bool, value { - isEnabled = true - } - self.isEnabled = isEnabled - } -} - public struct ChatListFilterPeerCategories: OptionSet, Hashable { public var rawValue: Int32 diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ResolvePeerByName.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ResolvePeerByName.swift index 2e290468fb..21698d63bf 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ResolvePeerByName.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ResolvePeerByName.swift @@ -3,17 +3,6 @@ import Postbox import TelegramApi import SwiftSignalKit -public enum ResolvePeerByNameOptionCached { - case none - case cached - case cachedIfLaterThan(timestamp: Int32) -} - -public enum ResolvePeerByNameOptionRemote { - case updateIfEarlierThan(timestamp: Int32) - case update -} - public enum ResolvePeerIdByNameResult { case progress case result(PeerId?) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SaveSecureIdValue.swift b/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SaveSecureIdValue.swift index 818d662be9..a629a77757 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SaveSecureIdValue.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SaveSecureIdValue.swift @@ -276,44 +276,6 @@ public func deleteSecureIdValues(network: Network, keys: Set) } } -public func dropSecureId(network: Network, currentPassword: String) -> Signal { - return _internal_twoStepAuthData(network) - |> mapError { _ -> AuthorizationPasswordVerificationError in - return .generic - } - |> mapToSignal { authData -> Signal in - let checkPassword: Api.InputCheckPasswordSRP - if let currentPasswordDerivation = authData.currentPasswordDerivation, let srpSessionData = authData.srpSessionData { - let kdfResult = passwordKDF(encryptionProvider: network.encryptionProvider, password: currentPassword, derivation: currentPasswordDerivation, srpSessionData: srpSessionData) - if let kdfResult = kdfResult { - checkPassword = .inputCheckPasswordSRP(.init(srpId: kdfResult.id, A: Buffer(data: kdfResult.A), M1: Buffer(data: kdfResult.M1))) - } else { - return .fail(.generic) - } - } else { - checkPassword = .inputCheckPasswordEmpty - } - - let settings = network.request(Api.functions.account.getPasswordSettings(password: checkPassword), automaticFloodWait: false) - |> mapError { error in - return AuthorizationPasswordVerificationError.generic - } - - return settings - |> mapToSignal { value -> Signal in - switch value { - case .passwordSettings: - var flags: Int32 = 0 - flags |= (1 << 2) - return network.request(Api.functions.account.updatePasswordSettings(password: .inputCheckPasswordEmpty, newSettings: .passwordInputSettings(.init(flags: flags, newAlgo: nil, newPasswordHash: nil, hint: nil, email: nil, newSecureSettings: nil))), automaticFloodWait: false) - |> map { _ in } - |> mapError { _ in - return AuthorizationPasswordVerificationError.generic - } - } - } - } -} public enum GetAllSecureIdValuesError { case generic diff --git a/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SecureIdValueAccessContext.swift b/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SecureIdValueAccessContext.swift index 88bc31d1ff..90c64deab8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SecureIdValueAccessContext.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/SecureId/SecureIdValueAccessContext.swift @@ -15,10 +15,6 @@ public struct SecureIdValueAccessContext: Equatable { } } -public func generateSecureIdValueEmptyAccessContext() -> SecureIdValueAccessContext? { - return SecureIdValueAccessContext(secret: Data(), id: 0) -} - public func generateSecureIdValueAccessContext() -> SecureIdValueAccessContext? { guard let secret = generateSecureSecretData() else { return nil diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Themes/TelegramEngineThemes.swift b/submodules/TelegramCore/Sources/TelegramEngine/Themes/TelegramEngineThemes.swift index b6b890c3a7..c4c5f760c8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Themes/TelegramEngineThemes.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Themes/TelegramEngineThemes.swift @@ -12,6 +12,14 @@ public extension TelegramEngine { public func getChatThemes(accountManager: AccountManager, forceUpdate: Bool = false, onlyCached: Bool = false) -> Signal<[TelegramTheme], NoError> { return _internal_getChatThemes(accountManager: accountManager, network: self.account.network, forceUpdate: forceUpdate, onlyCached: onlyCached) } + + public func themes(accountManager: AccountManager, forceUpdate: Bool = false) -> Signal<[TelegramTheme], NoError> { + return _internal_telegramThemes(postbox: self.account.postbox, network: self.account.network, accountManager: accountManager, forceUpdate: forceUpdate) + } + + public func wallpapers(forceUpdate: Bool = false) -> Signal<[TelegramWallpaper], NoError> { + return _internal_telegramWallpapers(postbox: self.account.postbox, network: self.account.network, forceUpdate: forceUpdate) + } public func setChatTheme(peerId: PeerId, chatTheme: ChatTheme?) -> Signal { return _internal_setChatTheme(account: self.account, peerId: peerId, chatTheme: chatTheme) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Utils/EnginePostboxCoding.swift b/submodules/TelegramCore/Sources/TelegramEngine/Utils/EnginePostboxCoding.swift index 9d0752d94e..23714d0d0a 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Utils/EnginePostboxCoding.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Utils/EnginePostboxCoding.swift @@ -4,6 +4,7 @@ public typealias EngineMemoryBuffer = MemoryBuffer public typealias EnginePostboxDecoder = PostboxDecoder public typealias EnginePostboxEncoder = PostboxEncoder public typealias EngineAdaptedPostboxDecoder = AdaptedPostboxDecoder +public typealias EngineAdaptedPostboxEncoder = AdaptedPostboxEncoder public typealias EngineItemCollectionId = ItemCollectionId public typealias EngineStoryId = StoryId public typealias EngineFetchResourceSourceType = FetchResourceSourceType @@ -18,6 +19,7 @@ public typealias EngineValueBoxEncryptionParameters = ValueBoxEncryptionParamete public typealias EngineMessageAndThreadId = MessageAndThreadId public typealias EnginePeerStoryStats = PeerStoryStats public typealias EngineMessageHistoryAnchorIndex = MessageHistoryAnchorIndex +public typealias EngineMessageHistoryEntryLocation = MessageHistoryEntryLocation public typealias EngineChatListTotalUnreadStateCategory = ChatListTotalUnreadStateCategory public typealias EngineChatListTotalUnreadStateStats = ChatListTotalUnreadStateStats public typealias EngineChatListTotalUnreadState = ChatListTotalUnreadState @@ -28,8 +30,28 @@ public typealias EngineCachedMediaResourceRepresentationResult = CachedMediaReso public typealias EngineMediaResourceDataFetchResult = MediaResourceDataFetchResult public typealias EngineMediaResourceDataFetchError = MediaResourceDataFetchError public typealias EngineMediaResourceStatus = MediaResourceStatus +public typealias EnginePostboxCoding = PostboxCoding +public typealias EngineRawItemCollectionInfo = ItemCollectionInfo +public typealias EngineRawItemCollectionItem = ItemCollectionItem +public typealias EngineRawMedia = Media +public typealias EngineRawMessage = Message +public typealias EngineRawPeer = Peer +public typealias EngineRawMediaResource = MediaResource +public typealias EngineRawMediaResourceId = MediaResourceId +public typealias EngineRawMediaResourceData = MediaResourceData +public typealias EngineRawMediaResourceDataFetchCopyLocalItem = MediaResourceDataFetchCopyLocalItem +public typealias EngineRawCachedMediaResourceRepresentation = CachedMediaResourceRepresentation +public typealias EngineCachedMediaRepresentationKeepDuration = CachedMediaRepresentationKeepDuration public typealias EngineCachedPeerData = CachedPeerData public func engineFileSize(_ path: String, useTotalFileAllocatedSize: Bool = false) -> Int64? { return fileSize(path, useTotalFileAllocatedSize: useTotalFileAllocatedSize) } + +public func enginePersistentHash32(_ string: String) -> Int32 { + return persistentHash32(string) +} + +public func engineDeclareEncodable(_ type: Any.Type, f: @escaping (EnginePostboxDecoder) -> EnginePostboxCoding) { + declareEncodable(type, f: f) +} diff --git a/submodules/TelegramCore/Sources/Themes.swift b/submodules/TelegramCore/Sources/Themes.swift index 4d8b2d4124..b7d49d7a19 100644 --- a/submodules/TelegramCore/Sources/Themes.swift +++ b/submodules/TelegramCore/Sources/Themes.swift @@ -11,7 +11,7 @@ let telegramThemeFormat = "ios" let telegramThemeFileExtension = "tgios-theme" #endif -public func telegramThemes(postbox: Postbox, network: Network, accountManager: AccountManager?, forceUpdate: Bool = false) -> Signal<[TelegramTheme], NoError> { +func _internal_telegramThemes(postbox: Postbox, network: Network, accountManager: AccountManager?, forceUpdate: Bool = false) -> Signal<[TelegramTheme], NoError> { let fetch: ([TelegramTheme]?, Int64?) -> Signal<[TelegramTheme], NoError> = { current, hash in network.request(Api.functions.account.getThemes(format: telegramThemeFormat, hash: hash ?? 0)) |> retryRequest @@ -145,7 +145,7 @@ private func saveUnsaveTheme(account: Account, accountManager: AccountManager mapToSignal { _ -> Signal in - return telegramThemes(postbox: account.postbox, network: account.network, accountManager: accountManager, forceUpdate: true) + return _internal_telegramThemes(postbox: account.postbox, network: account.network, accountManager: accountManager, forceUpdate: true) |> take(1) |> mapToSignal { _ -> Signal in return .complete() @@ -542,7 +542,7 @@ func managedThemesUpdates(accountManager: AccountManager take(1)).start() } }.start() diff --git a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift index df30e8c937..955b0eccd7 100644 --- a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift +++ b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift @@ -478,18 +478,6 @@ public func peerViewMainPeer(_ view: PeerView) -> Peer? { } } -public func peerViewMonoforumMainPeer(_ view: PeerView) -> Peer? { - if let peer = peerViewMainPeer(view) { - if let channel = peer as? TelegramChannel, channel.flags.contains(.isMonoforum), let linkedMonoforumId = channel.linkedMonoforumId { - return view.peers[linkedMonoforumId] - } else { - return nil - } - } else { - return nil - } -} - public extension RenderedPeer { convenience init(peer: EnginePeer) { self.init(peer: peer._asPeer()) diff --git a/submodules/TelegramCore/Sources/Wallpapers.swift b/submodules/TelegramCore/Sources/Wallpapers.swift index 84985dc5dd..670afaa857 100644 --- a/submodules/TelegramCore/Sources/Wallpapers.swift +++ b/submodules/TelegramCore/Sources/Wallpapers.swift @@ -4,7 +4,7 @@ import SwiftSignalKit import TelegramApi -public func telegramWallpapers(postbox: Postbox, network: Network, forceUpdate: Bool = false) -> Signal<[TelegramWallpaper], NoError> { +func _internal_telegramWallpapers(postbox: Postbox, network: Network, forceUpdate: Bool = false) -> Signal<[TelegramWallpaper], NoError> { let fetch: ([TelegramWallpaper]?, Int64?) -> Signal<[TelegramWallpaper], NoError> = { current, hash in network.request(Api.functions.account.getWallPapers(hash: hash ?? 0)) |> retryRequestIfNotFrozen diff --git a/submodules/TelegramCore/Sources/WebpagePreview.swift b/submodules/TelegramCore/Sources/WebpagePreview.swift index 926417f85e..770233baff 100644 --- a/submodules/TelegramCore/Sources/WebpagePreview.swift +++ b/submodules/TelegramCore/Sources/WebpagePreview.swift @@ -39,10 +39,6 @@ public enum WebpagePreviewWithProgressResult { case progress(Float) } -public func normalizedWebpagePreviewUrl(url: String) -> String { - return url -} - public func webpagePreviewWithProgress(account: Account, urls: [String], webpageId: MediaId? = nil, forPeerId: PeerId? = nil) -> Signal { return account.postbox.transaction { transaction -> Signal in if let webpageId = webpageId, let webpage = transaction.getMedia(webpageId) as? TelegramMediaWebpage, let url = webpage.content.url { diff --git a/submodules/TelegramPresentationData/Sources/PresentationData.swift b/submodules/TelegramPresentationData/Sources/PresentationData.swift index ca3e549ff3..f557750fd4 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationData.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationData.swift @@ -504,11 +504,6 @@ private func automaticThemeShouldSwitchNow(_ parameters: AutomaticThemeSwitchPar } } -public func automaticThemeShouldSwitchNow(settings: AutomaticThemeSwitchSetting, systemUserInterfaceStyle: WindowUserInterfaceStyle) -> Bool { - let parameters = AutomaticThemeSwitchParameters(settings: settings) - return automaticThemeShouldSwitchNow(parameters, systemUserInterfaceStyle: systemUserInterfaceStyle) -} - private func automaticThemeShouldSwitch(_ settings: AutomaticThemeSwitchSetting, systemUserInterfaceStyle: WindowUserInterfaceStyle) -> Signal { if settings.force { return .single(true) diff --git a/submodules/TelegramUI/Components/Chat/ChatButtonKeyboardInputNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatButtonKeyboardInputNode/BUILD index d124e45634..9396769890 100644 --- a/submodules/TelegramUI/Components/Chat/ChatButtonKeyboardInputNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatButtonKeyboardInputNode/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/Display", "//submodules/AsyncDisplayKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/Chat/ChatHistorySearchContainerNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatHistorySearchContainerNode/BUILD index f192f2f409..4bba448043 100644 --- a/submodules/TelegramUI/Components/Chat/ChatHistorySearchContainerNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatHistorySearchContainerNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/TelegramPresentationData", "//submodules/MergeLists", diff --git a/submodules/TelegramUI/Components/Chat/ChatHistorySearchContainerNode/Sources/ChatHistorySearchContainerNode.swift b/submodules/TelegramUI/Components/Chat/ChatHistorySearchContainerNode/Sources/ChatHistorySearchContainerNode.swift index 8e857273f7..c9ca8638b1 100644 --- a/submodules/TelegramUI/Components/Chat/ChatHistorySearchContainerNode/Sources/ChatHistorySearchContainerNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatHistorySearchContainerNode/Sources/ChatHistorySearchContainerNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import MergeLists @@ -35,11 +34,11 @@ private extension ListMessageItemInteraction { } private enum ChatHistorySearchEntryStableId: Hashable { - case messageId(MessageId) + case messageId(EngineMessage.Id) } private enum ChatHistorySearchEntry: Comparable, Identifiable { - case message(Message, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationFontSize) + case message(EngineRawMessage, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationFontSize) var stableId: ChatHistorySearchEntryStableId { switch self { @@ -88,7 +87,7 @@ private enum ChatHistorySearchEntry: Comparable, Identifiable { } } - func item(context: AccountContext, peerId: PeerId, interaction: ChatControllerInteraction) -> ListViewItem { + func item(context: AccountContext, peerId: EnginePeer.Id, interaction: ChatControllerInteraction) -> ListViewItem { switch self { case let .message(message, theme, strings, dateTimeFormat, fontSize): return ListMessageItem(presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: theme, wallpaper: .builtin(WallpaperSettings())), fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, disableAnimations: false, largeEmoji: false, chatBubbleCorners: PresentationChatBubbleCorners(mainRadius: 0.0, auxiliaryRadius: 0.0, mergeBubbleCorners: false)), context: context, chatLocation: .peer(id: peerId), interaction: ListMessageItemInteraction(controllerInteraction: interaction), message: message, selection: .none, displayHeader: true) @@ -104,7 +103,7 @@ private struct ChatHistorySearchContainerTransition { let displayingResults: Bool } -private func chatHistorySearchContainerPreparedTransition(from fromEntries: [ChatHistorySearchEntry], to toEntries: [ChatHistorySearchEntry], query: String, displayingResults: Bool, context: AccountContext, peerId: PeerId, interaction: ChatControllerInteraction) -> ChatHistorySearchContainerTransition { +private func chatHistorySearchContainerPreparedTransition(from fromEntries: [ChatHistorySearchEntry], to toEntries: [ChatHistorySearchEntry], query: String, displayingResults: Bool, context: AccountContext, peerId: EnginePeer.Id, interaction: ChatControllerInteraction) -> ChatHistorySearchContainerTransition { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } @@ -126,7 +125,7 @@ public final class ChatHistorySearchContainerNode: SearchDisplayControllerConten private var containerLayout: (ContainerViewLayout, CGFloat)? private var currentEntries: [ChatHistorySearchEntry]? - public var currentMessages: [MessageId: Message]? + public var currentMessages: [EngineMessage.Id: EngineRawMessage]? private var currentQuery: String? private let searchQuery = Promise() @@ -149,7 +148,7 @@ public final class ChatHistorySearchContainerNode: SearchDisplayControllerConten return true } - public init(context: AccountContext, peerId: PeerId, threadId: Int64?, tagMask: MessageTags, interfaceInteraction: ChatControllerInteraction) { + public init(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64?, tagMask: EngineMessage.Tags, interfaceInteraction: ChatControllerInteraction) { self.context = context let presentationData = context.sharedContext.currentPresentationData.with { $0 } @@ -194,14 +193,14 @@ public final class ChatHistorySearchContainerNode: SearchDisplayControllerConten self.searchQueryDisposable.set((self.searchQuery.get() |> deliverOnMainQueue).startStrict(next: { [weak self] query in if let strongSelf = self { - let signal: Signal<([ChatHistorySearchEntry], [MessageId: Message])?, NoError> + let signal: Signal<([ChatHistorySearchEntry], [EngineMessage.Id: EngineRawMessage])?, NoError> if let query = query, !query.isEmpty { - let foundRemoteMessages: Signal<[Message], NoError> = context.engine.messages.searchMessages(location: .peer(peerId: peerId, fromId: nil, tags: tagMask, reactions: nil, threadId: threadId, minDate: nil, maxDate: nil), query: query, state: nil) + let foundRemoteMessages: Signal<[EngineRawMessage], NoError> = context.engine.messages.searchMessages(location: .peer(peerId: peerId, fromId: nil, tags: tagMask, reactions: nil, threadId: threadId, minDate: nil, maxDate: nil), query: query, state: nil) |> map { $0.0.messages } |> delay(0.2, queue: Queue.concurrentDefaultQueue()) signal = combineLatest(foundRemoteMessages, themeAndStringsPromise.get()) - |> map { messages, themeAndStrings -> ([ChatHistorySearchEntry], [MessageId: Message])? in + |> map { messages, themeAndStrings -> ([ChatHistorySearchEntry], [EngineMessage.Id: EngineRawMessage])? in if messages.isEmpty { return ([], [:]) } else { @@ -377,7 +376,7 @@ public final class ChatHistorySearchContainerNode: SearchDisplayControllerConten } } - public func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + public func transitionNodeForGallery(messageId: EngineMessage.Id, media: EngineRawMedia) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? self.listNode.forEachItemNode { itemNode in if let itemNode = itemNode as? ChatMessageItemView { diff --git a/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/BUILD b/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/BUILD index 9c809d2612..3804ac777b 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/BUILD @@ -14,7 +14,6 @@ swift_library( "//submodules/TelegramCore", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/AsyncDisplayKit", - "//submodules/Postbox", "//submodules/TelegramPresentationData", "//submodules/StickerResources", "//submodules/AccountContext", diff --git a/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/Sources/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/Sources/ChatMediaInputStickerGridItem.swift index 8a888df6a5..4ce9960037 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/Sources/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem/Sources/ChatMediaInputStickerGridItem.swift @@ -4,7 +4,6 @@ import Display import TelegramCore import SwiftSignalKit import AsyncDisplayKit -import Postbox import TelegramPresentationData import StickerResources import AccountContext @@ -21,7 +20,7 @@ public enum ChatMediaInputStickerGridSectionAccessory { } public final class ChatMediaInputStickerGridSection: GridSection { - public let collectionId: ItemCollectionId + public let collectionId: EngineItemCollectionId public let collectionInfo: StickerPackCollectionInfo? public let accessory: ChatMediaInputStickerGridSectionAccessory public let interaction: ChatMediaInputNodeInteraction @@ -32,7 +31,7 @@ public final class ChatMediaInputStickerGridSection: GridSection { return self.collectionId.hashValue } - public init(collectionId: ItemCollectionId, collectionInfo: StickerPackCollectionInfo?, accessory: ChatMediaInputStickerGridSectionAccessory, theme: PresentationTheme, interaction: ChatMediaInputNodeInteraction) { + public init(collectionId: EngineItemCollectionId, collectionInfo: StickerPackCollectionInfo?, accessory: ChatMediaInputStickerGridSectionAccessory, theme: PresentationTheme, interaction: ChatMediaInputNodeInteraction) { self.collectionId = collectionId self.collectionInfo = collectionInfo self.accessory = accessory @@ -118,7 +117,7 @@ public final class ChatMediaInputStickerGridSectionNode: ASDisplayNode { public final class ChatMediaInputStickerGridItem: GridItem { public let context: AccountContext - public let index: ItemCollectionViewEntryIndex + public let index: EngineItemCollectionViewEntryIndex public let stickerItem: StickerPackItem public let selected: () -> Void public let interfaceInteraction: ChatControllerInteraction? @@ -129,7 +128,7 @@ public final class ChatMediaInputStickerGridItem: GridItem { public let section: GridSection? - public init(context: AccountContext, collectionId: ItemCollectionId, stickerPackInfo: StickerPackCollectionInfo?, index: ItemCollectionViewEntryIndex, stickerItem: StickerPackItem, canManagePeerSpecificPack: Bool?, interfaceInteraction: ChatControllerInteraction?, inputNodeInteraction: ChatMediaInputNodeInteraction, hasAccessory: Bool, theme: PresentationTheme, large: Bool = false, isLocked: Bool = false, selected: @escaping () -> Void) { + public init(context: AccountContext, collectionId: EngineItemCollectionId, stickerPackInfo: StickerPackCollectionInfo?, index: EngineItemCollectionViewEntryIndex, stickerItem: StickerPackItem, canManagePeerSpecificPack: Bool?, interfaceInteraction: ChatControllerInteraction?, inputNodeInteraction: ChatMediaInputNodeInteraction, hasAccessory: Bool, theme: PresentationTheme, large: Bool = false, isLocked: Bool = false, selected: @escaping () -> Void) { self.context = context self.index = index self.stickerItem = stickerItem diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift index 72528395d0..6f923f5d50 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/Sources/ChatMessageActionBubbleContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import AccountContext import TelegramPresentationData @@ -26,7 +25,7 @@ import ComponentFlow import ReactionSelectionNode import MultilineTextComponent -private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: Message, messageCount: Int? = nil, accountPeerId: PeerId, forForumOverview: Bool) -> NSAttributedString? { +private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineRawMessage, messageCount: Int? = nil, accountPeerId: EnginePeer.Id, forForumOverview: Bool) -> NSAttributedString? { return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: EngineMessage(message), messageCount: messageCount, accountPeerId: accountPeerId, forChatList: false, forForumOverview: forForumOverview) } @@ -108,7 +107,7 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { super.didLoad() } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if let imageNode = self.imageNode, self.item?.message.id == messageId { return (imageNode, imageNode.bounds, { [weak self] in guard let strongSelf = self, let imageNode = strongSelf.imageNode else { @@ -137,9 +136,9 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { } } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { var mediaHidden = false - var currentMedia: Media? + var currentMedia: EngineRawMedia? if let item = item { mediaLoop: for media in item.message.media { if let media = media as? TelegramMediaAction { @@ -552,7 +551,7 @@ public class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { strongSelf.mediaBackgroundNode.image = backgroundImage if let image = image, let video = image.videoRepresentations.last, let id = image.id?.id { - let videoFileReference = FileMediaReference.message(message: MessageReference(item.message), media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: image.representations, videoThumbnails: [], immediateThumbnailData: image.immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [], preloadSize: nil, coverTime: nil, videoCodec: nil)], alternativeRepresentations: [])) + let videoFileReference = FileMediaReference.message(message: MessageReference(item.message), media: TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: image.representations, videoThumbnails: [], immediateThumbnailData: image.immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [], preloadSize: nil, coverTime: nil, videoCodec: nil)], alternativeRepresentations: [])) let videoContent = NativeVideoContent(id: .profileVideo(id, "action"), userLocation: .peer(item.message.id.peerId), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear, storeAfterDownload: nil) if videoContent.id != strongSelf.videoContent?.id { let mediaManager = item.context.sharedContext.mediaManager diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode/BUILD index 3869cfb7c9..1bd7f3cb75 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/Display", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/TelegramUIPreferences", "//submodules/TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode/Sources/ChatMessageBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode/Sources/ChatMessageBubbleContentNode.swift index 539164a44f..684c404552 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode/Sources/ChatMessageBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode/Sources/ChatMessageBubbleContentNode.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import Display -import Postbox import TelegramCore import TelegramUIPreferences import TelegramPresentationData @@ -144,14 +143,14 @@ public struct ChatMessageBubbleContentTapAction { case url(Url) case phone(String) case textMention(String) - case peerMention(peerId: PeerId, mention: String, openProfile: Bool) + case peerMention(peerId: EnginePeer.Id, mention: String, openProfile: Bool) case botCommand(String) case hashtag(String?, String) case instantPage case wallpaper case theme - case call(peerId: PeerId, isVideo: Bool) - case conferenceCall(message: Message) + case call(peerId: EnginePeer.Id, isVideo: Bool) + case conferenceCall(message: EngineRawMessage) case openMessage case timecode(Double, String) case tooltip(String, ASDisplayNode?, CGRect?) @@ -162,7 +161,7 @@ public struct ChatMessageBubbleContentTapAction { case date(Int32, String) case largeEmoji(String, String?, TelegramMediaFile) case customEmoji(TelegramMediaFile) - case externalInstantPage(url: Url, webpageId: MediaId, anchor: String?) + case externalInstantPage(url: Url, webpageId: EngineMedia.Id, anchor: String?) case custom(() -> Void) } @@ -182,8 +181,8 @@ public struct ChatMessageBubbleContentTapAction { public final class ChatMessageBubbleContentItem { public let context: AccountContext public let controllerInteraction: ChatControllerInteraction - public let message: Message - public let topMessage: Message + public let message: EngineRawMessage + public let topMessage: EngineRawMessage public let content: ChatMessageItemContent public let read: Bool public let chatLocation: ChatLocation @@ -193,7 +192,7 @@ public final class ChatMessageBubbleContentItem { public let isItemPinned: Bool public let isItemEdited: Bool - public init(context: AccountContext, controllerInteraction: ChatControllerInteraction, message: Message, topMessage: Message, content: ChatMessageItemContent, read: Bool, chatLocation: ChatLocation, presentationData: ChatPresentationData, associatedData: ChatMessageItemAssociatedData, attributes: ChatMessageEntryAttributes, isItemPinned: Bool, isItemEdited: Bool) { + public init(context: AccountContext, controllerInteraction: ChatControllerInteraction, message: EngineRawMessage, topMessage: EngineRawMessage, content: ChatMessageItemContent, read: Bool, chatLocation: ChatLocation, presentationData: ChatPresentationData, associatedData: ChatMessageItemAssociatedData, attributes: ChatMessageEntryAttributes, isItemPinned: Bool, isItemEdited: Bool) { self.context = context self.controllerInteraction = controllerInteraction self.message = message @@ -258,7 +257,7 @@ open class ChatMessageBubbleContentNode: ASDisplayNode { }) } - open func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + open func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { return nil } @@ -266,11 +265,11 @@ open class ChatMessageBubbleContentNode: ASDisplayNode { return nil } - open func updateHiddenMedia(_ media: [Media]?) -> Bool { + open func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { return false } - open func updateSearchTextHighlightState(text: String?, messages: [MessageIndex]?) { + open func updateSearchTextHighlightState(text: String?, messages: [EngineMessage.Index]?) { } open func updateAutomaticMediaDownloadSettings(_ settings: MediaAutoDownloadSettings) { @@ -317,7 +316,7 @@ open class ChatMessageBubbleContentNode: ASDisplayNode { return nil } - open func targetForStoryTransition(id: StoryId) -> UIView? { + open func targetForStoryTransition(id: EngineStoryId) -> UIView? { return nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageCommentFooterContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageCommentFooterContentNode/BUILD index 488db161a5..f50ac6e3b5 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageCommentFooterContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageCommentFooterContentNode/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/Display", "//submodules/AsyncDisplayKit", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousDescriptionContentNode/Sources/ChatMessageEventLogPreviousDescriptionContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousDescriptionContentNode/Sources/ChatMessageEventLogPreviousDescriptionContentNode.swift index d17580bb8f..ae9d2538c0 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousDescriptionContentNode/Sources/ChatMessageEventLogPreviousDescriptionContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousDescriptionContentNode/Sources/ChatMessageEventLogPreviousDescriptionContentNode.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import Display import AsyncDisplayKit import SwiftSignalKit @@ -50,7 +49,7 @@ public final class ChatMessageEventLogPreviousDescriptionContentNode: ChatMessag } else { text = item.message.text } - let mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)? = nil + let mediaAndFlags: ([EngineRawMedia], ChatMessageAttachedContentNodeMediaFlags)? = nil let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer) @@ -103,11 +102,11 @@ public final class ChatMessageEventLogPreviousDescriptionContentNode: ChatMessag return ChatMessageBubbleContentTapAction(content: .none) } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { return self.contentNode.updateHiddenMedia(media) } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id != messageId { return nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousLinkContentNode/Sources/ChatMessageEventLogPreviousLinkContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousLinkContentNode/Sources/ChatMessageEventLogPreviousLinkContentNode.swift index 0b420f0c7f..202bca13b2 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousLinkContentNode/Sources/ChatMessageEventLogPreviousLinkContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousLinkContentNode/Sources/ChatMessageEventLogPreviousLinkContentNode.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import Display import AsyncDisplayKit import SwiftSignalKit @@ -45,7 +44,7 @@ public final class ChatMessageEventLogPreviousLinkContentNode: ChatMessageBubble let title: String = item.message.text.contains("\n") ? item.presentationData.strings.Channel_AdminLog_MessagePreviousLinks : item.presentationData.strings.Channel_AdminLog_MessagePreviousLink let text: String = item.message.text - let mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)? = nil + let mediaAndFlags: ([EngineRawMedia], ChatMessageAttachedContentNodeMediaFlags)? = nil let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer) @@ -98,11 +97,11 @@ public final class ChatMessageEventLogPreviousLinkContentNode: ChatMessageBubble return ChatMessageBubbleContentTapAction(content: .none) } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { return self.contentNode.updateHiddenMedia(media) } - - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id != messageId { return nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousMessageContentNode/Sources/ChatMessageEventLogPreviousMessageContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousMessageContentNode/Sources/ChatMessageEventLogPreviousMessageContentNode.swift index d3ec9d1355..773b6c1849 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousMessageContentNode/Sources/ChatMessageEventLogPreviousMessageContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousMessageContentNode/Sources/ChatMessageEventLogPreviousMessageContentNode.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import Display import AsyncDisplayKit import SwiftSignalKit @@ -50,7 +49,7 @@ public final class ChatMessageEventLogPreviousMessageContentNode: ChatMessageBub } else { text = item.message.text } - let mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)? = nil + let mediaAndFlags: ([EngineRawMedia], ChatMessageAttachedContentNodeMediaFlags)? = nil let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer) @@ -105,11 +104,11 @@ public final class ChatMessageEventLogPreviousMessageContentNode: ChatMessageBub self.contentNode.updateTouchesAtPoint(point.flatMap { $0.offsetBy(dx: -contentNodeFrame.minX, dy: -contentNodeFrame.minY) }) } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { return self.contentNode.updateHiddenMedia(media) } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id != messageId { return nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageFileBubbleContentNode/Sources/ChatMessageFileBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageFileBubbleContentNode/Sources/ChatMessageFileBubbleContentNode.swift index 1aebf306db..877c143a8c 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageFileBubbleContentNode/Sources/ChatMessageFileBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageFileBubbleContentNode/Sources/ChatMessageFileBubbleContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramUIPreferences import ComponentFlow @@ -201,7 +200,7 @@ public class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode { } } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id == messageId { return self.interactiveFileNode.transitionNode(media: media) } else { @@ -209,7 +208,7 @@ public class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode { } } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { return self.interactiveFileNode.updateHiddenMedia(media) } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageGameBubbleContentNode/Sources/ChatMessageGameBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageGameBubbleContentNode/Sources/ChatMessageGameBubbleContentNode.swift index 647345b103..ca722d6fde 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageGameBubbleContentNode/Sources/ChatMessageGameBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageGameBubbleContentNode/Sources/ChatMessageGameBubbleContentNode.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import Display import AsyncDisplayKit import SwiftSignalKit @@ -67,7 +66,7 @@ public final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNod var title: String? var text: String? - var mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)? + var mediaAndFlags: ([EngineRawMedia], ChatMessageAttachedContentNodeMediaFlags)? if let game = game { title = game.title @@ -132,11 +131,11 @@ public final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNod return ChatMessageBubbleContentTapAction(content: .none) } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { return self.contentNode.updateHiddenMedia(media) } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id != messageId { return nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoBubbleContentNode/BUILD index becb2bbd06..5ec7467b05 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoBubbleContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/TelegramUIPreferences", "//submodules/ComponentFlow", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoBubbleContentNode/Sources/ChatMessageInstantVideoBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoBubbleContentNode/Sources/ChatMessageInstantVideoBubbleContentNode.swift index 0b9936d978..1b6e4b11d6 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoBubbleContentNode/Sources/ChatMessageInstantVideoBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoBubbleContentNode/Sources/ChatMessageInstantVideoBubbleContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramUIPreferences import ComponentFlow @@ -393,11 +392,11 @@ public class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentN } } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { return nil } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { return false } @@ -465,7 +464,7 @@ public class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentN return nil } - override public func targetForStoryTransition(id: StoryId) -> UIView? { + override public func targetForStoryTransition(id: EngineStoryId) -> UIView? { return self.interactiveVideoNode.targetForStoryTransition(id: id) } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/BUILD index 5716eabe19..1dd6a7760c 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/TelegramPresentationData", "//submodules/TelegramUIPreferences", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift index 2e3e9876cf..f8c3faf696 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -48,7 +47,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, ASGestureReco public var appliedParams: ListViewItemLayoutParams? public var appliedItem: ChatMessageItem? - public var appliedForwardInfo: (Peer?, String?)? + public var appliedForwardInfo: (EngineRawPeer?, String?)? public var appliedHasAvatar = false public var appliedCurrentlyPlaying: Bool? public var appliedAutomaticDownload = false @@ -461,11 +460,11 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, ASGestureReco } } - var replyMessage: Message? + var replyMessage: EngineRawMessage? var replyForward: QuotedReplyMessageAttribute? var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)? var replyInnerSubject: EngineMessageReplyInnerSubject? - var replyStory: StoryId? + var replyStory: EngineStoryId? for attribute in item.message.attributes { if let attribute = attribute as? InlineBotMessageAttribute { var inlineBotNameString: String? @@ -551,7 +550,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, ASGestureReco let availableContentWidth = params.width - params.leftInset - params.rightInset - layoutConstants.bubble.edgeInset * 2.0 - avatarInset - layoutConstants.bubble.contentInsets.left - var forwardSource: Peer? + var forwardSource: EngineRawPeer? var forwardAuthorSignature: String? var forwardInfoSizeApply: (CGSize, (CGFloat) -> ChatMessageForwardInfoNode)? @@ -1513,7 +1512,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, ASGestureReco return nil } - override public func targetForStoryTransition(id: StoryId) -> UIView? { + override public func targetForStoryTransition(id: EngineStoryId) -> UIView? { guard let item = self.item else { return nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInvoiceBubbleContentNode/Sources/ChatMessageInvoiceBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInvoiceBubbleContentNode/Sources/ChatMessageInvoiceBubbleContentNode.swift index 02855854c9..e6034a6550 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInvoiceBubbleContentNode/Sources/ChatMessageInvoiceBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInvoiceBubbleContentNode/Sources/ChatMessageInvoiceBubbleContentNode.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import Display import AsyncDisplayKit import SwiftSignalKit @@ -52,7 +51,7 @@ public final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContent var title: String? var subtitle: NSAttributedString? = nil var text: String? - var mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)? + var mediaAndFlags: ([EngineRawMedia], ChatMessageAttachedContentNodeMediaFlags)? var automaticDownloadSettings = item.controllerInteraction.automaticMediaDownloadSettings if let invoice = invoice { @@ -128,11 +127,11 @@ public final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContent return ChatMessageBubbleContentTapAction(content: .none) } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { return self.contentNode.updateHiddenMedia(media) } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id != messageId { return nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItem/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageItem/BUILD index 8c82069452..df02b6c4ad 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItem/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItem/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItem/Sources/ChatMessageItem.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItem/Sources/ChatMessageItem.swift index f736e8cbee..67ae7c2ef2 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItem/Sources/ChatMessageItem.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItem/Sources/ChatMessageItem.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import AsyncDisplayKit import Display import SwiftSignalKit @@ -12,10 +11,10 @@ import TelegramPresentationData import ChatMessageItemCommon public enum ChatMessageItemContent: Sequence { - case message(message: Message, read: Bool, selection: ChatHistoryMessageSelection, attributes: ChatMessageEntryAttributes, location: MessageHistoryEntryLocation?) - case group(messages: [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)]) - - public func effectivelyIncoming(_ accountPeerId: PeerId, associatedData: ChatMessageItemAssociatedData? = nil) -> Bool { + case message(message: EngineRawMessage, read: Bool, selection: ChatHistoryMessageSelection, attributes: ChatMessageEntryAttributes, location: EngineMessageHistoryEntryLocation?) + case group(messages: [(EngineRawMessage, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, EngineMessageHistoryEntryLocation?)]) + + public func effectivelyIncoming(_ accountPeerId: EnginePeer.Id, associatedData: ChatMessageItemAssociatedData? = nil) -> Bool { if let subject = associatedData?.subject, case let .messageOptions(_, _, info) = subject { if case .forward = info { return false @@ -31,7 +30,7 @@ public enum ChatMessageItemContent: Sequence { } } - public var index: MessageIndex { + public var index: EngineMessage.Index { switch self { case let .message(message, _, _, _, _): return message.index @@ -40,7 +39,7 @@ public enum ChatMessageItemContent: Sequence { } } - public var firstMessage: Message { + public var firstMessage: EngineRawMessage { switch self { case let .message(message, _, _, _, _): return message @@ -58,9 +57,9 @@ public enum ChatMessageItemContent: Sequence { } } - public func makeIterator() -> AnyIterator<(Message, ChatMessageEntryAttributes)> { + public func makeIterator() -> AnyIterator<(EngineRawMessage, ChatMessageEntryAttributes)> { var index = 0 - return AnyIterator { () -> (Message, ChatMessageEntryAttributes)? in + return AnyIterator { () -> (EngineRawMessage, ChatMessageEntryAttributes)? in switch self { case let .message(message, _, _, attributes, _): if index == 0 { @@ -84,10 +83,10 @@ public enum ChatMessageItemContent: Sequence { } public enum ChatMessageItemAdditionalContent { - case eventLogPreviousMessage(Message) - case eventLogPreviousDescription(Message) - case eventLogPreviousLink(Message) - case eventLogGroupedMessages([Message], Bool) + case eventLogPreviousMessage(EngineRawMessage) + case eventLogPreviousDescription(EngineRawMessage) + case eventLogPreviousLink(EngineRawMessage) + case eventLogGroupedMessages([EngineRawMessage], Bool) } public enum ChatMessageMerge: Int32 { @@ -131,12 +130,12 @@ public protocol ChatMessageItem: ListViewItem { var controllerInteraction: ChatControllerInteraction { get } var content: ChatMessageItemContent { get } var disableDate: Bool { get } - var effectiveAuthorId: PeerId? { get } + var effectiveAuthorId: EnginePeer.Id? { get } var additionalContent: ChatMessageItemAdditionalContent? { get } var headers: [ListViewItemHeader] { get } - var message: Message { get } + var message: EngineRawMessage { get } var read: Bool { get } var unsent: Bool { get } var sending: Bool { get } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift index f8c40ccc3d..da8399997d 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import AsyncDisplayKit import Display import SwiftSignalKit @@ -18,7 +17,7 @@ import ChatMessageStickerItemNode import ChatMessageAnimatedStickerItemNode import ChatMessageBubbleItemNode -private func mediaMergeableStyle(_ media: Media) -> ChatMessageMerge { +private func mediaMergeableStyle(_ media: EngineRawMedia) -> ChatMessageMerge { if let story = media as? TelegramMediaStory, story.isMention { return .none } @@ -47,9 +46,9 @@ private func mediaMergeableStyle(_ media: Media) -> ChatMessageMerge { return .fullyMerged } -private func messagesShouldBeMerged(accountPeerId: PeerId, _ lhs: Message, _ rhs: Message) -> ChatMessageMerge { - var lhsEffectiveAuthor: Peer? = lhs.author - var rhsEffectiveAuthor: Peer? = rhs.author +private func messagesShouldBeMerged(accountPeerId: EnginePeer.Id, _ lhs: EngineRawMessage, _ rhs: EngineRawMessage) -> ChatMessageMerge { + var lhsEffectiveAuthor: EngineRawPeer? = lhs.author + var rhsEffectiveAuthor: EngineRawPeer? = rhs.author for attribute in lhs.attributes { if let attribute = attribute as? SourceReferenceMessageAttribute { lhsEffectiveAuthor = lhs.peers[attribute.messageId.peerId] @@ -223,7 +222,7 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible public let controllerInteraction: ChatControllerInteraction public let content: ChatMessageItemContent public let disableDate: Bool - public let effectiveAuthorId: PeerId? + public let effectiveAuthorId: EnginePeer.Id? public let additionalContent: ChatMessageItemAdditionalContent? let dateHeader: ChatMessageDateHeader @@ -232,7 +231,7 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible public let headers: [ListViewItemHeader] - public var message: Message { + public var message: EngineRawMessage { switch self.content { case let .message(message, _, _, _, _): return message @@ -299,10 +298,10 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible var avatarHeader: ChatMessageAvatarHeader? let incoming = content.effectivelyIncoming(self.context.account.peerId) - var effectiveAuthor: Peer? + var effectiveAuthor: EngineRawPeer? var displayAuthorInfo: Bool - let messagePeerId: PeerId = chatLocation.peerId ?? content.firstMessage.id.peerId + let messagePeerId: EnginePeer.Id = chatLocation.peerId ?? content.firstMessage.id.peerId var headerSeparableThreadId: Int64? var headerDisplayPeer: ChatMessageDateHeader.HeaderData? @@ -312,14 +311,14 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible if let forwardInfo = content.firstMessage.forwardInfo { effectiveAuthor = forwardInfo.author if effectiveAuthor == nil, let authorSignature = forwardInfo.authorSignature { - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) + effectiveAuthor = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.Empty, id: EnginePeer.Id.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) } } if let sourceAuthorInfo = content.firstMessage.sourceAuthorInfo { if let originalAuthor = sourceAuthorInfo.originalAuthor, let peer = content.firstMessage.peers[originalAuthor] { effectiveAuthor = peer } else if let authorSignature = sourceAuthorInfo.originalAuthorName { - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) + effectiveAuthor = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.Empty, id: EnginePeer.Id.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) } } if peerId.isVerificationCodes && effectiveAuthor == nil { @@ -360,7 +359,7 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible headerDisplayPeer = ChatMessageDateHeader.HeaderData(contents: .thread(id: threadId, info: threadInfo)) } else if content.firstMessage.threadId == EngineMessage.newTopicThreadId { headerSeparableThreadId = content.firstMessage.threadId - headerDisplayPeer = ChatMessageDateHeader.HeaderData(contents: .thread(id: threadId, info: Message.AssociatedThreadInfo( + headerDisplayPeer = ChatMessageDateHeader.HeaderData(contents: .thread(id: threadId, info: EngineRawMessage.AssociatedThreadInfo( title: presentationData.strings.Chat_MessageHeaderBotNewThread, icon: nil, iconColor: 0, @@ -434,7 +433,7 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible if hasAvatar { if let effectiveAuthor = effectiveAuthor { - var storyStats: PeerStoryStats? + var storyStats: EnginePeerStoryStats? if case .peer(id: context.account.peerId) = chatLocation { } else { switch content { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItemView/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageItemView/BUILD index e935774197..eba7dfef21 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItemView/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemView/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/AsyncDisplayKit", "//submodules/Display", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/AccountContext", "//submodules/LocalizedPeerData", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItemView/Sources/ChatMessageItemView.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemView/Sources/ChatMessageItemView.swift index 5ab0030bb4..828078334e 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItemView/Sources/ChatMessageItemView.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemView/Sources/ChatMessageItemView.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import Display -import Postbox import TelegramCore import AccountContext import LocalizedPeerData @@ -105,7 +104,7 @@ public final class ChatMessageAccessibilityData { } } - let dataForMessage: (Message, Bool) -> (String, String) = { message, isReply -> (String, String) in + let dataForMessage: (EngineRawMessage, Bool) -> (String, String) = { message, isReply -> (String, String) in var label: String = "" var value: String = "" @@ -634,12 +633,12 @@ public enum InternalBubbleTapAction { } public struct OpenContextMenu { - public var tapMessage: Message + public var tapMessage: EngineRawMessage public var selectAll: Bool public var subFrame: CGRect public var disableDefaultPressAnimation: Bool - public init(tapMessage: Message, selectAll: Bool, subFrame: CGRect, disableDefaultPressAnimation: Bool = false) { + public init(tapMessage: EngineRawMessage, selectAll: Bool, subFrame: CGRect, disableDefaultPressAnimation: Bool = false) { self.tapMessage = tapMessage self.selectAll = selectAll self.subFrame = subFrame @@ -727,7 +726,7 @@ open class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol { } } - public func matchesMessage(id: MessageId) -> Bool { + public func matchesMessage(id: EngineMessage.Id) -> Bool { if let item = self.item { for (message, _) in item.content { if message.id == id { @@ -738,18 +737,18 @@ open class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol { return false } - public func messages() -> [Message] { + public func messages() -> [EngineRawMessage] { guard let item = self.item else { return [] } - var messages: [Message] = [] + var messages: [EngineRawMessage] = [] for (message, _) in item.content { messages.append(message) } return messages } - open func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + open func transitionNode(id: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { return nil } @@ -828,7 +827,7 @@ open class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol { case let .callback(requiresPassword, data): item.controllerInteraction.requestMessageActionCallback(item.message, data, false, requiresPassword, progress) case let .switchInline(samePeer, query, peerTypes): - var botPeer: Peer? + var botPeer: EngineRawPeer? var found = false for attribute in item.message.attributes { @@ -843,7 +842,7 @@ open class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol { botPeer = item.message.author } - var peerId: PeerId? + var peerId: EnginePeer.Id? if samePeer { peerId = item.message.id.peerId } @@ -895,7 +894,7 @@ open class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol { return nil } - open func targetForStoryTransition(id: StoryId) -> UIView? { + open func targetForStoryTransition(id: EngineStoryId) -> UIView? { return nil } @@ -995,7 +994,7 @@ open class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol { return nil } - private func playEffectAnimation(resource: MediaResource) { + private func playEffectAnimation(resource: EngineRawMediaResource) { guard let item = self.item else { return } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageJoinedChannelBubbleContentNode/Sources/ChatMessageJoinedChannelBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageJoinedChannelBubbleContentNode/Sources/ChatMessageJoinedChannelBubbleContentNode.swift index d769f7231b..86131766f1 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageJoinedChannelBubbleContentNode/Sources/ChatMessageJoinedChannelBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageJoinedChannelBubbleContentNode/Sources/ChatMessageJoinedChannelBubbleContentNode.swift @@ -337,7 +337,7 @@ public class ChatMessageJoinedChannelBubbleContentNode: ChatMessageBubbleContent jsonString += "}" if let data = jsonString.data(using: .utf8), let json = JSON(data: data) { - addAppLogEvent(postbox: item.context.account.postbox, type: "channels.open_recommended_channel", data: json) + item.context.engine.accountData.addAppLogEvent(type: "channels.open_recommended_channel", data: json) } item.controllerInteraction.openPeer(peer, .chat(textInputState: nil, subject: nil, peekData: nil), nil, .default) } else { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageMapBubbleContentNode/Sources/ChatMessageMapBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageMapBubbleContentNode/Sources/ChatMessageMapBubbleContentNode.swift index 53993ce16c..e66c17d057 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageMapBubbleContentNode/Sources/ChatMessageMapBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageMapBubbleContentNode/Sources/ChatMessageMapBubbleContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import LiveLocationTimerNode import PhotoResources @@ -505,7 +504,7 @@ public class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode { self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id == messageId, let currentMedia = self.media, currentMedia.isEqual(to: media) { let imageNode = self.imageNode return (self.imageNode, self.imageNode.bounds, { [weak imageNode] in @@ -515,7 +514,7 @@ public class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode { return nil } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { var mediaHidden = false if let currentMedia = self.media, let media = media { for item in media { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageMediaBubbleContentNode/Sources/ChatMessageMediaBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageMediaBubbleContentNode/Sources/ChatMessageMediaBubbleContentNode.swift index fa752abe2d..21feda7d24 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageMediaBubbleContentNode/Sources/ChatMessageMediaBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageMediaBubbleContentNode/Sources/ChatMessageMediaBubbleContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramUIPreferences import TelegramPresentationData @@ -27,7 +26,7 @@ public class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { private var selectionNode: GridMessageSelectionNode? private var highlightedState: Bool = false - private var media: Media? + private var media: EngineRawMedia? private var mediaIndex: Int? private var automaticPlayback: Bool? @@ -116,7 +115,7 @@ public class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { let interactiveImageLayout = self.interactiveImageNode.asyncLayout() return { item, layoutConstants, preparePosition, selection, constrainedSize, _ in - var selectedMedia: Media? + var selectedMedia: EngineRawMedia? var selectedMediaIndex: Int? var extendedMedia: TelegramExtendedMedia? var automaticDownload: InteractiveMediaNodeAutodownloadMode = .none @@ -512,7 +511,7 @@ public class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { } } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id == messageId, var currentMedia = self.media { if let invoice = currentMedia as? TelegramMediaInvoice, let extendedMedia = invoice.extendedMedia, case let .full(fullMedia) = extendedMedia { currentMedia = fullMedia @@ -527,7 +526,7 @@ public class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { return nil } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { var mediaHidden = false var currentMedia = self.media diff --git a/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessageQuizAnswerBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessageQuizAnswerBubbleContentNode.swift index 72d3794fbb..1573119fe6 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessageQuizAnswerBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessageQuizAnswerBubbleContentNode.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import Display import AsyncDisplayKit import SwiftSignalKit @@ -48,7 +47,7 @@ public final class ChatMessageQuizAnswerBubbleContentNode: ChatMessageBubbleCont let title: String = item.presentationData.strings.MessagePoll_Explanation var text: String = "" var entities: [MessageTextEntity] = [] - var mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)? = nil + var mediaAndFlags: ([EngineRawMedia], ChatMessageAttachedContentNodeMediaFlags)? = nil var solution: TelegramMediaPollResults.Solution? if let poll = item.message.media.first(where: { $0 is TelegramMediaPoll }) as? TelegramMediaPoll, let solutionValue = poll.results.solution { text = solutionValue.text @@ -124,11 +123,11 @@ public final class ChatMessageQuizAnswerBubbleContentNode: ChatMessageBubbleCont self.contentNode.updateTouchesAtPoint(point.flatMap { $0.offsetBy(dx: -contentNodeFrame.minX, dy: -contentNodeFrame.minY) }) } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { return self.contentNode.updateHiddenMedia(media) } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id != messageId { return nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageProfilePhotoSuggestionContentNode/Sources/ChatMessageProfilePhotoSuggestionContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageProfilePhotoSuggestionContentNode/Sources/ChatMessageProfilePhotoSuggestionContentNode.swift index 11008ec607..04a68ef4f5 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageProfilePhotoSuggestionContentNode/Sources/ChatMessageProfilePhotoSuggestionContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageProfilePhotoSuggestionContentNode/Sources/ChatMessageProfilePhotoSuggestionContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import AccountContext import TelegramPresentationData @@ -95,7 +94,7 @@ public class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleCont self.fetchDisposable.dispose() } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id == messageId { return (self.imageNode, self.imageNode.bounds, { [weak self] in guard let strongSelf = self else { @@ -110,9 +109,9 @@ public class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleCont } } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { var mediaHidden = false - var currentMedia: Media? + var currentMedia: EngineRawMedia? if let item = item { mediaLoop: for media in item.message.media { if let media = media as? TelegramMediaAction { @@ -218,7 +217,7 @@ public class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleCont } if let photo = photo, let video = photo.videoRepresentations.last, let id = photo.id?.id { - let videoFileReference = FileMediaReference.message(message: MessageReference(item.message), media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: photo.representations, videoThumbnails: [], immediateThumbnailData: photo.immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [], preloadSize: nil, coverTime: nil, videoCodec: nil)], alternativeRepresentations: [])) + let videoFileReference = FileMediaReference.message(message: MessageReference(item.message), media: TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: photo.representations, videoThumbnails: [], immediateThumbnailData: photo.immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [], preloadSize: nil, coverTime: nil, videoCodec: nil)], alternativeRepresentations: [])) let videoContent = NativeVideoContent(id: .profileVideo(id, "action"), userLocation: .peer(item.message.id.peerId), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear, storeAfterDownload: nil) if videoContent.id != strongSelf.videoContent?.id { let mediaManager = item.context.sharedContext.mediaManager diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/BUILD index 9c5a9df3aa..7acafa371c 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/BUILD @@ -11,7 +11,6 @@ swift_library( ], deps = [ "//submodules/AsyncDisplayKit", - "//submodules/Postbox", "//submodules/Display", "//submodules/TelegramCore", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift index 29a4cda102..4aef7b4f1e 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import AsyncDisplayKit -import Postbox import Display import TelegramCore import SwiftSignalKit @@ -80,13 +79,13 @@ public class ChatMessageReplyInfoNode: ASDisplayNode { public let strings: PresentationStrings public let context: AccountContext public let type: ChatMessageReplyInfoType - public let message: Message? + public let message: EngineRawMessage? public let replyForward: QuotedReplyMessageAttribute? public let quote: (quote: EngineMessageReplyQuote, isQuote: Bool)? public let innerSubject: EngineMessageReplyInnerSubject? - public let story: StoryId? + public let story: EngineStoryId? public let isSummarized: Bool - public let parentMessage: Message + public let parentMessage: EngineRawMessage public let constrainedSize: CGSize public let animationCache: AnimationCache? public let animationRenderer: MultiAnimationRenderer? @@ -97,13 +96,13 @@ public class ChatMessageReplyInfoNode: ASDisplayNode { strings: PresentationStrings, context: AccountContext, type: ChatMessageReplyInfoType, - message: Message?, + message: EngineRawMessage?, replyForward: QuotedReplyMessageAttribute?, quote: (quote: EngineMessageReplyQuote, isQuote: Bool)?, innerSubject: EngineMessageReplyInnerSubject?, - story: StoryId?, + story: EngineStoryId?, isSummarized: Bool, - parentMessage: Message, + parentMessage: EngineRawMessage, constrainedSize: CGSize, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?, @@ -222,7 +221,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode { if let peer = forwardInfo.author { author = peer } else if let authorSignature = forwardInfo.authorSignature { - author = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) + author = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.Empty, id: EnginePeer.Id.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) } } @@ -903,7 +902,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode { pattern = MessageInlineBlockBackgroundView.Pattern( context: arguments.context, fileId: backgroundEmojiId, - file: arguments.parentMessage.associatedMedia[MediaId( + file: arguments.parentMessage.associatedMedia[EngineMedia.Id( namespace: Namespaces.Media.CloudFile, id: backgroundEmojiId )] as? TelegramMediaFile, diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageRichDataBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageRichDataBubbleContentNode/BUILD index 0615ab5b69..bbc0db7fde 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageRichDataBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageRichDataBubbleContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/TelegramCore", - "//submodules/Postbox", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/AccountContext", "//submodules/InstantPageUI", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageRichDataBubbleContentNode/Sources/ChatMessageRichDataBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageRichDataBubbleContentNode/Sources/ChatMessageRichDataBubbleContentNode.swift index 599bf566ba..f1e0efe887 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageRichDataBubbleContentNode/Sources/ChatMessageRichDataBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageRichDataBubbleContentNode/Sources/ChatMessageRichDataBubbleContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import TelegramCore -import Postbox import SwiftSignalKit import AccountContext import ChatMessageBubbleContentNode @@ -697,7 +696,7 @@ public class ChatMessageRichDataBubbleContentNode: ChatMessageBubbleContentNode } } - override public func updateSearchTextHighlightState(text: String?, messages: [MessageIndex]?) { + override public func updateSearchTextHighlightState(text: String?, messages: [EngineMessage.Index]?) { } override public func willUpdateIsExtractedToContextPreview(_ value: Bool) { @@ -779,7 +778,7 @@ public class ChatMessageRichDataBubbleContentNode: ChatMessageBubbleContentNode self.textSelectionNode = textSelectionNode } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { guard let item = self.item, item.message.id == messageId else { return nil } @@ -797,7 +796,7 @@ public class ChatMessageRichDataBubbleContentNode: ChatMessageBubbleContentNode return nil } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { var hiddenMedia: InstantPageMedia? if let media, !media.isEmpty, let layout = self.currentPageLayout?.layout { for raw in media { @@ -813,7 +812,7 @@ public class ChatMessageRichDataBubbleContentNode: ChatMessageBubbleContentNode return hiddenMedia != nil } - private func findInstantPageMedia(in items: [InstantPageItem], mediaId: MediaId) -> InstantPageMedia? { + private func findInstantPageMedia(in items: [InstantPageItem], mediaId: EngineMedia.Id) -> InstantPageMedia? { for item in items { if let detailsItem = item as? InstantPageDetailsItem { if let found = self.findInstantPageMedia(in: detailsItem.items, mediaId: mediaId) { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/BUILD index 93400be766..1c4c39b41e 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/TelegramPresentationData", "//submodules/TextFormat", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift index b43b5d001e..bcd759a779 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TextFormat @@ -75,7 +74,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { private var replyRecognizer: ChatSwipeToReplyRecognizer? private var currentSwipeAction: ChatControllerInteractionSwipeAction? - private var appliedForwardInfo: (Peer?, String?)? + private var appliedForwardInfo: (EngineRawPeer?, String?)? private var enableSynchronousImageApply: Bool = false @@ -703,11 +702,11 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { } } - var replyMessage: Message? + var replyMessage: EngineRawMessage? var replyForward: QuotedReplyMessageAttribute? var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)? var replyInnerSubject: EngineMessageReplyInnerSubject? - var replyStory: StoryId? + var replyStory: EngineStoryId? for attribute in item.message.attributes { if let attribute = attribute as? InlineBotMessageAttribute { var inlineBotNameString: String? @@ -811,7 +810,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { let contentHeight = max(imageSize.height, layoutConstants.image.minDimensions.height) - var forwardSource: Peer? + var forwardSource: EngineRawPeer? var forwardAuthorSignature: String? var forwardPsaType: String? @@ -867,13 +866,13 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { } var buttonDeclineValue: UInt8 = 0 - let buttonDecline = MemoryBuffer(data: Data(bytes: &buttonDeclineValue, count: 1)) + let buttonDecline = EngineMemoryBuffer(data: Data(bytes: &buttonDeclineValue, count: 1)) var buttonApproveValue: UInt8 = 1 - let buttonApprove = MemoryBuffer(data: Data(bytes: &buttonApproveValue, count: 1)) + let buttonApprove = EngineMemoryBuffer(data: Data(bytes: &buttonApproveValue, count: 1)) var buttonSuggestChangesValue: UInt8 = 2 - let buttonSuggestChanges = MemoryBuffer(data: Data(bytes: &buttonSuggestChangesValue, count: 1)) - - let customInfos: [MemoryBuffer: ChatMessageActionButtonsNode.CustomInfo] = [ + let buttonSuggestChanges = EngineMemoryBuffer(data: Data(bytes: &buttonSuggestChangesValue, count: 1)) + + let customInfos: [EngineMemoryBuffer: ChatMessageActionButtonsNode.CustomInfo] = [ buttonDecline: ChatMessageActionButtonsNode.CustomInfo( isEnabled: true, icon: .suggestedPostReject @@ -2219,7 +2218,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { item.controllerInteraction.openMessageContextMenu(item.message, false, self, self.imageNode.frame, nil, nil) } - override public func targetForStoryTransition(id: StoryId) -> UIView? { + override public func targetForStoryTransition(id: EngineStoryId) -> UIView? { guard let item = self.item else { return nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageStoryMentionContentNode/Sources/ChatMessageStoryMentionContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageStoryMentionContentNode/Sources/ChatMessageStoryMentionContentNode.swift index 3e805b7cb6..4962128938 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageStoryMentionContentNode/Sources/ChatMessageStoryMentionContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageStoryMentionContentNode/Sources/ChatMessageStoryMentionContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import AccountContext import TelegramPresentationData @@ -95,7 +94,7 @@ public class ChatMessageStoryMentionContentNode: ChatMessageBubbleContentNode { self.fetchDisposable.dispose() } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id == messageId { return (self.imageNode, self.imageNode.bounds, { [weak self] in guard let strongSelf = self else { @@ -110,9 +109,9 @@ public class ChatMessageStoryMentionContentNode: ChatMessageBubbleContentNode { } } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { var mediaHidden = false - var currentMedia: Media? + var currentMedia: EngineRawMedia? if let item = item { mediaLoop: for media in item.message.media { if let media = media as? TelegramMediaStory { @@ -159,7 +158,7 @@ public class ChatMessageStoryMentionContentNode: ChatMessageBubbleContentNode { var story: Stories.Item? let storyMedia: TelegramMediaStory? = item.message.media.first(where: { $0 is TelegramMediaStory }) as? TelegramMediaStory - var selectedMedia: Media? + var selectedMedia: EngineRawMedia? if let storyMedia, let storyItem = item.message.associatedStories[storyMedia.storyId], !storyItem.data.isEmpty, case let .item(storyValue) = storyItem.get(Stories.StoredItem.self) { selectedMedia = storyValue.media diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/BUILD index 0a6225a1f7..95017bfc93 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/TelegramCore", - "//submodules/Postbox", "//submodules/TextFormat", "//submodules/UrlEscaping", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/Sources/ChatMessageTodoBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/Sources/ChatMessageTodoBubbleContentNode.swift index bdc4c7dc8d..566a097725 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/Sources/ChatMessageTodoBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageTodoBubbleContentNode/Sources/ChatMessageTodoBubbleContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import TelegramCore -import Postbox import TextFormat import UrlEscaping import SwiftSignalKit @@ -407,7 +406,7 @@ private final class ChatMessageTodoItemNode: ASDisplayNode { let separatorNode: ASDisplayNode var context: AccountContext? - var message: Message? + var message: EngineRawMessage? var option: TelegramMediaTodo.Item? var pressed: (() -> Void)? @@ -727,7 +726,7 @@ private final class ChatMessageTodoItemNode: ASDisplayNode { return ChatMessageBubbleContentTapAction(content: .none) } - static func asyncLayout(_ maybeNode: ChatMessageTodoItemNode?) -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ presentationContext: ChatPresentationContext, _ message: Message, _ todo: TelegramMediaTodo, _ option: TelegramMediaTodo.Item, _ completion: TelegramMediaTodo.Completion?, _ translation: TranslationMessageAttribute.Additional?, _ constrainedWidth: CGFloat) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (Bool, Bool, Bool) -> ChatMessageTodoItemNode))) { + static func asyncLayout(_ maybeNode: ChatMessageTodoItemNode?) -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ presentationContext: ChatPresentationContext, _ message: EngineRawMessage, _ todo: TelegramMediaTodo, _ option: TelegramMediaTodo.Item, _ completion: TelegramMediaTodo.Completion?, _ translation: TranslationMessageAttribute.Additional?, _ constrainedWidth: CGFloat) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (Bool, Bool, Bool) -> ChatMessageTodoItemNode))) { let makeTitleLayout = TextNodeWithEntities.asyncLayout(maybeNode?.titleNode) let makeNameLayout = TextNode.asyncLayout(maybeNode?.nameNode) @@ -1087,7 +1086,7 @@ public class ChatMessageTodoBubbleContentNode: ChatMessageBubbleContentNode { let makeViewResultsTextLayout = TextNode.asyncLayout(self.buttonViewResultsTextNode) let statusLayout = self.statusNode.asyncLayout() - var previousOptionNodeLayouts: [Int32: (_ contet: AccountContext, _ presentationData: ChatPresentationData, _ presentationContext: ChatPresentationContext, _ message: Message, _ poll: TelegramMediaTodo, _ option: TelegramMediaTodo.Item, _ completion: TelegramMediaTodo.Completion?, _ translation: TranslationMessageAttribute.Additional?, _ constrainedWidth: CGFloat) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (Bool, Bool, Bool) -> ChatMessageTodoItemNode)))] = [:] + var previousOptionNodeLayouts: [Int32: (_ contet: AccountContext, _ presentationData: ChatPresentationData, _ presentationContext: ChatPresentationContext, _ message: EngineRawMessage, _ poll: TelegramMediaTodo, _ option: TelegramMediaTodo.Item, _ completion: TelegramMediaTodo.Completion?, _ translation: TranslationMessageAttribute.Additional?, _ constrainedWidth: CGFloat) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (Bool, Bool, Bool) -> ChatMessageTodoItemNode)))] = [:] for optionNode in self.optionNodes { if let option = optionNode.option { previousOptionNodeLayouts[option.id] = ChatMessageTodoItemNode.asyncLayout(optionNode) @@ -1293,7 +1292,7 @@ public class ChatMessageTodoBubbleContentNode: ChatMessageBubbleContentNode { for i in 0 ..< todo.items.count { let todoItem = todo.items[i] - let makeLayout: (_ context: AccountContext, _ presentationData: ChatPresentationData, _ presentationContext: ChatPresentationContext, _ message: Message, _ todo: TelegramMediaTodo, _ item: TelegramMediaTodo.Item, _ completion: TelegramMediaTodo.Completion?, _ translation: TranslationMessageAttribute.Additional?, _ constrainedWidth: CGFloat) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (Bool, Bool, Bool) -> ChatMessageTodoItemNode))) + let makeLayout: (_ context: AccountContext, _ presentationData: ChatPresentationData, _ presentationContext: ChatPresentationContext, _ message: EngineRawMessage, _ todo: TelegramMediaTodo, _ item: TelegramMediaTodo.Item, _ completion: TelegramMediaTodo.Completion?, _ translation: TranslationMessageAttribute.Additional?, _ constrainedWidth: CGFloat) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (Bool, Bool, Bool) -> ChatMessageTodoItemNode))) if let previous = previousOptionNodeLayouts[todoItem.id] { makeLayout = previous } else { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageWallpaperBubbleContentNode/Sources/ChatMessageWallpaperBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageWallpaperBubbleContentNode/Sources/ChatMessageWallpaperBubbleContentNode.swift index ec9e6380ea..6aa35297cf 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageWallpaperBubbleContentNode/Sources/ChatMessageWallpaperBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageWallpaperBubbleContentNode/Sources/ChatMessageWallpaperBubbleContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import AccountContext import TelegramPresentationData @@ -135,7 +134,7 @@ public class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode item.context.account.pendingPeerMediaUploadManager.cancel(peerId: item.message.id.peerId) } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id == messageId { return (self.imageNode, self.imageNode.bounds, { [weak self] in guard let strongSelf = self else { @@ -150,9 +149,9 @@ public class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode } } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { var mediaHidden = false - var currentMedia: Media? + var currentMedia: EngineRawMedia? if let item = item { mediaLoop: for media in item.message.media { if let media = media as? TelegramMediaAction { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift index c0da699d9b..f4f93efff9 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import Display import AsyncDisplayKit import SwiftSignalKit @@ -225,7 +224,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent var text: String? var entities: [MessageTextEntity]? var titleBadge: String? - var mediaAndFlags: ([Media], ChatMessageAttachedContentNodeMediaFlags)? + var mediaAndFlags: ([EngineRawMedia], ChatMessageAttachedContentNodeMediaFlags)? var badge: String? var actionIcon: ChatMessageAttachedContentActionIcon? @@ -258,7 +257,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent entities = generateTextEntities(textValue, enabledTypes: entityTypes) } - var mainMedia: Media? + var mainMedia: EngineRawMedia? var automaticPlayback = false @@ -527,7 +526,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent for attribute in webpage.attributes { if case let .aiTextStyle(aiTextStyle) = attribute { - if let file = item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: aiTextStyle.emojiFileId)] { + if let file = item.message.associatedMedia[EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: aiTextStyle.emojiFileId)] { mediaAndFlags = ([file], [.preferMediaInline]) } } @@ -744,13 +743,13 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent return ChatMessageBubbleContentTapAction(content: .none) } - override public func updateHiddenMedia(_ media: [Media]?) -> Bool { + override public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { if let media = media { var updatedMedia = media if let current = self.webPage, case let .Loaded(content) = current.content { for item in media { if let webpage = item as? TelegramMediaWebpage, webpage.id == current.id { - var mediaList: [Media] = [webpage] + var mediaList: [EngineRawMedia] = [webpage] if let image = content.image { mediaList.append(image) } @@ -762,7 +761,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent } updatedMedia = mediaList } else if let id = item.id, content.file?.id == id || content.image?.id == id { - var mediaList: [Media] = [current] + var mediaList: [EngineRawMedia] = [current] if let image = content.image { mediaList.append(image) } @@ -782,7 +781,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent } } - override public func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(messageId: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if self.item?.message.id != messageId { return nil } diff --git a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsFilterController.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsFilterController.swift deleted file mode 100644 index cc001bf972..0000000000 --- a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsFilterController.swift +++ /dev/null @@ -1,504 +0,0 @@ -import Foundation -import UIKit -import Display -import SwiftSignalKit -import Postbox -import TelegramCore -import TelegramPresentationData -import TelegramUIPreferences -import ItemListUI -import PresentationDataUtils -import AccountContext -import ItemListPeerItem - -private final class ChatRecentActionsFilterControllerArguments { - let context: AccountContext - - let toggleAllActions: (Bool) -> Void - let toggleAction: ([AdminLogEventsFlags]) -> Void - let toggleAllAdmins: (Bool) -> Void - let toggleAdmin: (PeerId) -> Void - - init(context: AccountContext, toggleAllActions: @escaping (Bool) -> Void, toggleAction: @escaping ([AdminLogEventsFlags]) -> Void, toggleAllAdmins: @escaping (Bool) -> Void, toggleAdmin: @escaping (PeerId) -> Void) { - self.context = context - self.toggleAllActions = toggleAllActions - self.toggleAction = toggleAction - self.toggleAllAdmins = toggleAllAdmins - self.toggleAdmin = toggleAdmin - } -} - -private enum ChatRecentActionsFilterSection: Int32 { - case actions - case admins -} - -private enum ChatRecentActionsFilterEntryStableId: Hashable { - case index(Int32) - case peer(PeerId) -} - -private enum ChatRecentActionsFilterEntry: ItemListNodeEntry { - case actionsTitle(PresentationTheme, String) - case allActions(PresentationTheme, String, Bool) - case actionItem(PresentationTheme, Int32, [AdminLogEventsFlags], String, Bool) - - case adminsTitle(PresentationTheme, String) - case allAdmins(PresentationTheme, String, Bool) - case adminPeerItem(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, Int32, RenderedChannelParticipant, Bool, Bool) - - var section: ItemListSectionId { - switch self { - case .actionsTitle, .allActions, .actionItem: - return ChatRecentActionsFilterSection.actions.rawValue - case .adminsTitle, .allAdmins, .adminPeerItem: - return ChatRecentActionsFilterSection.admins.rawValue - } - } - - var stableId: ChatRecentActionsFilterEntryStableId { - switch self { - case .actionsTitle: - return .index(0) - case .allActions: - return .index(1) - case let .actionItem(_, index, _, _, _): - return .index(100 + index) - case .adminsTitle: - return .index(200) - case .allAdmins: - return .index(201) - case let .adminPeerItem(_, _, _, _, _, participant, _, _): - return .peer(participant.peer.id) - } - } - - static func ==(lhs: ChatRecentActionsFilterEntry, rhs: ChatRecentActionsFilterEntry) -> Bool { - switch lhs { - case let .actionsTitle(lhsTheme, lhsText): - if case let .actionsTitle(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .allActions(lhsTheme, lhsText, lhsValue): - if case let .allActions(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - case let .actionItem(lhsTheme, lhsIndex, lhsFlags, lhsText, lhsValue): - if case let .actionItem(rhsTheme, rhsIndex, rhsFlags, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsIndex == rhsIndex, lhsFlags == rhsFlags, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - case let .adminsTitle(lhsTheme, lhsText): - if case let .adminsTitle(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .allAdmins(lhsTheme, lhsText, lhsValue): - if case let .allAdmins(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - case let .adminPeerItem(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsNameDisplayOrder, lhsIndex, lhsParticipant, lhsIsAntiSpam, lhsChecked): - if case let .adminPeerItem(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsNameDisplayOrder, rhsIndex, rhsParticipant, rhsIsAntiSpam, rhsChecked) = rhs { - if lhsTheme !== rhsTheme { - return false - } - if lhsStrings !== rhsStrings { - return false - } - if lhsDateTimeFormat != rhsDateTimeFormat { - return false - } - if lhsNameDisplayOrder != rhsNameDisplayOrder { - return false - } - if lhsIndex != rhsIndex { - return false - } - if lhsParticipant != rhsParticipant { - return false - } - if lhsIsAntiSpam != rhsIsAntiSpam { - return false - } - if lhsChecked != rhsChecked { - return false - } - return true - } else { - return false - } - } - } - - static func <(lhs: ChatRecentActionsFilterEntry, rhs: ChatRecentActionsFilterEntry) -> Bool { - switch lhs { - case .actionsTitle: - return true - case .allActions: - switch rhs { - case .actionsTitle: - return false - default: - return true - } - case let .actionItem(_, lhsIndex, _, _, _): - switch rhs { - case .actionsTitle, .allActions: - return false - case let .actionItem(_, rhsIndex, _, _, _): - return lhsIndex < rhsIndex - default: - return true - } - case .adminsTitle: - switch rhs { - case .adminPeerItem, .allAdmins: - return true - default: - return false - } - case .allAdmins: - switch rhs { - case .adminPeerItem: - return true - default: - return false - } - case let .adminPeerItem(_, _, _, _, lhsIndex, _, _, _): - switch rhs { - case let .adminPeerItem(_, _, _, _, rhsIndex, _, _, _): - return lhsIndex < rhsIndex - default: - return false - } - } - } - - func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { - let arguments = arguments as! ChatRecentActionsFilterControllerArguments - switch self { - case let .actionsTitle(_, text): - return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) - case let .allActions(_, text, value): - return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enabled: true, sectionId: self.section, style: .blocks, updated: { value in - arguments.toggleAllActions(value) - }) - case let .actionItem(_, _, events, text, value): - return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .right, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: { - arguments.toggleAction(events) - }) - case let .adminsTitle(_, text): - return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) - case let .allAdmins(_, text, value): - return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enabled: true, sectionId: self.section, style: .blocks, updated: { value in - arguments.toggleAllAdmins(value) - }) - case let .adminPeerItem(_, strings, dateTimeFormat, nameDisplayOrder, _, participant, isAntiSpam, checked): - var peerText: String = "" - if isAntiSpam { - peerText = strings.Group_Management_AntiSpamMagic - } else { - switch participant.participant { - case .creator: - peerText = strings.Channel_Management_LabelOwner.lowercased() - case .member: - peerText = strings.ChatAdmins_AdminLabel.lowercased() - } - } - return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: participant.peer, presence: nil, text: .text(peerText, .secondary), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: ItemListPeerItemSwitch(value: checked, style: .check), enabled: true, selectable: true, sectionId: self.section, action: { - arguments.toggleAdmin(participant.peer.id) - }, setPeerIdWithRevealedOptions: { _, _ in - }, removePeer: { _ in }) - } - } -} - -private struct ChatRecentActionsFilterControllerState: Equatable { - let events: AdminLogEventsFlags - let adminPeerIds: [PeerId]? - - init(events: AdminLogEventsFlags, adminPeerIds: [PeerId]?) { - self.events = events - self.adminPeerIds = adminPeerIds - } - - static func ==(lhs: ChatRecentActionsFilterControllerState, rhs: ChatRecentActionsFilterControllerState) -> Bool { - if lhs.events != rhs.events { - return false - } - if let lhsAdminPeerIds = lhs.adminPeerIds, let rhsAdminPeerIds = rhs.adminPeerIds { - if lhsAdminPeerIds != rhsAdminPeerIds { - return false - } - } else if (lhs.adminPeerIds != nil) != (rhs.adminPeerIds != nil) { - return false - } - - return true - } - - func withUpdatedEvents(_ events: AdminLogEventsFlags) -> ChatRecentActionsFilterControllerState { - return ChatRecentActionsFilterControllerState(events: events, adminPeerIds: self.adminPeerIds) - } - - func withUpdatedAdminPeerIds(_ adminPeerIds: [PeerId]?) -> ChatRecentActionsFilterControllerState { - return ChatRecentActionsFilterControllerState(events: self.events, adminPeerIds: adminPeerIds) - } -} - -private func channelRecentActionsFilterControllerEntries(presentationData: PresentationData, accountPeerId: PeerId, peer: Peer, antiSpamBotId: PeerId?, state: ChatRecentActionsFilterControllerState, participants: [RenderedChannelParticipant]?) -> [ChatRecentActionsFilterEntry] { - var isGroup = true - if let peer = peer as? TelegramChannel, case .broadcast = peer.info { - isGroup = false - } - - var entries: [ChatRecentActionsFilterEntry] = [] - - let order: [([AdminLogEventsFlags], String)] - if isGroup { - order = [ - ([.ban, .unban, .kick, .unkick], presentationData.strings.Channel_AdminLogFilter_EventsRestrictions), - ([.promote, .demote], presentationData.strings.Channel_AdminLogFilter_EventsAdmins), - ([.invite, .join], presentationData.strings.Channel_AdminLogFilter_EventsNewMembers), - ([.info, .settings], isGroup ? presentationData.strings.Channel_AdminLogFilter_EventsInfo : presentationData.strings.Channel_AdminLogFilter_ChannelEventsInfo), - ([.invites], presentationData.strings.Channel_AdminLogFilter_EventsInviteLinks), - ([.deleteMessages], presentationData.strings.Channel_AdminLogFilter_EventsDeletedMessages), - ([.editMessages], presentationData.strings.Channel_AdminLogFilter_EventsEditedMessages), - ([.pinnedMessages], presentationData.strings.Channel_AdminLogFilter_EventsPinned), - ([.leave], presentationData.strings.Channel_AdminLogFilter_EventsLeaving), - ([.calls], presentationData.strings.Channel_AdminLogFilter_EventsCalls) - ] - } else { - order = [ - ([.promote, .demote], presentationData.strings.Channel_AdminLogFilter_EventsAdmins), - ([.invite, .join], presentationData.strings.Channel_AdminLogFilter_EventsNewMembers), - ([.info, .settings], isGroup ? presentationData.strings.Channel_AdminLogFilter_EventsInfo : presentationData.strings.Channel_AdminLogFilter_ChannelEventsInfo), - ([.invites], presentationData.strings.Channel_AdminLogFilter_EventsInviteLinks), - ([.deleteMessages], presentationData.strings.Channel_AdminLogFilter_EventsDeletedMessages), - ([.editMessages], presentationData.strings.Channel_AdminLogFilter_EventsEditedMessages), - ([.pinnedMessages], presentationData.strings.Channel_AdminLogFilter_EventsPinned), - ([.leave], presentationData.strings.Channel_AdminLogFilter_EventsLeaving), - ([.calls], presentationData.strings.Channel_AdminLogFilter_EventsLiveStreams) - ] - } - - var allTypesSelected = true - outer: for (events, _) in order { - for event in events { - if !state.events.contains(event) { - allTypesSelected = false - break outer - } - } - } - - entries.append(.actionsTitle(presentationData.theme, presentationData.strings.Channel_AdminLogFilter_EventsTitle)) - entries.append(.allActions(presentationData.theme, presentationData.strings.Channel_AdminLogFilter_EventsAll, allTypesSelected)) - - var index: Int32 = 0 - for (events, text) in order { - var eventsSelected = true - inner: for event in events { - if !state.events.contains(event) { - eventsSelected = false - break inner - } - } - entries.append(.actionItem(presentationData.theme, index, events, text, eventsSelected)) - index += 1 - } - - if let participants = participants { - var allAdminsSelected = true - if let adminPeerIds = state.adminPeerIds { - for participant in participants { - if !adminPeerIds.contains(participant.peer.id) { - allAdminsSelected = false - break - } - } - } else { - allAdminsSelected = true - } - - entries.append(.adminsTitle(presentationData.theme, presentationData.strings.Channel_AdminLogFilter_AdminsTitle)) - entries.append(.allAdmins(presentationData.theme, presentationData.strings.Channel_AdminLogFilter_AdminsAll, allAdminsSelected)) - - var index: Int32 = 0 - for participant in participants { - var adminSelected = true - if let adminPeerIds = state.adminPeerIds { - if !adminPeerIds.contains(participant.peer.id) { - adminSelected = false - } - } else { - adminSelected = true - } - entries.append(.adminPeerItem(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, index, participant, participant.peer.id == antiSpamBotId, adminSelected)) - index += 1 - } - } - - return entries -} - -public func channelRecentActionsFilterController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peer: Peer, events: AdminLogEventsFlags, adminPeerIds: [PeerId]?, apply: @escaping (_ events: AdminLogEventsFlags, _ adminPeerIds: [PeerId]?) -> Void) -> ViewController { - let statePromise = ValuePromise(ChatRecentActionsFilterControllerState(events: events, adminPeerIds: adminPeerIds), ignoreRepeated: true) - let stateValue = Atomic(value: ChatRecentActionsFilterControllerState(events: events, adminPeerIds: adminPeerIds)) - let updateState: ((ChatRecentActionsFilterControllerState) -> ChatRecentActionsFilterControllerState) -> Void = { f in - statePromise.set(stateValue.modify { f($0) }) - } - - var dismissImpl: (() -> Void)? - - let adminsPromise = Promise<[RenderedChannelParticipant]?>(nil) - - let actionsDisposable = DisposableSet() - - let arguments = ChatRecentActionsFilterControllerArguments(context: context, toggleAllActions: { value in - updateState { current in - if value { - return current.withUpdatedEvents(.all) - } else { - return current.withUpdatedEvents([]) - } - } - }, toggleAction: { events in - if let first = events.first { - updateState { current in - var updatedEvents = current.events - if updatedEvents.contains(first) { - for event in events { - updatedEvents.remove(event) - } - } else { - for event in events { - updatedEvents.insert(event) - } - } - return current.withUpdatedEvents(updatedEvents) - } - } - }, toggleAllAdmins: { value in - let _ = (adminsPromise.get() - |> take(1) - |> deliverOnMainQueue).startStandalone(next: { admins in - if let _ = admins { - updateState { current in - if value { - return current.withUpdatedAdminPeerIds(nil) - } else { - return current.withUpdatedAdminPeerIds([]) - } - } - } - }) - }, toggleAdmin: { adminId in - let _ = (adminsPromise.get() - |> take(1) - |> deliverOnMainQueue).startStandalone(next: { admins in - if let admins = admins { - updateState { current in - if let adminPeerIds = current.adminPeerIds, let index = adminPeerIds.firstIndex(of: adminId) { - var updatedAdminPeerIds = adminPeerIds - updatedAdminPeerIds.remove(at: index) - return current.withUpdatedAdminPeerIds(updatedAdminPeerIds) - } else { - var updatedAdminPeerIds = current.adminPeerIds ?? admins.map { $0.peer.id } - if updatedAdminPeerIds.contains(adminId), let index = updatedAdminPeerIds.firstIndex(of: adminId) { - updatedAdminPeerIds.remove(at: index) - } else { - updatedAdminPeerIds.append(adminId) - } - return current.withUpdatedAdminPeerIds(updatedAdminPeerIds) - } - } - } - }) - }) - - adminsPromise.set(.single(nil)) - - let (membersDisposable, _) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peer.id) { membersState in - if case .loading = membersState.loadingState, membersState.list.isEmpty { - adminsPromise.set(.single(nil)) - } else { - adminsPromise.set(.single(membersState.list)) - } - } - actionsDisposable.add(membersDisposable) - - let antiSpamBotConfiguration = AntiSpamBotConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) - let antiSpamBotPeerPromise = Promise(nil) - if let antiSpamBotId = antiSpamBotConfiguration.antiSpamBotId { - antiSpamBotPeerPromise.set(context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: antiSpamBotId)) - |> map { peer in - if let peer = peer, case let .user(user) = peer { - return RenderedChannelParticipant(participant: .member(id: user.id, invitedAt: 0, adminInfo: nil, banInfo: nil, rank: nil, subscriptionUntilDate: nil), peer: peer) - } else { - return nil - } - }) - } - - var previousPeers: [RenderedChannelParticipant]? - - let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData - let signal = combineLatest(presentationData, statePromise.get(), adminsPromise.get(), antiSpamBotPeerPromise.get()) - |> deliverOnMainQueue - |> map { presentationData, state, admins, antiSpamBot -> (ItemListControllerState, (ItemListNodeState, Any)) in - let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { - dismissImpl?() - }) - - let doneEnabled = !state.events.isEmpty - - let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: doneEnabled, action: { - var resultState: ChatRecentActionsFilterControllerState? - updateState { current in - resultState = current - return current - } - if let resultState = resultState { - apply(resultState.events, resultState.adminPeerIds) - } - dismissImpl?() - }) - - var sortedAdmins: [RenderedChannelParticipant]? - if let admins = admins { - sortedAdmins = admins.filter { $0.peer.id == context.account.peerId } + admins.filter({ $0.peer.id != context.account.peerId }) - if let antiSpamBot = antiSpamBot { - sortedAdmins?.insert(antiSpamBot, at: 0) - } - } else { - sortedAdmins = nil - } - - let previous = previousPeers - previousPeers = sortedAdmins - - let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ChatAdmins_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelRecentActionsFilterControllerEntries(presentationData: presentationData, accountPeerId: context.account.peerId, peer: peer, antiSpamBotId: antiSpamBotConfiguration.antiSpamBotId, state: state, participants: sortedAdmins), style: .blocks, animateChanges: previous != nil && admins != nil && previous!.count >= sortedAdmins!.count) - - return (controllerState, (listState, arguments)) - } - |> afterDisposed { - actionsDisposable.dispose() - } - - let controller = ItemListController(context: context, state: signal) - dismissImpl = { [weak controller] in - controller?.dismiss() - } - return controller -} - diff --git a/submodules/TelegramUI/Components/ChatControllerInteraction/BUILD b/submodules/TelegramUI/Components/ChatControllerInteraction/BUILD index 684e3ca458..43bbbfc9aa 100644 --- a/submodules/TelegramUI/Components/ChatControllerInteraction/BUILD +++ b/submodules/TelegramUI/Components/ChatControllerInteraction/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/ChatPresentationInterfaceState:ChatPresentationInterfaceState", "//submodules/TelegramUIPreferences:TelegramUIPreferences", diff --git a/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift index 43ba16297c..1387502783 100644 --- a/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift @@ -16,7 +16,6 @@ import TextFormat import WallpaperBackgroundNode import AnimationCache import MultiAnimationRenderer -import Postbox public struct ChatInterfaceHighlightedState: Equatable { public struct Quote: Equatable { @@ -41,9 +40,9 @@ public struct ChatInterfaceHighlightedState: Equatable { } public struct ChatInterfacePollActionState: Equatable { - public var pollMessageIdsInProgress: [MessageId: [Data]] = [:] + public var pollMessageIdsInProgress: [EngineMessage.Id: [Data]] = [:] - public init(pollMessageIdsInProgress: [MessageId: [Data]] = [:]) { + public init(pollMessageIdsInProgress: [EngineMessage.Id: [Data]] = [:]) { self.pollMessageIdsInProgress = pollMessageIdsInProgress } } @@ -59,10 +58,10 @@ public enum ChatControllerInteractionReaction { } public struct UnreadMessageRangeKey: Hashable { - public var peerId: PeerId - public var namespace: MessageId.Namespace + public var peerId: EnginePeer.Id + public var namespace: Int32 - public init(peerId: PeerId, namespace: MessageId.Namespace) { + public init(peerId: EnginePeer.Id, namespace: Int32) { self.peerId = peerId self.namespace = namespace } @@ -137,18 +136,18 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol public enum OpenPeerSource { case `default` case reaction - case groupParticipant(storyStats: PeerStoryStats?, avatarHeaderNode: ASDisplayNode?) + case groupParticipant(storyStats: EnginePeerStoryStats?, avatarHeaderNode: ASDisplayNode?) } public struct OpenUrl { public var url: String public var concealed: Bool public var external: Bool? - public var message: Message? + public var message: EngineRawMessage? public var allowInlineWebpageResolution: Bool public var progress: Promise? - public init(url: String, concealed: Bool, external: Bool? = nil, message: Message? = nil, allowInlineWebpageResolution: Bool = false, progress: Promise? = nil) { + public init(url: String, concealed: Bool, external: Bool? = nil, message: EngineRawMessage? = nil, allowInlineWebpageResolution: Bool = false, progress: Promise? = nil) { self.url = url self.concealed = concealed self.external = external @@ -159,13 +158,13 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol } public struct OpenInstantPage { - public var webpageId: MediaId + public var webpageId: EngineMedia.Id public var url: String public var anchor: String? public var concealed: Bool public var progress: Promise? - public init(webpageId: MediaId, url: String, anchor: String?, concealed: Bool, progress: Promise? = nil) { + public init(webpageId: EngineMedia.Id, url: String, anchor: String?, concealed: Bool, progress: Promise? = nil) { self.webpageId = webpageId self.url = url self.anchor = anchor @@ -175,13 +174,13 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol } public struct LongTapParams { - public var message: Message? + public var message: EngineRawMessage? public var contentNode: ContextExtractedContentContainingNode? public var messageNode: ASDisplayNode? public var progress: Promise? public var gesture: TapLongTapOrDoubleTapGestureRecognizer? - public init(message: Message? = nil, contentNode: ContextExtractedContentContainingNode? = nil, messageNode: ASDisplayNode? = nil, progress: Promise? = nil, gesture: TapLongTapOrDoubleTapGestureRecognizer? = nil) { + public init(message: EngineRawMessage? = nil, contentNode: ContextExtractedContentContainingNode? = nil, messageNode: ASDisplayNode? = nil, progress: Promise? = nil, gesture: TapLongTapOrDoubleTapGestureRecognizer? = nil) { self.message = message self.contentNode = contentNode self.messageNode = messageNode @@ -195,100 +194,100 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol case solution(TelegramMediaPollResults.Solution) } - public let openMessage: (Message, OpenMessageParams) -> Bool + public let openMessage: (EngineRawMessage, OpenMessageParams) -> Bool public let openPeer: (EnginePeer, ChatControllerInteractionNavigateToPeer, MessageReference?, OpenPeerSource) -> Void public let openPeerMention: (String, Promise?) -> Void - public let openMessageContextMenu: (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?, CGPoint?) -> Void - public let updateMessageReaction: (Message, ChatControllerInteractionReaction, Bool, ContextExtractedContentContainingView?) -> Void - public let openMessageReactionContextMenu: (Message, ContextExtractedContentContainingView, ContextGesture?, MessageReaction.Reaction) -> Void + public let openMessageContextMenu: (EngineRawMessage, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?, CGPoint?) -> Void + public let updateMessageReaction: (EngineRawMessage, ChatControllerInteractionReaction, Bool, ContextExtractedContentContainingView?) -> Void + public let openMessageReactionContextMenu: (EngineRawMessage, ContextExtractedContentContainingView, ContextGesture?, MessageReaction.Reaction) -> Void public let activateMessagePinch: (PinchSourceContainerNode) -> Void - public let openMessageContextActions: (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void - public let navigateToMessage: (MessageId, MessageId, NavigateToMessageParams) -> Void - public let navigateToMessageStandalone: (MessageId) -> Void - public let navigateToThreadMessage: (PeerId, Int64, MessageId?) -> Void - public let tapMessage: ((Message) -> Void)? + public let openMessageContextActions: (EngineRawMessage, ASDisplayNode, CGRect, ContextGesture?) -> Void + public let navigateToMessage: (EngineMessage.Id, EngineMessage.Id, NavigateToMessageParams) -> Void + public let navigateToMessageStandalone: (EngineMessage.Id) -> Void + public let navigateToThreadMessage: (EnginePeer.Id, Int64, EngineMessage.Id?) -> Void + public let tapMessage: ((EngineRawMessage) -> Void)? public let clickThroughMessage: (UIView?, CGPoint?) -> Void - public let toggleMessagesSelection: ([MessageId], Bool) -> Void + public let toggleMessagesSelection: ([EngineMessage.Id], Bool) -> Void public let sendCurrentMessage: (Bool, ChatSendMessageEffect?) -> Void public let sendMessage: (String) -> Void - public let sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, UIView?, CGRect?, CALayer?, [ItemCollectionId]) -> Bool + public let sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, UIView?, CGRect?, CALayer?, [EngineItemCollectionId]) -> Bool public let sendEmoji: (String, ChatTextInputTextCustomEmojiAttribute, Bool) -> Void public let sendGif: (FileMediaReference, UIView, CGRect, Bool, Bool) -> Bool public let sendBotContextResultAsGif: (ChatContextResultCollection, ChatContextResult, UIView, CGRect, Bool, Bool) -> Bool public let editGif: (FileMediaReference, Bool) -> Void - public let requestMessageActionCallback: (Message, MemoryBuffer?, Bool, Bool, Promise?) -> Void + public let requestMessageActionCallback: (EngineRawMessage, EngineMemoryBuffer?, Bool, Bool, Promise?) -> Void public let requestMessageActionUrlAuth: (String, MessageActionUrlSubject) -> Void - public let activateSwitchInline: (PeerId?, String, ReplyMarkupButtonAction.PeerTypes?) -> Void + public let activateSwitchInline: (EnginePeer.Id?, String, ReplyMarkupButtonAction.PeerTypes?) -> Void public let openUrl: (OpenUrl) -> Void public let openExternalInstantPage: (OpenInstantPage) -> Void public let shareCurrentLocation: () -> Void public let shareAccountContact: () -> Void - public let sendBotCommand: (MessageId?, String) -> Void - public let openInstantPage: (Message, ChatMessageItemAssociatedData?) -> Void - public let openWallpaper: (Message) -> Void - public let openTheme: (Message) -> Void + public let sendBotCommand: (EngineMessage.Id?, String) -> Void + public let openInstantPage: (EngineRawMessage, ChatMessageItemAssociatedData?) -> Void + public let openWallpaper: (EngineRawMessage) -> Void + public let openTheme: (EngineRawMessage) -> Void public let openHashtag: (String?, String) -> Void public let updateInputState: ((ChatTextInputState) -> ChatTextInputState) -> Void public let updateInputMode: ((ChatInputMode) -> ChatInputMode) -> Void public let updatePresentationState: ((ChatPresentationInterfaceState) -> ChatPresentationInterfaceState) -> Void - public let openMessageShareMenu: (MessageId) -> Void + public let openMessageShareMenu: (EngineMessage.Id) -> Void public let presentController: (ViewController, Any?) -> Void public let presentControllerInCurrent: (ViewController, Any?) -> Void public let navigationController: () -> NavigationController? public let chatControllerNode: () -> ASDisplayNode? public let presentGlobalOverlayController: (ViewController, Any?) -> Void - public let callPeer: (PeerId, Bool) -> Void - public let openConferenceCall: (Message) -> Void + public let callPeer: (EnginePeer.Id, Bool) -> Void + public let openConferenceCall: (EngineRawMessage) -> Void public let longTap: (ChatControllerInteractionLongTapAction, LongTapParams?) -> Void public let todoItemLongTap: (Int32, LongTapParams?) -> Void public let pollOptionLongTap: (Data, LongTapParams?) -> Void - public let openCheckoutOrReceipt: (MessageId, OpenMessageParams?) -> Void + public let openCheckoutOrReceipt: (EngineMessage.Id, OpenMessageParams?) -> Void public let openSearch: () -> Void - public let setupReply: (MessageId) -> Void - public let canSetupReply: (Message) -> ChatControllerInteractionSwipeAction + public let setupReply: (EngineMessage.Id) -> Void + public let canSetupReply: (EngineRawMessage) -> ChatControllerInteractionSwipeAction public let canSendMessages: () -> Bool public let navigateToFirstDateMessage: (Int32, Bool) -> Void - public let requestRedeliveryOfFailedMessages: (MessageId) -> Void + public let requestRedeliveryOfFailedMessages: (EngineMessage.Id) -> Void public let addContact: (String) -> Void - public let rateCall: (Message, CallId, Bool) -> Void - public let requestSelectMessagePollOptions: (MessageId, [Data]) -> Void - public let requestAddMessagePollOption: (MessageId, String, [MessageTextEntity], Data, AnyMediaReference?) -> Void - public let requestOpenMessagePollResults: (MessageId, MediaId) -> Void + public let rateCall: (EngineRawMessage, CallId, Bool) -> Void + public let requestSelectMessagePollOptions: (EngineMessage.Id, [Data]) -> Void + public let requestAddMessagePollOption: (EngineMessage.Id, String, [MessageTextEntity], Data, AnyMediaReference?) -> Void + public let requestOpenMessagePollResults: (EngineMessage.Id, EngineMedia.Id) -> Void public let openAppStorePage: () -> Void - public let displayMessageTooltip: (MessageId, String, Bool, ASDisplayNode?, CGRect?) -> Void - public let seekToTimecode: (Message, Double, Bool) -> Void + public let displayMessageTooltip: (EngineMessage.Id, String, Bool, ASDisplayNode?, CGRect?) -> Void + public let seekToTimecode: (EngineRawMessage, Double, Bool) -> Void public let scheduleCurrentMessage: (ChatSendMessageActionSheetController.SendParameters?) -> Void - public let sendScheduledMessagesNow: ([MessageId]) -> Void - public let editScheduledMessagesTime: ([MessageId]) -> Void - public let performTextSelectionAction: (Message?, Bool, NSAttributedString, [MessageTextEntity]?, TextSelectionAction) -> Void + public let sendScheduledMessagesNow: ([EngineMessage.Id]) -> Void + public let editScheduledMessagesTime: ([EngineMessage.Id]) -> Void + public let performTextSelectionAction: (EngineRawMessage?, Bool, NSAttributedString, [MessageTextEntity]?, TextSelectionAction) -> Void public let displayImportedMessageTooltip: (ASDisplayNode) -> Void public let displaySwipeToReplyHint: () -> Void - public let dismissReplyMarkupMessage: (Message) -> Void - public let openMessagePollResults: (MessageId, Data) -> Void + public let dismissReplyMarkupMessage: (EngineRawMessage) -> Void + public let openMessagePollResults: (EngineMessage.Id, Data) -> Void public let openPollCreation: (Bool?) -> Void - public let openPollMedia: (Message, PollMediaSubject) -> Void + public let openPollMedia: (EngineRawMessage, PollMediaSubject) -> Void public let displayPollSolution: (TelegramMediaPollResults.Solution?, ASDisplayNode?) -> Void public let displayPsa: (String, ASDisplayNode) -> Void public let displayDiceTooltip: (TelegramMediaDice) -> Void public let animateDiceSuccess: (Bool, Bool) -> Void - public let displayPremiumStickerTooltip: (TelegramMediaFile, Message) -> Void - public let displayEmojiPackTooltip: (TelegramMediaFile, Message) -> Void - public let openPeerContextMenu: (Peer, MessageId?, ASDisplayNode, CGRect, ContextGesture?) -> Void - public let openMessageReplies: (MessageId, Bool, Bool) -> Void - public let openReplyThreadOriginalMessage: (Message) -> Void - public let openMessageStats: (MessageId) -> Void - public let editMessageMedia: (MessageId, Bool) -> Void + public let displayPremiumStickerTooltip: (TelegramMediaFile, EngineRawMessage) -> Void + public let displayEmojiPackTooltip: (TelegramMediaFile, EngineRawMessage) -> Void + public let openPeerContextMenu: (EngineRawPeer, EngineMessage.Id?, ASDisplayNode, CGRect, ContextGesture?) -> Void + public let openMessageReplies: (EngineMessage.Id, Bool, Bool) -> Void + public let openReplyThreadOriginalMessage: (EngineRawMessage) -> Void + public let openMessageStats: (EngineMessage.Id) -> Void + public let editMessageMedia: (EngineMessage.Id, Bool) -> Void public let copyText: (String) -> Void public let displayUndo: (UndoOverlayContent) -> Void public let isAnimatingMessage: (UInt32) -> Bool public let getMessageTransitionNode: () -> ChatMessageTransitionProtocol? public let updateChoosingSticker: (Bool) -> Void - public let commitEmojiInteraction: (MessageId, String, EmojiInteraction, TelegramMediaFile) -> Void + public let commitEmojiInteraction: (EngineMessage.Id, String, EmojiInteraction, TelegramMediaFile) -> Void public let openLargeEmojiInfo: (String, String?, TelegramMediaFile) -> Void public let openJoinLink: (String) -> Void public let openWebView: (String, String, Bool, ChatOpenWebViewSource) -> Void public let activateAdAction: (EngineMessage.Id, Promise?, Bool, Bool) -> Void - public let adContextAction: (Message, ASDisplayNode, ContextGesture?) -> Void + public let adContextAction: (EngineRawMessage, ASDisplayNode, ContextGesture?) -> Void public let removeAd: (Data) -> Void public let openRequestedPeerSelection: (EngineMessage.Id, ReplyMarkupButtonRequestPeerType, Int32, Int32) -> Void public let saveMediaToFiles: (EngineMessage.Id) -> Void @@ -299,45 +298,45 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol public let openRecommendedChannelContextMenu: (EnginePeer, UIView, ContextGesture?) -> Void public let openGroupBoostInfo: (EnginePeer.Id?, Int) -> Void public let openStickerEditor: () -> Void - public let openAgeRestrictedMessageMedia: (Message, @escaping () -> Void) -> Void - public let playMessageEffect: (Message) -> Void - public let editMessageFactCheck: (MessageId) -> Void + public let openAgeRestrictedMessageMedia: (EngineRawMessage, @escaping () -> Void) -> Void + public let playMessageEffect: (EngineRawMessage) -> Void + public let editMessageFactCheck: (EngineMessage.Id) -> Void public let sendGift: (EnginePeer.Id) -> Void public let openUniqueGift: (String) -> Void public let openMessageFeeException: () -> Void - public let requestMessageUpdate: (MessageId, Bool, ControlledTransition?) -> Void + public let requestMessageUpdate: (EngineMessage.Id, Bool, ControlledTransition?) -> Void public let cancelInteractiveKeyboardGestures: () -> Void public let dismissTextInput: () -> Void - public let scrollToMessageId: (MessageIndex, CGFloat) -> Void - public let scrollToMessageIdWithAnchor: (MessageIndex, String) -> Void - public let navigateToStory: (Message, StoryId) -> Void - public let attemptedNavigationToPrivateQuote: (Peer?) -> Void + public let scrollToMessageId: (EngineMessage.Index, CGFloat) -> Void + public let scrollToMessageIdWithAnchor: (EngineMessage.Index, String) -> Void + public let navigateToStory: (EngineRawMessage, EngineStoryId) -> Void + public let attemptedNavigationToPrivateQuote: (EngineRawPeer?) -> Void public let forceUpdateWarpContents: () -> Void public let playShakeAnimation: () -> Void - public let displayQuickShare: (MessageId, ASDisplayNode, ContextGesture) -> Void + public let displayQuickShare: (EngineMessage.Id, ASDisplayNode, ContextGesture) -> Void public let updateChatLocationThread: (Int64?, ChatControllerAnimateInnerChatSwitchDirection?) -> Void - public let requestToggleTodoMessageItem: (MessageId, Int32, Bool) -> Void - public let displayTodoToggleUnavailable: (MessageId) -> Void + public let requestToggleTodoMessageItem: (EngineMessage.Id, Int32, Bool) -> Void + public let displayTodoToggleUnavailable: (EngineMessage.Id) -> Void public let openStarsPurchase: (Int64?) -> Void public let openRankInfo: (EnginePeer, ChatRankInfoScreenRole, String) -> Void public let openSetPeerAvatar: () -> Void public let displayPollRestrictedToast: (EngineMessage.Id) -> Void public var canPlayMedia: Bool = false - public var hiddenMedia: [MessageId: [Media]] = [:] + public var hiddenMedia: [EngineMessage.Id: [EngineRawMedia]] = [:] public var expandedTranslationMessageStableIds: Set = Set() public var selectionState: ChatInterfaceSelectionState? public var highlightedState: ChatInterfaceHighlightedState? public var contextHighlightedState: ChatInterfaceHighlightedState? public var automaticMediaDownloadSettings: MediaAutoDownloadSettings public var pollActionState: ChatInterfacePollActionState - public var currentPollMessageWithTooltip: MessageId? - public var currentPsaMessageWithTooltip: MessageId? + public var currentPollMessageWithTooltip: EngineMessage.Id? + public var currentPsaMessageWithTooltip: EngineMessage.Id? public var stickerSettings: ChatInterfaceStickerSettings - public var searchTextHighightState: (String, [MessageIndex])? - public var unreadMessageRange: [UnreadMessageRangeKey: Range] = [:] - public var seenOneTimeAnimatedMedia = Set() - public var currentMessageWithLoadingReplyThread: MessageId? + public var searchTextHighightState: (String, [EngineMessage.Index])? + public var unreadMessageRange: [UnreadMessageRangeKey: Range] = [:] + public var seenOneTimeAnimatedMedia = Set() + public var currentMessageWithLoadingReplyThread: EngineMessage.Id? public var updatedPresentationData: (initial: PresentationData, signal: Signal)? public let presentationContext: ChatPresentationContext public var playNextOutgoingGift: Bool = false @@ -345,9 +344,9 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol public var enableFullTranslucency: Bool = true public var chatIsRotated: Bool = true public var canReadHistory: Bool = false - public var summarizedMessageIds: Set = Set() + public var summarizedMessageIds: Set = Set() public var focusedTextInputIsMedia: Bool = false - public var focusedPollAddOptionMessageId: MessageId? + public var focusedPollAddOptionMessageId: EngineMessage.Id? private var isOpeningMediaValue: Bool = false public var isOpeningMedia: Bool { @@ -375,100 +374,100 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol public var isSidePanelOpen: Bool = false public init( - openMessage: @escaping (Message, OpenMessageParams) -> Bool, + openMessage: @escaping (EngineRawMessage, OpenMessageParams) -> Bool, openPeer: @escaping (EnginePeer, ChatControllerInteractionNavigateToPeer, MessageReference?, OpenPeerSource) -> Void, openPeerMention: @escaping (String, Promise?) -> Void, - openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?, CGPoint?) -> Void, - openMessageReactionContextMenu: @escaping (Message, ContextExtractedContentContainingView, ContextGesture?, MessageReaction.Reaction) -> Void, - updateMessageReaction: @escaping (Message, ChatControllerInteractionReaction, Bool, ContextExtractedContentContainingView?) -> Void, + openMessageContextMenu: @escaping (EngineRawMessage, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?, CGPoint?) -> Void, + openMessageReactionContextMenu: @escaping (EngineRawMessage, ContextExtractedContentContainingView, ContextGesture?, MessageReaction.Reaction) -> Void, + updateMessageReaction: @escaping (EngineRawMessage, ChatControllerInteractionReaction, Bool, ContextExtractedContentContainingView?) -> Void, activateMessagePinch: @escaping (PinchSourceContainerNode) -> Void, - openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, - navigateToMessage: @escaping (MessageId, MessageId, NavigateToMessageParams) -> Void, - navigateToMessageStandalone: @escaping (MessageId) -> Void, - navigateToThreadMessage: @escaping (PeerId, Int64, MessageId?) -> Void, - tapMessage: ((Message) -> Void)?, + openMessageContextActions: @escaping (EngineRawMessage, ASDisplayNode, CGRect, ContextGesture?) -> Void, + navigateToMessage: @escaping (EngineMessage.Id, EngineMessage.Id, NavigateToMessageParams) -> Void, + navigateToMessageStandalone: @escaping (EngineMessage.Id) -> Void, + navigateToThreadMessage: @escaping (EnginePeer.Id, Int64, EngineMessage.Id?) -> Void, + tapMessage: ((EngineRawMessage) -> Void)?, clickThroughMessage: @escaping (UIView?, CGPoint?) -> Void, - toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, + toggleMessagesSelection: @escaping ([EngineMessage.Id], Bool) -> Void, sendCurrentMessage: @escaping (Bool, ChatSendMessageEffect?) -> Void, sendMessage: @escaping (String) -> Void, - sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, UIView?, CGRect?, CALayer?, [ItemCollectionId]) -> Bool, + sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, UIView?, CGRect?, CALayer?, [EngineItemCollectionId]) -> Bool, sendEmoji: @escaping (String, ChatTextInputTextCustomEmojiAttribute, Bool) -> Void, sendGif: @escaping (FileMediaReference, UIView, CGRect, Bool, Bool) -> Bool, sendBotContextResultAsGif: @escaping (ChatContextResultCollection, ChatContextResult, UIView, CGRect, Bool, Bool) -> Bool, editGif: @escaping (FileMediaReference, Bool) -> Void, - requestMessageActionCallback: @escaping (Message, MemoryBuffer?, Bool, Bool, Promise?) -> Void, + requestMessageActionCallback: @escaping (EngineRawMessage, EngineMemoryBuffer?, Bool, Bool, Promise?) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageActionUrlSubject) -> Void, - activateSwitchInline: @escaping (PeerId?, String, ReplyMarkupButtonAction.PeerTypes?) -> Void, + activateSwitchInline: @escaping (EnginePeer.Id?, String, ReplyMarkupButtonAction.PeerTypes?) -> Void, openUrl: @escaping (OpenUrl) -> Void, openExternalInstantPage: @escaping (OpenInstantPage) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, - sendBotCommand: @escaping (MessageId?, String) -> Void, - openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, - openWallpaper: @escaping (Message) -> Void, - openTheme: @escaping (Message) -> Void, + sendBotCommand: @escaping (EngineMessage.Id?, String) -> Void, + openInstantPage: @escaping (EngineRawMessage, ChatMessageItemAssociatedData?) -> Void, + openWallpaper: @escaping (EngineRawMessage) -> Void, + openTheme: @escaping (EngineRawMessage) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, updatePresentationState: @escaping ((ChatPresentationInterfaceState) -> ChatPresentationInterfaceState) -> Void, - openMessageShareMenu: @escaping (MessageId) -> Void, + openMessageShareMenu: @escaping (EngineMessage.Id) -> Void, presentController: @escaping (ViewController, Any?) -> Void, presentControllerInCurrent: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, - callPeer: @escaping (PeerId, Bool) -> Void, - openConferenceCall: @escaping (Message) -> Void, + callPeer: @escaping (EnginePeer.Id, Bool) -> Void, + openConferenceCall: @escaping (EngineRawMessage) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, LongTapParams?) -> Void, todoItemLongTap: @escaping (Int32, LongTapParams?) -> Void, pollOptionLongTap: @escaping (Data, LongTapParams?) -> Void, - openCheckoutOrReceipt: @escaping (MessageId, OpenMessageParams?) -> Void, + openCheckoutOrReceipt: @escaping (EngineMessage.Id, OpenMessageParams?) -> Void, openSearch: @escaping () -> Void, - setupReply: @escaping (MessageId) -> Void, - canSetupReply: @escaping (Message) -> ChatControllerInteractionSwipeAction, + setupReply: @escaping (EngineMessage.Id) -> Void, + canSetupReply: @escaping (EngineRawMessage) -> ChatControllerInteractionSwipeAction, canSendMessages: @escaping () -> Bool, navigateToFirstDateMessage: @escaping(Int32, Bool) ->Void, - requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, + requestRedeliveryOfFailedMessages: @escaping (EngineMessage.Id) -> Void, addContact: @escaping (String) -> Void, - rateCall: @escaping (Message, CallId, Bool) -> Void, - requestSelectMessagePollOptions: @escaping (MessageId, [Data]) -> Void, - requestAddMessagePollOption: @escaping (MessageId, String, [MessageTextEntity], Data, AnyMediaReference?) -> Void, - requestOpenMessagePollResults: @escaping (MessageId, MediaId) -> Void, + rateCall: @escaping (EngineRawMessage, CallId, Bool) -> Void, + requestSelectMessagePollOptions: @escaping (EngineMessage.Id, [Data]) -> Void, + requestAddMessagePollOption: @escaping (EngineMessage.Id, String, [MessageTextEntity], Data, AnyMediaReference?) -> Void, + requestOpenMessagePollResults: @escaping (EngineMessage.Id, EngineMedia.Id) -> Void, openAppStorePage: @escaping () -> Void, - displayMessageTooltip: @escaping (MessageId, String, Bool, ASDisplayNode?, CGRect?) -> Void, - seekToTimecode: @escaping (Message, Double, Bool) -> Void, + displayMessageTooltip: @escaping (EngineMessage.Id, String, Bool, ASDisplayNode?, CGRect?) -> Void, + seekToTimecode: @escaping (EngineRawMessage, Double, Bool) -> Void, scheduleCurrentMessage: @escaping (ChatSendMessageActionSheetController.SendParameters?) -> Void, - sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, - editScheduledMessagesTime: @escaping ([MessageId]) -> Void, - performTextSelectionAction: @escaping (Message?, Bool, NSAttributedString, [MessageTextEntity]?, TextSelectionAction) -> Void, + sendScheduledMessagesNow: @escaping ([EngineMessage.Id]) -> Void, + editScheduledMessagesTime: @escaping ([EngineMessage.Id]) -> Void, + performTextSelectionAction: @escaping (EngineRawMessage?, Bool, NSAttributedString, [MessageTextEntity]?, TextSelectionAction) -> Void, displayImportedMessageTooltip: @escaping (ASDisplayNode) -> Void, displaySwipeToReplyHint: @escaping () -> Void, - dismissReplyMarkupMessage: @escaping (Message) -> Void, - openMessagePollResults: @escaping (MessageId, Data) -> Void, + dismissReplyMarkupMessage: @escaping (EngineRawMessage) -> Void, + openMessagePollResults: @escaping (EngineMessage.Id, Data) -> Void, openPollCreation: @escaping (Bool?) -> Void, - openPollMedia: @escaping (Message, PollMediaSubject) -> Void, + openPollMedia: @escaping (EngineRawMessage, PollMediaSubject) -> Void, displayPollSolution: @escaping (TelegramMediaPollResults.Solution?, ASDisplayNode?) -> Void, displayPsa: @escaping (String, ASDisplayNode) -> Void, displayDiceTooltip: @escaping (TelegramMediaDice) -> Void, animateDiceSuccess: @escaping (Bool, Bool) -> Void, - displayPremiumStickerTooltip: @escaping (TelegramMediaFile, Message) -> Void, - displayEmojiPackTooltip: @escaping (TelegramMediaFile, Message) -> Void, - openPeerContextMenu: @escaping (Peer, MessageId?, ASDisplayNode, CGRect, ContextGesture?) -> Void, - openMessageReplies: @escaping (MessageId, Bool, Bool) -> Void, - openReplyThreadOriginalMessage: @escaping (Message) -> Void, - openMessageStats: @escaping (MessageId) -> Void, - editMessageMedia: @escaping (MessageId, Bool) -> Void, + displayPremiumStickerTooltip: @escaping (TelegramMediaFile, EngineRawMessage) -> Void, + displayEmojiPackTooltip: @escaping (TelegramMediaFile, EngineRawMessage) -> Void, + openPeerContextMenu: @escaping (EngineRawPeer, EngineMessage.Id?, ASDisplayNode, CGRect, ContextGesture?) -> Void, + openMessageReplies: @escaping (EngineMessage.Id, Bool, Bool) -> Void, + openReplyThreadOriginalMessage: @escaping (EngineRawMessage) -> Void, + openMessageStats: @escaping (EngineMessage.Id) -> Void, + editMessageMedia: @escaping (EngineMessage.Id, Bool) -> Void, copyText: @escaping (String) -> Void, displayUndo: @escaping (UndoOverlayContent) -> Void, isAnimatingMessage: @escaping (UInt32) -> Bool, getMessageTransitionNode: @escaping () -> ChatMessageTransitionProtocol?, updateChoosingSticker: @escaping (Bool) -> Void, - commitEmojiInteraction: @escaping (MessageId, String, EmojiInteraction, TelegramMediaFile) -> Void, + commitEmojiInteraction: @escaping (EngineMessage.Id, String, EmojiInteraction, TelegramMediaFile) -> Void, openLargeEmojiInfo: @escaping (String, String?, TelegramMediaFile) -> Void, openJoinLink: @escaping (String) -> Void, openWebView: @escaping (String, String, Bool, ChatOpenWebViewSource) -> Void, activateAdAction: @escaping (EngineMessage.Id, Promise?, Bool, Bool) -> Void, - adContextAction: @escaping (Message, ASDisplayNode, ContextGesture?) -> Void, + adContextAction: @escaping (EngineRawMessage, ASDisplayNode, ContextGesture?) -> Void, removeAd: @escaping (Data) -> Void, openRequestedPeerSelection: @escaping (EngineMessage.Id, ReplyMarkupButtonRequestPeerType, Int32, Int32) -> Void, saveMediaToFiles: @escaping (EngineMessage.Id) -> Void, @@ -479,25 +478,25 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol openRecommendedChannelContextMenu: @escaping (EnginePeer, UIView, ContextGesture?) -> Void, openGroupBoostInfo: @escaping (EnginePeer.Id?, Int) -> Void, openStickerEditor: @escaping () -> Void, - openAgeRestrictedMessageMedia: @escaping (Message, @escaping () -> Void) -> Void, - playMessageEffect: @escaping (Message) -> Void, - editMessageFactCheck: @escaping (MessageId) -> Void, + openAgeRestrictedMessageMedia: @escaping (EngineRawMessage, @escaping () -> Void) -> Void, + playMessageEffect: @escaping (EngineRawMessage) -> Void, + editMessageFactCheck: @escaping (EngineMessage.Id) -> Void, sendGift: @escaping (EnginePeer.Id) -> Void, openUniqueGift: @escaping (String) -> Void, openMessageFeeException: @escaping () -> Void, - requestMessageUpdate: @escaping (MessageId, Bool, ControlledTransition?) -> Void, + requestMessageUpdate: @escaping (EngineMessage.Id, Bool, ControlledTransition?) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, dismissTextInput: @escaping () -> Void, - scrollToMessageId: @escaping (MessageIndex, CGFloat) -> Void, - scrollToMessageIdWithAnchor: @escaping (MessageIndex, String) -> Void, - navigateToStory: @escaping (Message, StoryId) -> Void, - attemptedNavigationToPrivateQuote: @escaping (Peer?) -> Void, + scrollToMessageId: @escaping (EngineMessage.Index, CGFloat) -> Void, + scrollToMessageIdWithAnchor: @escaping (EngineMessage.Index, String) -> Void, + navigateToStory: @escaping (EngineRawMessage, EngineStoryId) -> Void, + attemptedNavigationToPrivateQuote: @escaping (EngineRawPeer?) -> Void, forceUpdateWarpContents: @escaping () -> Void, playShakeAnimation: @escaping () -> Void, - displayQuickShare: @escaping (MessageId, ASDisplayNode, ContextGesture) -> Void, + displayQuickShare: @escaping (EngineMessage.Id, ASDisplayNode, ContextGesture) -> Void, updateChatLocationThread: @escaping (Int64?, ChatControllerAnimateInnerChatSwitchDirection?) -> Void, - requestToggleTodoMessageItem: @escaping (MessageId, Int32, Bool) -> Void, - displayTodoToggleUnavailable: @escaping (MessageId) -> Void, + requestToggleTodoMessageItem: @escaping (EngineMessage.Id, Int32, Bool) -> Void, + displayTodoToggleUnavailable: @escaping (EngineMessage.Id) -> Void, openStarsPurchase: @escaping (Int64?) -> Void, openRankInfo: @escaping (EnginePeer, ChatRankInfoScreenRole, String) -> Void, openSetPeerAvatar: @escaping () -> Void, diff --git a/submodules/TelegramUI/Components/EntityKeyboardGifContent/BUILD b/submodules/TelegramUI/Components/EntityKeyboardGifContent/BUILD index cc15d62131..1888991dca 100644 --- a/submodules/TelegramUI/Components/EntityKeyboardGifContent/BUILD +++ b/submodules/TelegramUI/Components/EntityKeyboardGifContent/BUILD @@ -19,7 +19,6 @@ swift_library( "//submodules/Components/BundleIconComponent:BundleIconComponent", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/TelegramCore:TelegramCore", - "//submodules/Postbox:Postbox", "//submodules/AnimatedStickerNode:AnimatedStickerNode", "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", "//submodules/YuvConversion:YuvConversion", diff --git a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift index ec517ecc7e..0db09aed45 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/GiftSetupScreen.swift @@ -376,7 +376,7 @@ private final class GiftSetupScreenComponent: Component { let (currency, amount) = storeProduct.priceCurrencyAndAmount - addAppLogEvent(postbox: component.context.account.postbox, type: "premium_gift.promo_screen_accept") + component.context.engine.accountData.addAppLogEvent(type: "premium_gift.promo_screen_accept") var textInputText = NSAttributedString() if let inputPanelView = self.inputPanel.view as? MessageInputPanelComponent.View, case let .text(text) = inputPanelView.getSendMessageInput() { @@ -450,7 +450,7 @@ private final class GiftSetupScreenComponent: Component { } if let errorText { - addAppLogEvent(postbox: component.context.account.postbox, type: "premium_gift.promo_screen_fail") + component.context.engine.accountData.addAppLogEvent(type: "premium_gift.promo_screen_fail") let alertController = textAlertController(context: component.context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]) controller.present(alertController, in: .window(.root)) diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/BUILD b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/BUILD index 3f8e64ed20..3dad3ead7d 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/BUILD +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/AsyncDisplayKit", "//submodules/Display", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackCurrentItem.swift b/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackCurrentItem.swift index 622412a738..edc3f81720 100644 --- a/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackCurrentItem.swift +++ b/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackCurrentItem.swift @@ -3,7 +3,6 @@ import UIKit import Display import AsyncDisplayKit import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import ItemListUI @@ -323,7 +322,7 @@ class GroupStickerPackCurrentItemNode: ItemListRevealOptionsItemNode { } var updatedImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? - var updatedFetchSignal: Signal? + var updatedFetchSignal: Signal? if fileUpdated { if let file = file { updatedImageSignal = chatMessageSticker(account: item.account, userLocation: .other, file: file, small: false) diff --git a/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerSearchContainerNode.swift b/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerSearchContainerNode.swift index e8224ba5ca..381166f2d7 100644 --- a/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerSearchContainerNode.swift +++ b/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerSearchContainerNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -24,15 +23,15 @@ private final class GroupStickerSearchContainerInteraction { private final class GroupStickerSearchEntry: Comparable, Identifiable { let index: Int let pack: StickerPackCollectionInfo - let topItem: ItemCollectionItem? + let topItem: EngineRawItemCollectionItem? - init(index: Int, pack: StickerPackCollectionInfo, topItem: ItemCollectionItem?) { + init(index: Int, pack: StickerPackCollectionInfo, topItem: EngineRawItemCollectionItem?) { self.index = index self.pack = pack self.topItem = topItem } - var stableId: ItemCollectionId { + var stableId: EngineItemCollectionId { return self.pack.id } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatListPaneNode/BUILD b/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatListPaneNode/BUILD index 586c694ff3..2cbff8a410 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatListPaneNode/BUILD +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatListPaneNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit", "//submodules/AsyncDisplayKit", "//submodules/TelegramCore", - "//submodules/Postbox", "//submodules/TelegramPresentationData", "//submodules/AccountContext", "//submodules/TelegramStringFormatting", diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatPaneNode/BUILD b/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatPaneNode/BUILD index 067d915018..fe815d3255 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatPaneNode/BUILD +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatPaneNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit", "//submodules/AsyncDisplayKit", "//submodules/TelegramCore", - "//submodules/Postbox", "//submodules/TelegramPresentationData", "//submodules/AccountContext", "//submodules/TelegramStringFormatting", diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/BUILD b/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/BUILD index 1e8570712a..3bd9654bb7 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/BUILD +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/BUILD @@ -11,7 +11,6 @@ swift_library( ], deps = [ "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/AsyncDisplayKit", "//submodules/Display", diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoListPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoListPaneNode.swift index 774651c5c4..84d5d770e4 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoListPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoListPaneNode.swift @@ -3,7 +3,6 @@ import AsyncDisplayKit import Display import TelegramCore import SwiftSignalKit -import Postbox import TelegramPresentationData import PresentationDataUtils import AccountContext @@ -23,7 +22,7 @@ import PeerInfoPaneNode final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { private let context: AccountContext - private let peerId: PeerId + private let peerId: EnginePeer.Id private let chatLocation: ChatLocation private let chatLocationContextHolder: Atomic private let chatControllerInteraction: ChatControllerInteraction @@ -40,8 +39,8 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { return self.ready.get() } - private let selectedMessagesPromise = Promise?>(nil) - private var selectedMessages: Set? { + private let selectedMessagesPromise = Promise?>(nil) + private var selectedMessages: Set? { didSet { if self.selectedMessages != oldValue { self.selectedMessagesPromise.set(.single(self.selectedMessages)) @@ -69,7 +68,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { return 0.0 } - init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, chatControllerInteraction: ChatControllerInteraction, peerId: PeerId, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, tagMask: MessageTags) { + init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, chatControllerInteraction: ChatControllerInteraction, peerId: EnginePeer.Id, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, tagMask: EngineMessage.Tags) { self.context = context self.peerId = peerId self.chatLocation = chatLocation @@ -166,15 +165,15 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { let presentationData = context.sharedContext.currentPresentationData.with { $0 } switch tagMask { - case MessageTags.file: + case EngineMessage.Tags.file: return PeerInfoStatusData(text: presentationData.strings.SharedMedia_FileCount(Int32(count)), isActivity: false, key: .files) - case MessageTags.music: + case EngineMessage.Tags.music: return PeerInfoStatusData(text: presentationData.strings.SharedMedia_MusicCount(Int32(count)), isActivity: false, key: .music) - case MessageTags.voiceOrInstantVideo: + case EngineMessage.Tags.voiceOrInstantVideo: return PeerInfoStatusData(text: presentationData.strings.SharedMedia_VoiceMessageCount(Int32(count)), isActivity: false, key: .voice) - case MessageTags.webPage: + case EngineMessage.Tags.webPage: return PeerInfoStatusData(text: presentationData.strings.SharedMedia_LinkCount(Int32(count)), isActivity: false, key: .links) - case MessageTags.polls: + case EngineMessage.Tags.polls: return PeerInfoStatusData(text: presentationData.strings.SharedMedia_PollCount(Int32(count)), isActivity: false, key: .links) default: return nil @@ -276,7 +275,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { let settings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.musicPlaybackSettings)?.get(MusicPlaybackSettings.self) ?? MusicPlaybackSettings.defaultSettings transaction.updateSharedData(ApplicationSpecificSharedDataKeys.musicPlaybackSettings, { _ in - return PreferencesEntry(settings.withUpdatedVoicePlaybackRate(rate)) + return EnginePreferencesEntry(settings.withUpdatedVoicePlaybackRate(rate)) }) return rate } @@ -371,7 +370,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode { } if let id = state.id as? PeerMessagesMediaPlaylistItemId, let playlistLocation = strongSelf.playlistLocation as? PeerMessagesPlaylistLocation, case let .messages(chatLocation, _, _) = playlistLocation { if type == .music { - let signal = strongSelf.context.sharedContext.messageFromPreloadedChatHistoryViewForLocation(id: id.messageId, location: ChatHistoryLocationInput(content: .InitialSearch(subject: MessageHistoryInitialSearchSubject(location: .id(id.messageId)), count: 60, highlight: true, setupReply: false), id: 0), context: strongSelf.context, chatLocation: .peer(id: id.messageId.peerId), subject: nil, chatLocationContextHolder: Atomic(value: nil), tag: .tag(MessageTags.music)) + let signal = strongSelf.context.sharedContext.messageFromPreloadedChatHistoryViewForLocation(id: id.messageId, location: ChatHistoryLocationInput(content: .InitialSearch(subject: MessageHistoryInitialSearchSubject(location: .id(id.messageId)), count: 60, highlight: true, setupReply: false), id: 0), context: strongSelf.context, chatLocation: .peer(id: id.messageId.peerId), subject: nil, chatLocationContextHolder: Atomic(value: nil), tag: .tag(EngineMessage.Tags.music)) var cancelImpl: (() -> Void)? let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } diff --git a/submodules/TelegramUI/Components/Resources/FetchAudioMediaResource/BUILD b/submodules/TelegramUI/Components/Resources/FetchAudioMediaResource/BUILD index 24183c1036..54d18e0f46 100644 --- a/submodules/TelegramUI/Components/Resources/FetchAudioMediaResource/BUILD +++ b/submodules/TelegramUI/Components/Resources/FetchAudioMediaResource/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/TelegramCore", "//submodules/LegacyComponents", diff --git a/submodules/TelegramUI/Components/Resources/FetchAudioMediaResource/Sources/FetchAudioMediaResource.swift b/submodules/TelegramUI/Components/Resources/FetchAudioMediaResource/Sources/FetchAudioMediaResource.swift index 97acda1ddb..c451ecab49 100644 --- a/submodules/TelegramUI/Components/Resources/FetchAudioMediaResource/Sources/FetchAudioMediaResource.swift +++ b/submodules/TelegramUI/Components/Resources/FetchAudioMediaResource/Sources/FetchAudioMediaResource.swift @@ -1,14 +1,13 @@ import Foundation import UIKit -import Postbox import SwiftSignalKit import TelegramCore import FFMpegBinding import LocalMediaResources -public func fetchLocalFileAudioMediaResource(postbox: Postbox, resource: LocalFileAudioMediaResource) -> Signal { +public func fetchLocalFileAudioMediaResource(resource: LocalFileAudioMediaResource) -> Signal { let tempFile = EngineTempBox.shared.tempFile(fileName: "audio.ogg") FFMpegOpusTrimmer.trim(resource.path, to: tempFile.path, start: resource.trimRange?.lowerBound ?? 0.0, end: resource.trimRange?.upperBound ?? 1.0) - + return .single(.moveTempFile(file: tempFile)) } diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift index c00225f8a7..46c32e6195 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/ChannelAppearanceScreen.swift @@ -4,7 +4,6 @@ import Photos import Display import AsyncDisplayKit import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -98,7 +97,7 @@ final class ChannelAppearanceScreenComponent: Component { TelegramEngine.EngineData.Item.Peer.StickerPack(id: peerId), TelegramEngine.EngineData.Item.Peer.Wallpaper(id: peerId) ), - telegramThemes(postbox: context.account.postbox, network: context.account.network, accountManager: context.sharedContext.accountManager) + context.engine.themes.themes(accountManager: context.sharedContext.accountManager) ) |> map { peerData, cloudThemes -> ContentsData in let (peer, subscriberCount, emojiPack, canSetStickerPack, stickerPack, wallpaper) = peerData @@ -695,9 +694,9 @@ final class ChannelAppearanceScreenComponent: Component { self.previousEmojiSetupTimestamp = currentTimestamp self.emojiStatusSelectionController?.dismiss() - var selectedItems = Set() + var selectedItems = Set() if let currentFileId { - selectedItems.insert(MediaId(namespace: Namespaces.Media.CloudFile, id: currentFileId)) + selectedItems.insert(EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: currentFileId)) } let mappedSubject: EmojiPagerContentComponent.Subject @@ -1303,7 +1302,7 @@ final class ChannelAppearanceScreenComponent: Component { var emojiPackFile: TelegramMediaFile? if let thumbnail = emojiPack?.thumbnail { - emojiPackFile = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: thumbnail.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: thumbnail.immediateThumbnailData, mimeType: "", size: nil, attributes: [], alternativeRepresentations: []) + emojiPackFile = TelegramMediaFile(fileId: EngineMedia.Id(namespace: 0, id: 0), partialReference: nil, resource: thumbnail.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: thumbnail.immediateThumbnailData, mimeType: "", size: nil, attributes: [], alternativeRepresentations: []) } let emojiPackSectionSize = self.emojiPackSection.update( @@ -1435,7 +1434,7 @@ final class ChannelAppearanceScreenComponent: Component { var stickerPackFile: TelegramMediaFile? if let peerStickerPack = contentsData.peerStickerPack, let thumbnail = peerStickerPack.thumbnail { - stickerPackFile = TelegramMediaFile(fileId: MediaId(namespace: 0, id: peerStickerPack.id.id), partialReference: nil, resource: thumbnail.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: thumbnail.immediateThumbnailData, mimeType: "", size: nil, attributes: [], alternativeRepresentations: []) + stickerPackFile = TelegramMediaFile(fileId: EngineMedia.Id(namespace: 0, id: peerStickerPack.id.id), partialReference: nil, resource: thumbnail.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: thumbnail.immediateThumbnailData, mimeType: "", size: nil, attributes: [], alternativeRepresentations: []) } let stickerPackSectionSize = self.stickerPackSection.update( @@ -1505,7 +1504,7 @@ final class ChannelAppearanceScreenComponent: Component { if !isGroup { let messageItem = PeerNameColorChatPreviewItem.MessageItem( outgoing: false, - peerId: EnginePeer.Id(namespace: peer.id.namespace, id: PeerId.Id._internalFromInt64Value(0)), + peerId: EnginePeer.Id(namespace: peer.id.namespace, id: EnginePeer.Id.Id._internalFromInt64Value(0)), author: peer.compactDisplayTitle, photo: peer.profileImageRepresentations, nameColor: .preset(resolvedState.nameColor), @@ -1644,7 +1643,7 @@ final class ChannelAppearanceScreenComponent: Component { if isGroup { let incomingMessageItem = PeerNameColorChatPreviewItem.MessageItem( outgoing: false, - peerId: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), + peerId: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), author: environment.strings.Group_Appearance_PreviewAuthor, photo: [], nameColor: .preset(.red), @@ -1656,7 +1655,7 @@ final class ChannelAppearanceScreenComponent: Component { let outgoingMessageItem = PeerNameColorChatPreviewItem.MessageItem( outgoing: true, - peerId: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), + peerId: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)), author: peer.compactDisplayTitle, photo: peer.profileImageRepresentations, nameColor: .preset(.blue), diff --git a/submodules/TelegramUI/Components/Settings/SettingsThemeWallpaperNode/Sources/SettingsThemeWallpaperNode.swift b/submodules/TelegramUI/Components/Settings/SettingsThemeWallpaperNode/Sources/SettingsThemeWallpaperNode.swift index 5756cf369e..86a9ecb6ff 100644 --- a/submodules/TelegramUI/Components/Settings/SettingsThemeWallpaperNode/Sources/SettingsThemeWallpaperNode.swift +++ b/submodules/TelegramUI/Components/Settings/SettingsThemeWallpaperNode/Sources/SettingsThemeWallpaperNode.swift @@ -232,7 +232,7 @@ public final class SettingsThemeWallpaperNode: ASDisplayNode { switch wallpaper { case .builtin: self.imageNode.alpha = 1.0 - self.imageNode.setSignal(settingsBuiltinWallpaperImage(account: context.account, thumbnail: true)) + self.imageNode.setSignal(settingsBuiltinWallpaperImage(thumbnail: true)) let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: corners, imageSize: CGSize(), boundingSize: size, intrinsicInsets: UIEdgeInsets())) apply() self.isLoadedDisposable.set(nil) diff --git a/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorController.swift b/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorController.swift index 3acf431bae..3b656ee5be 100644 --- a/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorController.swift +++ b/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorController.swift @@ -385,7 +385,7 @@ public final class ThemeAccentColorController: ViewController { let _ = (combineLatest( self.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationThemeSettings]) |> take(1), - telegramWallpapers(postbox: context.account.postbox, network: context.account.network) |> take(1) + context.engine.themes.wallpapers() |> take(1) ) |> deliverOnMainQueue).start(next: { [weak self] sharedData, wallpapers in guard let strongSelf = self else { diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift index 247e0f75eb..b7888119d0 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift @@ -719,7 +719,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode { case .builtin, .emoticon: displaySize = CGSize(width: 1308.0, height: 2688.0).fitted(CGSize(width: 1280.0, height: 1280.0)).dividedByScreenScale().integralFloor contentSize = displaySize - signal = settingsBuiltinWallpaperImage(account: self.context.account) + signal = settingsBuiltinWallpaperImage() fetchSignal = .complete() statusSignal = .single(.Local) subtitleSignal = .single(nil) @@ -875,7 +875,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode { let dimensions = CGSize(width: asset.pixelWidth, height: asset.pixelHeight) contentSize = dimensions displaySize = dimensions.aspectFittedOrSmaller(CGSize(width: 2048.0, height: 2048.0)) - signal = photoWallpaper(postbox: context.account.postbox, photoLibraryResource: PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: Int64.random(in: Int64.min ... Int64.max))) + signal = photoWallpaper(photoLibraryResource: PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: Int64.random(in: Int64.min ... Int64.max))) fetchSignal = .complete() statusSignal = .single(.Local) subtitleSignal = .single(nil) diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperPatternPanelNode.swift b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperPatternPanelNode.swift index 22810d275e..bed529da7e 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperPatternPanelNode.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperPatternPanelNode.swift @@ -255,7 +255,7 @@ public final class WallpaperPatternPanelNode: ASDisplayNode { self.addSubnode(self.titleNode) self.addSubnode(self.labelNode) - self.disposable = ((telegramWallpapers(postbox: context.account.postbox, network: context.account.network) + self.disposable = ((context.engine.themes.wallpapers() |> map { wallpapers -> [TelegramWallpaper] in var existingIds = Set() diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridController.swift b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridController.swift index b7d86b3f0f..2c4d0213fa 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridController.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridController.swift @@ -359,7 +359,7 @@ public final class ThemeGridController: ViewController { }) }).start() - let _ = (telegramWallpapers(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network) + let _ = (strongSelf.context.engine.themes.wallpapers() |> deliverOnMainQueue).start(completed: { [weak self, weak controller] in controller?.dismiss() if let strongSelf = self { diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift index c316cecebb..7c2b63a292 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridControllerNode.swift @@ -633,7 +633,7 @@ final class ThemeGridControllerNode: ASDisplayNode { switch self.mode { case .generic: self.wallpapersPromise.set(combineLatest(queue: .mainQueue(), - telegramWallpapers(postbox: self.context.account.postbox, network: self.context.account.network), + self.context.engine.themes.wallpapers(), self.context.sharedContext.accountManager.sharedData(keys: [SharedDataKeys.wallapersState]) ) |> map { remoteWallpapers, sharedData -> [Wallpaper] in diff --git a/submodules/TelegramUI/Components/Stories/StorySetIndicatorComponent/Sources/StorySetIndicatorComponent.swift b/submodules/TelegramUI/Components/Stories/StorySetIndicatorComponent/Sources/StorySetIndicatorComponent.swift index 446e8d1910..29f49ec090 100644 --- a/submodules/TelegramUI/Components/Stories/StorySetIndicatorComponent/Sources/StorySetIndicatorComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StorySetIndicatorComponent/Sources/StorySetIndicatorComponent.swift @@ -203,7 +203,7 @@ public final class StorySetIndicatorComponent: Component { var fetchSignal: Signal? if displayAvatars { - imageSignal = peerAvatarCompleteImage(postbox: context.account.postbox, network: context.account.network, peer: item.peer, forceProvidedRepresentation: false, representation: nil, size: CGSize(width: 26.0, height: 26.0), round: true, font: avatarPlaceholderFont(size: 13.0), drawLetters: true, fullSize: false, blurred: false) + imageSignal = peerAvatarCompleteImage(postbox: context.account.postbox, peer: item.peer, forceProvidedRepresentation: false, representation: nil, size: CGSize(width: 26.0, height: 26.0), round: true, font: avatarPlaceholderFont(size: 13.0), drawLetters: true, fullSize: false, blurred: false) } else { switch messageMedia { case let .image(image): diff --git a/submodules/TelegramUI/Components/TelegramAccountAuxiliaryMethods/Sources/TelegramAccountAuxiliaryMethods.swift b/submodules/TelegramUI/Components/TelegramAccountAuxiliaryMethods/Sources/TelegramAccountAuxiliaryMethods.swift index 3f6203887f..976b942ba6 100644 --- a/submodules/TelegramUI/Components/TelegramAccountAuxiliaryMethods/Sources/TelegramAccountAuxiliaryMethods.swift +++ b/submodules/TelegramUI/Components/TelegramAccountAuxiliaryMethods/Sources/TelegramAccountAuxiliaryMethods.swift @@ -46,7 +46,7 @@ public func makeTelegramAccountAuxiliaryMethods(uploadInBackground: ((Postbox, M return fetchLocalFileVideoMediaResource(postbox: postbox, resource: resource, alwaysUseModernPipeline: useModernPipeline) } } else if let resource = resource as? LocalFileAudioMediaResource { - return fetchLocalFileAudioMediaResource(postbox: postbox, resource: resource) + return fetchLocalFileAudioMediaResource(resource: resource) } else if let resource = resource as? LocalFileGifMediaResource { return fetchLocalFileGifMediaResource(resource: resource) } else if let photoLibraryResource = resource as? PhotoLibraryMediaResource { diff --git a/submodules/TelegramUI/Components/TelegramUIDeclareEncodables/BUILD b/submodules/TelegramUI/Components/TelegramUIDeclareEncodables/BUILD index 5faf3562fe..72a004e510 100644 --- a/submodules/TelegramUI/Components/TelegramUIDeclareEncodables/BUILD +++ b/submodules/TelegramUI/Components/TelegramUIDeclareEncodables/BUILD @@ -10,7 +10,7 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", + "//submodules/TelegramCore", "//submodules/TemporaryCachedPeerDataManager", "//submodules/TelegramUIPreferences", "//submodules/TelegramNotices", diff --git a/submodules/TelegramUI/Components/TelegramUIDeclareEncodables/Sources/TelegramUIDeclareEncodables.swift b/submodules/TelegramUI/Components/TelegramUIDeclareEncodables/Sources/TelegramUIDeclareEncodables.swift index 461dc1999b..203fcd6656 100644 --- a/submodules/TelegramUI/Components/TelegramUIDeclareEncodables/Sources/TelegramUIDeclareEncodables.swift +++ b/submodules/TelegramUI/Components/TelegramUIDeclareEncodables/Sources/TelegramUIDeclareEncodables.swift @@ -1,4 +1,4 @@ -import Postbox +import TelegramCore import TemporaryCachedPeerDataManager import TelegramUIPreferences import TelegramNotices @@ -15,12 +15,12 @@ import ChatInterfaceState import ICloudResources private var telegramUIDeclaredEncodables: Void = { - declareEncodable(VideoLibraryMediaResource.self, f: { VideoLibraryMediaResource(decoder: $0) }) - declareEncodable(LocalFileVideoMediaResource.self, f: { LocalFileVideoMediaResource(decoder: $0) }) - declareEncodable(LocalFileAudioMediaResource.self, f: { LocalFileAudioMediaResource(decoder: $0) }) - declareEncodable(LocalFileGifMediaResource.self, f: { LocalFileGifMediaResource(decoder: $0) }) - declareEncodable(PhotoLibraryMediaResource.self, f: { PhotoLibraryMediaResource(decoder: $0) }) - declareEncodable(ICloudFileResource.self, f: { ICloudFileResource(decoder: $0) }) + engineDeclareEncodable(VideoLibraryMediaResource.self, f: { VideoLibraryMediaResource(decoder: $0) }) + engineDeclareEncodable(LocalFileVideoMediaResource.self, f: { LocalFileVideoMediaResource(decoder: $0) }) + engineDeclareEncodable(LocalFileAudioMediaResource.self, f: { LocalFileAudioMediaResource(decoder: $0) }) + engineDeclareEncodable(LocalFileGifMediaResource.self, f: { LocalFileGifMediaResource(decoder: $0) }) + engineDeclareEncodable(PhotoLibraryMediaResource.self, f: { PhotoLibraryMediaResource(decoder: $0) }) + engineDeclareEncodable(ICloudFileResource.self, f: { ICloudFileResource(decoder: $0) }) return }() diff --git a/submodules/TelegramUI/Components/WallpaperPreviewMedia/Sources/WallpaperPreviewMedia.swift b/submodules/TelegramUI/Components/WallpaperPreviewMedia/Sources/WallpaperPreviewMedia.swift index f2863df6c2..bbd149be09 100644 --- a/submodules/TelegramUI/Components/WallpaperPreviewMedia/Sources/WallpaperPreviewMedia.swift +++ b/submodules/TelegramUI/Components/WallpaperPreviewMedia/Sources/WallpaperPreviewMedia.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import TelegramCore public enum WallpaperPreviewMediaContent: Equatable { @@ -12,11 +11,11 @@ public enum WallpaperPreviewMediaContent: Equatable { case emoticon(String) } -public final class WallpaperPreviewMedia: Media { - public var id: MediaId? { +public final class WallpaperPreviewMedia: EngineRawMedia { + public var id: EngineMedia.Id? { return nil } - public let peerIds: [PeerId] = [] + public let peerIds: [EnginePeer.Id] = [] public let content: WallpaperPreviewMediaContent @@ -24,14 +23,14 @@ public final class WallpaperPreviewMedia: Media { self.content = content } - public init(decoder: PostboxDecoder) { + public init(decoder: EnginePostboxDecoder) { self.content = .color(.clear) } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { } - public func isEqual(to other: Media) -> Bool { + public func isEqual(to other: EngineRawMedia) -> Bool { guard let other = other as? WallpaperPreviewMedia else { return false } @@ -43,7 +42,7 @@ public final class WallpaperPreviewMedia: Media { return true } - public func isSemanticallyEqual(to other: Media) -> Bool { + public func isSemanticallyEqual(to other: EngineRawMedia) -> Bool { return self.isEqual(to: other) } } @@ -73,11 +72,11 @@ public extension WallpaperPreviewMedia { } } -public final class UniqueGiftPreviewMedia: Media { - public var id: MediaId? { +public final class UniqueGiftPreviewMedia: EngineRawMedia { + public var id: EngineMedia.Id? { return nil } - public let peerIds: [PeerId] = [] + public let peerIds: [EnginePeer.Id] = [] public let content: StarGift.UniqueGift? @@ -85,14 +84,14 @@ public final class UniqueGiftPreviewMedia: Media { self.content = content } - public init(decoder: PostboxDecoder) { + public init(decoder: EnginePostboxDecoder) { self.content = nil } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { } - public func isEqual(to other: Media) -> Bool { + public func isEqual(to other: EngineRawMedia) -> Bool { guard let other = other as? UniqueGiftPreviewMedia else { return false } @@ -104,17 +103,17 @@ public final class UniqueGiftPreviewMedia: Media { return true } - public func isSemanticallyEqual(to other: Media) -> Bool { + public func isSemanticallyEqual(to other: EngineRawMedia) -> Bool { return self.isEqual(to: other) } } -public final class GiftAuctionPreviewMedia: Media { - public var id: MediaId? { +public final class GiftAuctionPreviewMedia: EngineRawMedia { + public var id: EngineMedia.Id? { return nil } - public let peerIds: [PeerId] = [] + public let peerIds: [EnginePeer.Id] = [] public let content: StarGift.Gift? public let endTime: Int32 @@ -124,15 +123,15 @@ public final class GiftAuctionPreviewMedia: Media { self.endTime = endTime } - public init(decoder: PostboxDecoder) { + public init(decoder: EnginePostboxDecoder) { self.content = nil self.endTime = 0 } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { } - public func isEqual(to other: Media) -> Bool { + public func isEqual(to other: EngineRawMedia) -> Bool { guard let other = other as? GiftAuctionPreviewMedia else { return false } @@ -144,7 +143,7 @@ public final class GiftAuctionPreviewMedia: Media { return true } - public func isSemanticallyEqual(to other: Media) -> Bool { + public func isSemanticallyEqual(to other: EngineRawMedia) -> Bool { return self.isEqual(to: other) } } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 953692fad1..f15c0d78a2 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -212,7 +212,7 @@ func isTopmostChatController(_ controller: ChatControllerImpl) -> Bool { return true } -func calculateSlowmodeActiveUntilTimestamp(account: Account, untilTimestamp: Int32?) -> Int32? { +func calculateSlowmodeActiveUntilTimestamp(untilTimestamp: Int32?) -> Int32? { guard let untilTimestamp = untilTimestamp else { return nil } diff --git a/submodules/TelegramUI/Sources/ChatControllerContentData.swift b/submodules/TelegramUI/Sources/ChatControllerContentData.swift index fcc7e6e66f..77366bb6f7 100644 --- a/submodules/TelegramUI/Sources/ChatControllerContentData.swift +++ b/submodules/TelegramUI/Sources/ChatControllerContentData.swift @@ -1907,7 +1907,7 @@ extension ChatControllerImpl { canBypassRestrictions = true } if !canBypassRestrictions, let channel = combinedInitialData.initialData?.peer as? TelegramChannel, channel.isRestrictedBySlowmode, let timeout = cachedData.slowModeTimeout { - if let slowmodeUntilTimestamp = calculateSlowmodeActiveUntilTimestamp(account: context.account, untilTimestamp: cachedData.slowModeValidUntilTimestamp) { + if let slowmodeUntilTimestamp = calculateSlowmodeActiveUntilTimestamp(untilTimestamp: cachedData.slowModeValidUntilTimestamp) { slowmodeState = ChatSlowmodeState(timeout: timeout, variant: .timestamp(slowmodeUntilTimestamp)) } } @@ -2313,7 +2313,7 @@ extension ChatControllerImpl { if let channel = strongSelf.state.renderedPeer?.peer as? TelegramChannel, channel.isRestrictedBySlowmode, let timeout = cachedData.slowModeTimeout { if hasPendingMessages { slowmodeState = ChatSlowmodeState(timeout: timeout, variant: .pendingMessages) - } else if let slowmodeUntilTimestamp = calculateSlowmodeActiveUntilTimestamp(account: context.account, untilTimestamp: cachedData.slowModeValidUntilTimestamp) { + } else if let slowmodeUntilTimestamp = calculateSlowmodeActiveUntilTimestamp(untilTimestamp: cachedData.slowModeValidUntilTimestamp) { slowmodeState = ChatSlowmodeState(timeout: timeout, variant: .timestamp(slowmodeUntilTimestamp)) } } diff --git a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift index 324fd0e7e6..61744d861e 100644 --- a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import AsyncDisplayKit -import Postbox import TelegramCore import SwiftSignalKit import TelegramPresentationData @@ -570,7 +569,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { } } - private func enqueueTransition(width: CGFloat, panelHeight: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, animation: PinnedMessageAnimation?, pinnedMessage: ChatPinnedMessage, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: PeerId, firstTime: Bool, isReplyThread: Bool, translateToLanguage: String?) { + private func enqueueTransition(width: CGFloat, panelHeight: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, animation: PinnedMessageAnimation?, pinnedMessage: ChatPinnedMessage, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: EnginePeer.Id, firstTime: Bool, isReplyThread: Bool, translateToLanguage: String?) { let message = pinnedMessage.message var animationTransition: ContainedViewLayoutTransition = .immediate @@ -661,7 +660,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { } else if let paidContent = media as? TelegramMediaPaidContent, let firstMedia = paidContent.extendedMedia.first { switch firstMedia { case let .preview(dimensions, immediateThumbnailData, _): - let thumbnailMedia = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: [], immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) + let thumbnailMedia = TelegramMediaImage(imageId: EngineMedia.Id(namespace: 0, id: 0), representations: [], immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) if let dimensions { imageDimensions = dimensions.cgSize } @@ -722,7 +721,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { let hasSpoiler = message.attributes.contains(where: { $0 is MediaSpoilerMessageAttribute }) var updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? - var updatedFetchMediaSignal: Signal? + var updatedFetchMediaSignal: Signal? if mediaUpdated { if let updatedMediaReference = updatedMediaReference, imageDimensions != nil { if let imageReference = updatedMediaReference.concrete(TelegramMediaImage.self) { @@ -976,22 +975,22 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { }) return case let .switchInline(samePeer, query, peerTypes): - var botPeer: Peer? - + var botPeer: EnginePeer? + var found = false for attribute in message.attributes { if let attribute = attribute as? InlineBotMessageAttribute { if let peerId = attribute.peerId { - botPeer = message.peers[peerId] + botPeer = message.peers[peerId].flatMap(EnginePeer.init) found = true } } } if !found { - botPeer = message.author + botPeer = message.author.flatMap(EnginePeer.init) } - - var peerId: PeerId? + + var peerId: EnginePeer.Id? if samePeer { peerId = message.id.peerId } diff --git a/submodules/TelegramUI/Sources/FetchCachedRepresentations.swift b/submodules/TelegramUI/Sources/FetchCachedRepresentations.swift index 0e6be30087..1aa4751861 100644 --- a/submodules/TelegramUI/Sources/FetchCachedRepresentations.swift +++ b/submodules/TelegramUI/Sources/FetchCachedRepresentations.swift @@ -29,7 +29,7 @@ public func fetchCachedResourceRepresentation(account: Account, resource: MediaR if !data.complete { return .complete() } - return fetchCachedStickerAJpegRepresentation(account: account, resource: resource, resourceData: data, representation: representation) + return fetchCachedStickerAJpegRepresentation(resource: resource, resourceData: data, representation: representation) } } else if let representation = representation as? CachedScaledImageRepresentation { return account.postbox.mediaBox.resourceData(resource, option: .complete(waitUntilFetchStatus: false)) @@ -130,7 +130,7 @@ public func fetchCachedResourceRepresentation(account: Account, resource: MediaR return account.postbox.mediaBox.resourceData(resource, option: .complete(waitUntilFetchStatus: false)) |> mapToSignal { data -> Signal in if data.complete, let fileData = try? Data(contentsOf: URL(fileURLWithPath: data.path)) { - return fetchCachedAlbumArtworkRepresentation(account: account, resource: resource, data: fileData, representation: representation) + return fetchCachedAlbumArtworkRepresentation(resource: resource, data: fileData, representation: representation) |> `catch` { _ -> Signal in return .complete() } @@ -138,7 +138,7 @@ public func fetchCachedResourceRepresentation(account: Account, resource: MediaR return account.postbox.mediaBox.resourceData(resource, size: size, in: 0 ..< min(size, 256 * 1024)) |> mapToSignal { result -> Signal in let (data, _) = result - return fetchCachedAlbumArtworkRepresentation(account: account, resource: resource, data: data, representation: representation) + return fetchCachedAlbumArtworkRepresentation(resource: resource, data: data, representation: representation) |> `catch` { error -> Signal in switch error { case let .moreDataNeeded(targetSize): @@ -146,7 +146,7 @@ public func fetchCachedResourceRepresentation(account: Account, resource: MediaR |> mapToSignal { result -> Signal in let (data, _) = result - return fetchCachedAlbumArtworkRepresentation(account: account, resource: resource, data: data, representation: representation) + return fetchCachedAlbumArtworkRepresentation(resource: resource, data: data, representation: representation) |> `catch` { error -> Signal in return .complete() } @@ -164,7 +164,7 @@ public func fetchCachedResourceRepresentation(account: Account, resource: MediaR if !data.complete { return .complete() } - return fetchAnimatedStickerRepresentation(account: account, resource: resource, resourceData: data, representation: representation) + return fetchAnimatedStickerRepresentation(resource: resource, resourceData: data, representation: representation) } } else if let representation = representation as? CachedVideoStickerRepresentation { return account.postbox.mediaBox.resourceData(resource, option: .complete(waitUntilFetchStatus: false)) @@ -172,7 +172,7 @@ public func fetchCachedResourceRepresentation(account: Account, resource: MediaR if !data.complete { return .complete() } - return fetchVideoStickerRepresentation(account: account, resource: resource, resourceData: data, representation: representation) + return fetchVideoStickerRepresentation(resource: resource, resourceData: data, representation: representation) } } else if let representation = representation as? CachedAnimatedStickerFirstFrameRepresentation { return account.postbox.mediaBox.resourceData(resource, option: .complete(waitUntilFetchStatus: false)) @@ -180,7 +180,7 @@ public func fetchCachedResourceRepresentation(account: Account, resource: MediaR if !data.complete { return .complete() } - return fetchAnimatedStickerFirstFrameRepresentation(account: account, resource: resource, resourceData: data, representation: representation) + return fetchAnimatedStickerFirstFrameRepresentation(resource: resource, resourceData: data, representation: representation) } } else if let resource = resource as? YoutubeEmbedStoryboardMediaResource, let _ = representation as? YoutubeEmbedStoryboardMediaResourceRepresentation { return fetchYoutubeEmbedStoryboardResource(resource: resource) @@ -210,7 +210,7 @@ private func videoFirstFrameData(account: Account, resource: MediaResource, chun |> mapToSignal { _ -> Signal in return account.postbox.mediaBox.resourceData(resource, option: .incremental(waitUntilFetchStatus: false), attemptSynchronously: false) |> mapToSignal { data -> Signal in - return fetchCachedVideoFirstFrameRepresentation(account: account, resource: resource, resourceData: data) + return fetchCachedVideoFirstFrameRepresentation(resource: resource, resourceData: data) |> `catch` { _ -> Signal in if chunkSize > size { return .complete() @@ -225,7 +225,7 @@ private func videoFirstFrameData(account: Account, resource: MediaResource, chun } } -private func fetchCachedStickerAJpegRepresentation(account: Account, resource: MediaResource, resourceData: MediaResourceData, representation: CachedStickerAJpegRepresentation) -> Signal { +private func fetchCachedStickerAJpegRepresentation(resource: MediaResource, resourceData: MediaResourceData, representation: CachedStickerAJpegRepresentation) -> Signal { return Signal({ subscriber in if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) { var image: UIImage? @@ -371,7 +371,7 @@ public enum FetchVideoFirstFrameError { case generic } -private func fetchCachedVideoFirstFrameRepresentation(account: Account, resource: MediaResource, resourceData: MediaResourceData) -> Signal { +private func fetchCachedVideoFirstFrameRepresentation(resource: MediaResource, resourceData: MediaResourceData) -> Signal { return Signal { subscriber in let tempFilePath = NSTemporaryDirectory() + "\(arc4random()).mov" do { @@ -499,38 +499,11 @@ public func fetchCachedSharedResourceRepresentation(accountManager: AccountManag } } -private func fetchCachedBlurredWallpaperRepresentation(account: Account, resource: MediaResource, resourceData: MediaResourceData, representation: CachedBlurredWallpaperRepresentation) -> Signal { - return Signal({ subscriber in - if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) { - if let image = UIImage(data: data) { - let path = NSTemporaryDirectory() + "\(Int64.random(in: Int64.min ... Int64.max))" - let url = URL(fileURLWithPath: path) - - if let colorImage = blurredImage(image, radius: 30.0), let colorDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) { - CGImageDestinationSetProperties(colorDestination, NSDictionary() as CFDictionary) - - let colorQuality: Float = 0.5 - - let options = NSMutableDictionary() - options.setObject(colorQuality as NSNumber, forKey: kCGImageDestinationLossyCompressionQuality as NSString) - - CGImageDestinationAddImage(colorDestination, colorImage.cgImage!, options as CFDictionary) - if CGImageDestinationFinalize(colorDestination) { - subscriber.putNext(.temporaryPath(path)) - subscriber.putCompletion() - } - } - } - } - return EmptyDisposable - }) |> runOn(Queue.concurrentDefaultQueue()) -} - public enum FetchAlbumArtworkError { case moreDataNeeded(Int) } -private func fetchCachedAlbumArtworkRepresentation(account: Account, resource: MediaResource, data: Data, representation: CachedAlbumArtworkRepresentation) -> Signal { +private func fetchCachedAlbumArtworkRepresentation(resource: MediaResource, data: Data, representation: CachedAlbumArtworkRepresentation) -> Signal { return Signal({ subscriber in let result = readAlbumArtworkData(data) switch result { @@ -573,7 +546,7 @@ private func fetchCachedAlbumArtworkRepresentation(account: Account, resource: M }) |> runOn(Queue.concurrentDefaultQueue()) } -private func fetchAnimatedStickerFirstFrameRepresentation(account: Account, resource: MediaResource, resourceData: MediaResourceData, representation: CachedAnimatedStickerFirstFrameRepresentation) -> Signal { +private func fetchAnimatedStickerFirstFrameRepresentation(resource: MediaResource, resourceData: MediaResourceData, representation: CachedAnimatedStickerFirstFrameRepresentation) -> Signal { return Signal({ subscriber in if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) { return fetchCompressedLottieFirstFrameAJpeg(data: data, size: CGSize(width: CGFloat(representation.width), height: CGFloat(representation.height)), fitzModifier: representation.fitzModifier, cacheKey: "\(resource.id.stringRepresentation)-\(representation.uniqueId)").start(next: { file in @@ -587,7 +560,7 @@ private func fetchAnimatedStickerFirstFrameRepresentation(account: Account, reso |> runOn(Queue.concurrentDefaultQueue()) } -private func fetchAnimatedStickerRepresentation(account: Account, resource: MediaResource, resourceData: MediaResourceData, representation: CachedAnimatedStickerRepresentation) -> Signal { +private func fetchAnimatedStickerRepresentation(resource: MediaResource, resourceData: MediaResourceData, representation: CachedAnimatedStickerRepresentation) -> Signal { return Signal({ subscriber in if let data = try? Data(contentsOf: URL(fileURLWithPath: resourceData.path), options: [.mappedIfSafe]) { return cacheAnimatedStickerFrames(data: data, size: CGSize(width: CGFloat(representation.width), height: CGFloat(representation.height)), fitzModifier: representation.fitzModifier, cacheKey: "\(resource.id.stringRepresentation)-\(representation.uniqueId)").start(next: { value in @@ -602,7 +575,7 @@ private func fetchAnimatedStickerRepresentation(account: Account, resource: Medi |> runOn(Queue.concurrentDefaultQueue()) } -private func fetchVideoStickerRepresentation(account: Account, resource: MediaResource, resourceData: MediaResourceData, representation: CachedVideoStickerRepresentation) -> Signal { +private func fetchVideoStickerRepresentation(resource: MediaResource, resourceData: MediaResourceData, representation: CachedVideoStickerRepresentation) -> Signal { return Signal({ subscriber in return cacheVideoStickerFrames(path: resourceData.path, size: CGSize(width: CGFloat(representation.width), height: CGFloat(representation.height)), cacheKey: "\(resource.id.stringRepresentation)-\(representation.uniqueId)").start(next: { value in subscriber.putNext(value) diff --git a/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift b/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift index 9faa2ba98a..bc2da20523 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift @@ -4,7 +4,6 @@ import Display import TelegramCore import SwiftSignalKit import AsyncDisplayKit -import Postbox import StickerResources import AccountContext import AnimatedStickerNode @@ -81,7 +80,7 @@ final class HorizontalStickerGridItemNode: GridItemNode { var stickerItem: StickerPackItem? { if let (_, item, _) = self.currentState { - return StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: 0), file: item.file, indexKeys: []) + return StickerPackItem(index: EngineItemCollectionItemIndex(index: 0, id: 0), file: item.file, indexKeys: []) } else { return nil } diff --git a/submodules/TelegramUI/Sources/NotificationContentContext.swift b/submodules/TelegramUI/Sources/NotificationContentContext.swift index 5fa8c6edf8..022b47055b 100644 --- a/submodules/TelegramUI/Sources/NotificationContentContext.swift +++ b/submodules/TelegramUI/Sources/NotificationContentContext.swift @@ -4,7 +4,6 @@ import UserNotificationsUI import Display import TelegramCore import SwiftSignalKit -import Postbox import TelegramPresentationData import TelegramUIPreferences import AccountContext @@ -87,7 +86,7 @@ public final class NotificationViewControllerImpl { let rootPath = rootPathForBasePath(self.initializationData.appGroupPath) performAppGroupUpgrades(appGroupPath: self.initializationData.appGroupPath, rootPath: rootPath) - TempBox.initializeShared(basePath: rootPath, processType: "notification-content", launchSpecificId: Int64.random(in: Int64.min ... Int64.max)) + EngineTempBox.initializeShared(basePath: rootPath, processType: "notification-content", launchSpecificId: Int64.random(in: Int64.min ... Int64.max)) let logsPath = rootPath + "/logs/notificationcontent-logs" let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil) @@ -140,7 +139,7 @@ public final class NotificationViewControllerImpl { return nil }) - sharedAccountContext = SharedAccountContextImpl(mainWindow: nil, sharedContainerPath: self.initializationData.appGroupPath, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, appLockContext: appLockContext, notificationController: nil, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, apiHash: self.initializationData.apiHash, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(self.initializationData.bundleData), externalRequestVerificationStream: .never(), externalRecaptchaRequestVerification: { _, _ in return .never() }, autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), deviceModelName: nil, useBetaFeatures: self.initializationData.useBetaFeatures, isICloudEnabled: false), hasInAppPurchases: false, rootPath: rootPath, legacyBasePath: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), firebaseSecretStream: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _, _ in }, appDelegate: nil) + sharedAccountContext = SharedAccountContextImpl(mainWindow: nil, sharedContainerPath: self.initializationData.appGroupPath, basePath: rootPath, encryptionParameters: EngineValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: EngineValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: EngineValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, appLockContext: appLockContext, notificationController: nil, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, apiHash: self.initializationData.apiHash, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(self.initializationData.bundleData), externalRequestVerificationStream: .never(), externalRecaptchaRequestVerification: { _, _ in return .never() }, autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), deviceModelName: nil, useBetaFeatures: self.initializationData.useBetaFeatures, isICloudEnabled: false), hasInAppPurchases: false, rootPath: rootPath, legacyBasePath: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), firebaseSecretStream: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _, _ in }, appDelegate: nil) presentationDataPromise.set(sharedAccountContext!.presentationData) } @@ -179,7 +178,7 @@ public final class NotificationViewControllerImpl { return } - let messageId = MessageId(peerId: PeerId(peerIdValue), namespace: messageIdNamespace, id: messageIdId) + let messageId = EngineMessage.Id(peerId: EnginePeer.Id(peerIdValue), namespace: messageIdNamespace, id: messageIdId) if let image = media as? TelegramMediaImage, let thumbnailRepresentation = imageRepresentationLargerThan(image.representations, size: PixelDimensions(width: 120, height: 120)), let largestRepresentation = largestImageRepresentation(image.representations) { let dimensions = largestRepresentation.dimensions diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerController.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerController.swift index ed034ebced..c7fef41747 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerController.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerController.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import TelegramCore -import Postbox import Display import SwiftSignalKit import TelegramUIPreferences @@ -15,7 +14,7 @@ final class OverlayAudioPlayerControllerImpl: ViewController, OverlayAudioPlayer private let context: AccountContext let chatLocation: ChatLocation let type: MediaManagerPlayerType - let initialMessageId: MessageId + let initialMessageId: EngineMessage.Id let initialOrder: MusicPlaybackSettingsOrder let playlistLocation: SharedMediaPlaylistLocation? @@ -33,7 +32,7 @@ final class OverlayAudioPlayerControllerImpl: ViewController, OverlayAudioPlayer context: AccountContext, chatLocation: ChatLocation, type: MediaManagerPlayerType, - initialMessageId: MessageId, + initialMessageId: EngineMessage.Id, initialOrder: MusicPlaybackSettingsOrder, playlistLocation: SharedMediaPlaylistLocation? = nil, parentNavigationController: NavigationController? @@ -189,7 +188,7 @@ final class OverlayAudioPlayerControllerImpl: ViewController, OverlayAudioPlayer attributes.append(.Audio(isVoice: false, duration: audioMetadata.duration, title: audioMetadata.title, performer: audioMetadata.performer, waveform: nil)) } - let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(item.fileSize), attributes: attributes, alternativeRepresentations: []) + let file = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(item.fileSize), attributes: attributes, alternativeRepresentations: []) let _ = (standaloneUploadedFile( postbox: self.context.account.postbox, diff --git a/submodules/TelegramUI/Sources/ThemeUpdateManager.swift b/submodules/TelegramUI/Sources/ThemeUpdateManager.swift index f6f3f81488..e7baecc1e7 100644 --- a/submodules/TelegramUI/Sources/ThemeUpdateManager.swift +++ b/submodules/TelegramUI/Sources/ThemeUpdateManager.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import TelegramCore import SwiftSignalKit import TelegramPresentationData @@ -138,7 +137,7 @@ final class ThemeUpdateManagerImpl: ThemeUpdateManager { theme = updatedTheme } - return PreferencesEntry(PresentationThemeSettings(theme: theme, themePreferredBaseTheme: current.themePreferredBaseTheme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion)) + return EnginePreferencesEntry(PresentationThemeSettings(theme: theme, themePreferredBaseTheme: current.themePreferredBaseTheme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion)) }) }).start() } diff --git a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift index 3e7f2c5484..5f2f06d4d7 100644 --- a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import TelegramCore import SwiftSignalKit @@ -58,7 +57,7 @@ public struct WallpaperPresentationOptions: OptionSet { public static let blur = WallpaperPresentationOptions(rawValue: 1 << 1) } -public struct PresentationLocalTheme: PostboxCoding, Equatable { +public struct PresentationLocalTheme: EnginePostboxCoding, Equatable { public let title: String public let resource: LocalFileMediaResource public let resolvedWallpaper: TelegramWallpaper? @@ -69,13 +68,13 @@ public struct PresentationLocalTheme: PostboxCoding, Equatable { self.resolvedWallpaper = resolvedWallpaper } - public init(decoder: PostboxDecoder) { + public init(decoder: EnginePostboxDecoder) { self.title = decoder.decodeStringForKey("title", orElse: "") self.resource = decoder.decodeObjectForKey("resource", decoder: { LocalFileMediaResource(decoder: $0) }) as! LocalFileMediaResource self.resolvedWallpaper = decoder.decode(TelegramWallpaperNativeCodable.self, forKey: "wallpaper")?.value } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeString(self.title, forKey: "title") encoder.encodeObject(self.resource, forKey: "resource") if let resolvedWallpaper = self.resolvedWallpaper { @@ -137,12 +136,12 @@ public struct PresentationCloudTheme: Codable, Equatable { } } -public enum PresentationThemeReference: PostboxCoding, Equatable { +public enum PresentationThemeReference: EnginePostboxCoding, Equatable { case builtin(PresentationBuiltinThemeReference) case local(PresentationLocalTheme) case cloud(PresentationCloudTheme) - public init(decoder: PostboxDecoder) { + public init(decoder: EnginePostboxDecoder) { switch decoder.decodeInt32ForKey("v", orElse: 0) { case 0: self = .builtin(PresentationBuiltinThemeReference(rawValue: decoder.decodeInt32ForKey("t", orElse: 0))!) @@ -166,7 +165,7 @@ public enum PresentationThemeReference: PostboxCoding, Equatable { } } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { switch self { case let .builtin(reference): encoder.encodeInt32(0, forKey: "v") @@ -369,8 +368,8 @@ public struct AutomaticThemeSwitchSetting: Codable, Equatable { self.force = try container.decodeIfPresent(Bool.self, forKey: "force") ?? false self.trigger = try container.decode(AutomaticThemeSwitchTrigger.self, forKey: "trigger") - if let themeData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: "theme_v2") { - self.theme = PresentationThemeReference(decoder: PostboxDecoder(buffer: MemoryBuffer(data: themeData.data))) + if let themeData = try container.decodeIfPresent(EngineAdaptedPostboxDecoder.RawObjectData.self, forKey: "theme_v2") { + self.theme = PresentationThemeReference(decoder: EnginePostboxDecoder(buffer: EngineMemoryBuffer(data: themeData.data))) } else { self.theme = .builtin(.night) } @@ -382,7 +381,7 @@ public struct AutomaticThemeSwitchSetting: Codable, Equatable { try container.encode(self.force, forKey: "force") try container.encode(self.trigger, forKey: "trigger") - let themeData = PostboxEncoder().encodeObjectToRawData(self.theme) + let themeData = EnginePostboxEncoder().encodeObjectToRawData(self.theme) try container.encode(themeData, forKey: "theme_v2") } } @@ -435,7 +434,7 @@ public enum PresentationThemeBaseColor: Int32, CaseIterable { } } -public struct PresentationThemeAccentColor: PostboxCoding, Equatable { +public struct PresentationThemeAccentColor: EnginePostboxCoding, Equatable { public static func == (lhs: PresentationThemeAccentColor, rhs: PresentationThemeAccentColor) -> Bool { return lhs.index == rhs.index && lhs.baseColor == rhs.baseColor && lhs.accentColor == rhs.accentColor && lhs.bubbleColors == rhs.bubbleColors } @@ -476,7 +475,7 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { self.themeIndex = themeIndex } - public init(decoder: PostboxDecoder) { + public init(decoder: EnginePostboxDecoder) { self.index = decoder.decodeInt32ForKey("i", orElse: -1) self.baseColor = PresentationThemeBaseColor(rawValue: decoder.decodeInt32ForKey("b", orElse: 0)) ?? .blue self.accentColor = decoder.decodeOptionalInt32ForKey("c").flatMap { UInt32(bitPattern: $0) } @@ -500,7 +499,7 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { self.themeIndex = decoder.decodeOptionalInt64ForKey("t") } - public func encode(_ encoder: PostboxEncoder) { + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeInt32(self.index, forKey: "i") encoder.encodeInt32(self.baseColor.rawValue, forKey: "b") if let value = self.accentColor { @@ -617,12 +616,12 @@ public struct PresentationThemeSettings: Codable { public var largeEmoji: Bool public var reduceMotion: Bool - private func wallpaperResources(_ wallpaper: TelegramWallpaper) -> [MediaResourceId] { + private func wallpaperResources(_ wallpaper: TelegramWallpaper) -> [EngineRawMediaResourceId] { switch wallpaper { case let .image(representations, _): return representations.map { $0.resource.id } case let .file(file): - var resources: [MediaResourceId] = [] + var resources: [EngineRawMediaResourceId] = [] resources.append(file.file.resource.id) resources.append(contentsOf: file.file.previewRepresentations.map { $0.resource.id }) return resources @@ -631,8 +630,8 @@ public struct PresentationThemeSettings: Codable { } } - public var relatedResources: [MediaResourceId] { - var resources: [MediaResourceId] = [] + public var relatedResources: [EngineRawMediaResourceId] { + var resources: [EngineRawMediaResourceId] = [] for (_, chatWallpaper) in self.themeSpecificChatWallpapers { resources.append(contentsOf: wallpaperResources(chatWallpaper)) } @@ -673,8 +672,8 @@ public struct PresentationThemeSettings: Codable { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: StringCodingKey.self) - if let themeData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: "t") { - self.theme = PresentationThemeReference(decoder: PostboxDecoder(buffer: MemoryBuffer(data: themeData.data))) + if let themeData = try container.decodeIfPresent(EngineAdaptedPostboxDecoder.RawObjectData.self, forKey: "t") { + self.theme = PresentationThemeReference(decoder: EnginePostboxDecoder(buffer: EngineMemoryBuffer(data: themeData.data))) } else { self.theme = .builtin(.dayClassic) } @@ -695,10 +694,10 @@ public struct PresentationThemeSettings: Codable { } self.themeSpecificChatWallpapers = mappedThemeSpecificChatWallpapers - let themeSpecificAccentColorsDict = try container.decode([DictionaryKey: AdaptedPostboxDecoder.RawObjectData].self, forKey: "themeSpecificAccentColors") + let themeSpecificAccentColorsDict = try container.decode([DictionaryKey: EngineAdaptedPostboxDecoder.RawObjectData].self, forKey: "themeSpecificAccentColors") var mappedThemeSpecificAccentColors: [Int64: PresentationThemeAccentColor] = [:] for (key, value) in themeSpecificAccentColorsDict { - let innerDecoder = PostboxDecoder(buffer: MemoryBuffer(data: value.data)) + let innerDecoder = EnginePostboxDecoder(buffer: EngineMemoryBuffer(data: value.data)) mappedThemeSpecificAccentColors[key.key] = PresentationThemeAccentColor(decoder: innerDecoder) } self.themeSpecificAccentColors = mappedThemeSpecificAccentColors @@ -719,7 +718,7 @@ public struct PresentationThemeSettings: Codable { public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: StringCodingKey.self) - try container.encode(PostboxEncoder().encodeObjectToRawData(self.theme), forKey: "t") + try container.encode(EnginePostboxEncoder().encodeObjectToRawData(self.theme), forKey: "t") var mappedThemePreferredBaseTheme: [Int64: Int64] = [:] for (key, value) in self.themePreferredBaseTheme { @@ -727,9 +726,9 @@ public struct PresentationThemeSettings: Codable { } try container.encode(mappedThemePreferredBaseTheme, forKey: "themePreferredBaseTheme") - var mappedThemeSpecificAccentColors: [DictionaryKey: AdaptedPostboxEncoder.RawObjectData] = [:] + var mappedThemeSpecificAccentColors: [DictionaryKey: EngineAdaptedPostboxEncoder.RawObjectData] = [:] for (key, value) in self.themeSpecificAccentColors { - mappedThemeSpecificAccentColors[DictionaryKey(key)] = PostboxEncoder().encodeObjectToRawData(value) + mappedThemeSpecificAccentColors[DictionaryKey(key)] = EnginePostboxEncoder().encodeObjectToRawData(value) } try container.encode(mappedThemeSpecificAccentColors, forKey: "themeSpecificAccentColors") @@ -802,7 +801,7 @@ public func updatePresentationThemeSettingsInteractively(accountManager: Account } else { currentSettings = PresentationThemeSettings.defaultSettings } - return PreferencesEntry(f(currentSettings)) + return EnginePreferencesEntry(f(currentSettings)) }) } } diff --git a/submodules/TelegramUniversalVideoContent/Sources/YoutubeEmbedImplementation.swift b/submodules/TelegramUniversalVideoContent/Sources/YoutubeEmbedImplementation.swift index 753ea23172..452764e542 100644 --- a/submodules/TelegramUniversalVideoContent/Sources/YoutubeEmbedImplementation.swift +++ b/submodules/TelegramUniversalVideoContent/Sources/YoutubeEmbedImplementation.swift @@ -1,6 +1,5 @@ import Foundation import Display -import Postbox import TelegramCore import AccountContext import WebKit @@ -417,23 +416,23 @@ public class YoutubeEmbedStoryboardMediaResource: TelegramMediaResource { self.url = url } - public required init(decoder: PostboxDecoder) { + public required init(decoder: EnginePostboxDecoder) { self.videoId = decoder.decodeStringForKey("v", orElse: "") self.storyboardId = decoder.decodeInt32ForKey("i", orElse: 0) self.url = decoder.decodeStringForKey("u", orElse: "") } - - public func encode(_ encoder: PostboxEncoder) { + + public func encode(_ encoder: EnginePostboxEncoder) { encoder.encodeString(self.videoId, forKey: "v") encoder.encodeInt32(self.storyboardId, forKey: "i") encoder.encodeString(self.url, forKey: "u") } - - public var id: MediaResourceId { - return MediaResourceId(YoutubeEmbedStoryboardMediaResourceId(videoId: self.videoId, storyboardId: self.storyboardId).uniqueId) + + public var id: EngineRawMediaResourceId { + return EngineRawMediaResourceId(YoutubeEmbedStoryboardMediaResourceId(videoId: self.videoId, storyboardId: self.storyboardId).uniqueId) } - - public func isEqual(to: MediaResource) -> Bool { + + public func isEqual(to: EngineRawMediaResource) -> Bool { if let to = to as? YoutubeEmbedStoryboardMediaResource { return self.videoId == to.videoId && self.storyboardId == to.storyboardId && self.url == to.url } else { @@ -442,17 +441,17 @@ public class YoutubeEmbedStoryboardMediaResource: TelegramMediaResource { } } -public final class YoutubeEmbedStoryboardMediaResourceRepresentation: CachedMediaResourceRepresentation { - public let keepDuration: CachedMediaRepresentationKeepDuration = .shortLived - +public final class YoutubeEmbedStoryboardMediaResourceRepresentation: EngineRawCachedMediaResourceRepresentation { + public let keepDuration: EngineCachedMediaRepresentationKeepDuration = .shortLived + public var uniqueId: String { return "cached" } - + public init() { } - - public func isEqual(to: CachedMediaResourceRepresentation) -> Bool { + + public func isEqual(to: EngineRawCachedMediaResourceRepresentation) -> Bool { if to is YoutubeEmbedStoryboardMediaResourceRepresentation { return true } else { @@ -461,14 +460,14 @@ public final class YoutubeEmbedStoryboardMediaResourceRepresentation: CachedMedi } } -public func fetchYoutubeEmbedStoryboardResource(resource: YoutubeEmbedStoryboardMediaResource) -> Signal { +public func fetchYoutubeEmbedStoryboardResource(resource: YoutubeEmbedStoryboardMediaResource) -> Signal { return Signal { subscriber in subscriber.putNext(.reset) let disposable = MetaDisposable() disposable.set(fetchHttpResource(url: resource.url).start(next: { next in if case let .dataPart(_, data, _, complete) = next, complete { - let tempFile = TempBox.shared.tempFile(fileName: "image.jpg") + let tempFile = EngineTempBox.shared.tempFile(fileName: "image.jpg") if let _ = try? data.write(to: URL(fileURLWithPath: tempFile.path), options: .atomic) { subscriber.putNext(.tempFile(tempFile)) subscriber.putCompletion() diff --git a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift index 29234377d7..c84cd84767 100644 --- a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift +++ b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import TelegramCore import Display import libprisma @@ -127,7 +126,7 @@ private func generateMessageSyntaxHighlight(spec: CachedMessageSyntaxHighlight.S return MessageSyntaxHighlight(entities: entities) } -public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], strings: PresentationStrings? = nil, dateTimeFormat: PresentationDateTimeFormat? = nil, baseColor: UIColor, linkColor: UIColor, baseQuoteTintColor: UIColor? = nil, baseQuoteSecondaryTintColor: UIColor? = nil, baseQuoteTertiaryTintColor: UIColor? = nil, codeBlockTitleColor: UIColor? = nil, codeBlockAccentColor: UIColor? = nil, codeBlockBackgroundColor: UIColor? = nil, baseFont: UIFont, linkFont: UIFont, boldFont: UIFont, italicFont: UIFont, boldItalicFont: UIFont, fixedFont: UIFont, blockQuoteFont: UIFont, underlineLinks: Bool = true, external: Bool = false, message: Message?, entityFiles: [MediaId: TelegramMediaFile] = [:], adjustQuoteFontSize: Bool = false, cachedMessageSyntaxHighlight: CachedMessageSyntaxHighlight? = nil, paragraphAlignment: NSTextAlignment? = nil) -> NSAttributedString { +public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], strings: PresentationStrings? = nil, dateTimeFormat: PresentationDateTimeFormat? = nil, baseColor: UIColor, linkColor: UIColor, baseQuoteTintColor: UIColor? = nil, baseQuoteSecondaryTintColor: UIColor? = nil, baseQuoteTertiaryTintColor: UIColor? = nil, codeBlockTitleColor: UIColor? = nil, codeBlockAccentColor: UIColor? = nil, codeBlockBackgroundColor: UIColor? = nil, baseFont: UIFont, linkFont: UIFont, boldFont: UIFont, italicFont: UIFont, boldItalicFont: UIFont, fixedFont: UIFont, blockQuoteFont: UIFont, underlineLinks: Bool = true, external: Bool = false, message: EngineRawMessage?, entityFiles: [EngineMedia.Id: TelegramMediaFile] = [:], adjustQuoteFontSize: Bool = false, cachedMessageSyntaxHighlight: CachedMessageSyntaxHighlight? = nil, paragraphAlignment: NSTextAlignment? = nil) -> NSAttributedString { let baseQuoteTintColor = baseQuoteTintColor ?? baseColor var nsString: NSString? @@ -380,7 +379,7 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti addFontAttributes(range, .smaller) } case let .CustomEmoji(_, fileId): - let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId) + let mediaId = EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: fileId) var emojiFile: TelegramMediaFile? if let file = message?.associatedMedia[mediaId] as? TelegramMediaFile { emojiFile = file @@ -662,7 +661,7 @@ public func asyncUpdateMessageSyntaxHighlight(engine: TelegramEngine, messageId: } } - if let entry = CodableEntry(CachedMessageSyntaxHighlight(values: updated)) { + if let entry = EngineCodableEntry(CachedMessageSyntaxHighlight(values: updated)) { return engine.messages.storeLocallyDerivedData(messageId: messageId, data: ["code": entry]).start(completed: { subscriber.putCompletion() }) diff --git a/submodules/TonBinding/BUILD b/submodules/TonBinding/BUILD deleted file mode 100644 index e32788b00b..0000000000 --- a/submodules/TonBinding/BUILD +++ /dev/null @@ -1,26 +0,0 @@ -objc_library( - name = "TonBinding", - module_name = "TonBinding", - enable_modules = True, - srcs = glob([ - "Sources/**/*.m", - "Sources/**/*.mm", - ]), - hdrs = glob([ - "Sources/**/*.h", - ]), - copts = [ - "-std=c++14", - ], - includes = [ - "Sources", - ], - deps = [ - "//submodules/SSignalKit/SSignalKit:SSignalKit", - "//third-party/boringssl:crypto", - "//submodules/ton:ton", - ], - visibility = [ - "//visibility:public", - ], -) diff --git a/submodules/TonBinding/Sources/TON.h b/submodules/TonBinding/Sources/TON.h deleted file mode 100644 index 31c0dc812f..0000000000 --- a/submodules/TonBinding/Sources/TON.h +++ /dev/null @@ -1,190 +0,0 @@ -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface TONError : NSObject - -@property (nonatomic, strong, readonly) NSString *text; - -@end - -@interface TONKey : NSObject - -@property (nonatomic, strong, readonly) NSString *publicKey; -@property (nonatomic, strong, readonly) NSData *secret; - -- (instancetype)initWithPublicKey:(NSString *)publicKey secret:(NSData *)secret; - -@end - -@interface TONTransactionId : NSObject - -@property (nonatomic, readonly) int64_t lt; -@property (nonatomic, strong, readonly) NSData * _Nonnull transactionHash; - -- (instancetype)initWithLt:(int64_t)lt transactionHash:(NSData * _Nonnull)transactionHash; - -@end - -@interface TONAccountState : NSObject - -@property (nonatomic, readonly) bool isInitialized; -@property (nonatomic, readonly) bool isRWallet; -@property (nonatomic, readonly) int64_t balance; -@property (nonatomic, readonly) int64_t unlockedBalance; - -@property (nonatomic, readonly) int32_t seqno; -@property (nonatomic, strong, readonly) TONTransactionId * _Nullable lastTransactionId; -@property (nonatomic, readonly) int64_t syncUtime; - -- (instancetype)initWithIsInitialized:(bool)isInitialized isRWallet:(bool)isRWallet balance:(int64_t)balance unlockedBalance:(int64_t)unlockedBalance seqno:(int32_t)seqno lastTransactionId:(TONTransactionId * _Nullable)lastTransactionId syncUtime:(int64_t)syncUtime; - -@end - -@protocol TONTransactionMessageContents - -@end - -@interface TONTransactionMessageContentsRawData : NSObject - -@property (nonatomic, strong, readonly) NSData * _Nonnull data; - -- (instancetype)initWithData:(NSData * _Nonnull)data; - -@end - -@interface TONTransactionMessageContentsPlainText : NSObject - -@property (nonatomic, strong, readonly) NSString * _Nonnull text; - -- (instancetype)initWithText:(NSString * _Nonnull)text; - -@end - -@interface TONEncryptedData : NSObject - -@property (nonatomic, strong, readonly) NSString * _Nonnull sourceAddress; -@property (nonatomic, strong, readonly) NSData * _Nonnull data; - -- (instancetype)initWithSourceAddress:(NSString * _Nonnull)sourceAddress data:(NSData * _Nonnull)data; - -@end - -@interface TONTransactionMessageContentsEncryptedText : NSObject - -@property (nonatomic, strong, readonly) TONEncryptedData * _Nonnull encryptedData; - -- (instancetype)initWithEncryptedData:(TONEncryptedData * _Nonnull)encryptedData; - -@end - -@interface TONTransactionMessage : NSObject - -@property (nonatomic, readonly) int64_t value; -@property (nonatomic, strong, readonly) NSString * _Nonnull source; -@property (nonatomic, strong, readonly) NSString * _Nonnull destination; -@property (nonatomic, strong, readonly) id _Nonnull contents; -@property (nonatomic, strong, readonly) NSData * _Nonnull bodyHash; - -- (instancetype)initWithValue:(int64_t)value source:(NSString * _Nonnull)source destination:(NSString * _Nonnull)destination contents:(id _Nonnull)contents bodyHash:(NSData * _Nonnull)bodyHash; - -@end - -@interface TONTransaction : NSObject - -@property (nonatomic, strong, readonly) NSData * _Nonnull data; -@property (nonatomic, strong, readonly) TONTransactionId * _Nonnull transactionId; -@property (nonatomic, readonly) int64_t timestamp; -@property (nonatomic, readonly) int64_t storageFee; -@property (nonatomic, readonly) int64_t otherFee; -@property (nonatomic, strong, readonly) TONTransactionMessage * _Nullable inMessage; -@property (nonatomic, strong, readonly) NSArray * _Nonnull outMessages; - -- (instancetype)initWithData:(NSData * _Nonnull)data transactionId:(TONTransactionId * _Nonnull)transactionId timestamp:(int64_t)timestamp storageFee:(int64_t)storageFee otherFee:(int64_t)otherFee inMessage:(TONTransactionMessage * _Nullable)inMessage outMessages:(NSArray * _Nonnull)outMessages; - -@end - -@interface TONExternalRequest : NSObject - -@property (nonatomic, strong, readonly) NSData * _Nonnull data; -@property (nonatomic, copy, readonly) void (^onResult)(NSData * _Nullable, NSString * _Nullable); - -- (instancetype)initWithData:(NSData * _Nonnull)data onResult:(void (^)(NSData * _Nullable, NSString * _Nullable))onResult; - -@end - -@interface TONFees : NSObject - -@property (nonatomic, readonly) int64_t inFwdFee; -@property (nonatomic, readonly) int64_t storageFee; -@property (nonatomic, readonly) int64_t gasFee; -@property (nonatomic, readonly) int64_t fwdFee; - -- (instancetype)initWithInFwdFee:(int64_t)inFwdFee storageFee:(int64_t)storageFee gasFee:(int64_t)gasFee fwdFee:(int64_t)fwdFee; - -@end - -@interface TONSendGramsQueryFees : NSObject - -@property (nonatomic, strong, readonly) TONFees * _Nonnull sourceFees; -@property (nonatomic, strong, readonly) NSArray * _Nonnull destinationFees; - -- (instancetype)initWithSourceFees:(TONFees * _Nonnull)sourceFees destinationFees:(NSArray * _Nonnull)destinationFees; - -@end - -@interface TONPreparedSendGramsQuery : NSObject - -@property (nonatomic, readonly) int64_t queryId; -@property (nonatomic, readonly) int64_t validUntil; -@property (nonatomic, strong, readonly) NSData * _Nonnull bodyHash; - -- (instancetype)initWithQueryId:(int64_t)queryId validUntil:(int64_t)validUntil bodyHash:(NSData *)bodyHash; - -@end - -@interface TONSendGramsResult : NSObject - -@property (nonatomic, readonly) int64_t sentUntil; -@property (nonatomic, strong, readonly) NSData * _Nonnull bodyHash; - -- (instancetype)initWithSentUntil:(int64_t)sentUntil bodyHash:(NSData *)bodyHash; - -@end - -@interface TONValidatedConfig : NSObject - -@property (nonatomic, readonly) int64_t defaultWalletId; - -- (instancetype)initWithDefaultWalletId:(int64_t)defaultWalletId; - -@end - -@interface TON : NSObject - -- (instancetype)initWithKeystoreDirectory:(NSString *)keystoreDirectory config:(NSString *)config blockchainName:(NSString *)blockchainName performExternalRequest:(void (^)(TONExternalRequest * _Nonnull))performExternalRequest enableExternalRequests:(bool)enableExternalRequests syncStateUpdated:(void (^)(float))syncStateUpdated; - -- (SSignal *)updateConfig:(NSString *)config blockchainName:(NSString *)blockchainName; -- (SSignal *)validateConfig:(NSString *)config blockchainName:(NSString *)blockchainName; - -- (SSignal *)createKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword; -- (SSignal *)getWalletAccountAddressWithPublicKey:(NSString *)publicKey initialWalletId:(int64_t)initialWalletId rwalletInitialPublicKey:(NSString * _Nullable)rwalletInitialPublicKey; -- (SSignal *)getAccountStateWithAddress:(NSString *)accountAddress; -- (SSignal *)generateSendGramsQueryFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount comment:(NSData *)comment encryptComment:(bool)encryptComment forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout randomId:(int64_t)randomId; -- (SSignal *)generateFakeSendGramsQueryFromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount comment:(NSData *)comment encryptComment:(bool)encryptComment forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout; -- (SSignal *)estimateSendGramsQueryFees:(TONPreparedSendGramsQuery *)preparedQuery; -- (SSignal *)commitPreparedSendGramsQuery:(TONPreparedSendGramsQuery *)preparedQuery; -- (SSignal *)exportKey:(TONKey *)key localPassword:(NSData *)localPassword; -- (SSignal *)importKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword wordList:(NSArray *)wordList; -- (SSignal *)deleteKey:(TONKey *)key; -- (SSignal *)deleteAllKeys; -- (SSignal *)getTransactionListWithAddress:(NSString * _Nonnull)address lt:(int64_t)lt hash:(NSData * _Nonnull)hash; -- (SSignal *)decryptMessagesWithKey:(TONKey * _Nonnull)key localPassword:(NSData * _Nonnull)localPassword messages:(NSArray * _Nonnull)messages; - -- (NSData *)encrypt:(NSData *)decryptedData secret:(NSData *)data; -- (NSData * __nullable)decrypt:(NSData *)encryptedData secret:(NSData *)data; - -@end - -NS_ASSUME_NONNULL_END diff --git a/submodules/TonBinding/Sources/TON.mm b/submodules/TonBinding/Sources/TON.mm deleted file mode 100644 index 1ff7dc656d..0000000000 --- a/submodules/TonBinding/Sources/TON.mm +++ /dev/null @@ -1,1227 +0,0 @@ -#import "TON.h" - -#import "tonlib/Client.h" - -static td::SecureString makeSecureString(NSData * _Nonnull data) { - if (data == nil || data.length == 0) { - return td::SecureString(); - } else { - return td::SecureString((const char *)data.bytes, (size_t)data.length); - } -} - -static std::string makeString(NSData * _Nonnull data) { - if (data == nil || data.length == 0) { - return std::string(); - } else { - return std::string((const char *)data.bytes, ((const char *)data.bytes) + data.length); - } -} - -static NSData * _Nonnull makeData(std::string &string) { - if (string.size() == 0) { - return [NSData data]; - } else { - return [[NSData alloc] initWithBytes:string.data() length:string.size()]; - } -} - -static NSString * _Nullable readString(std::string &string) { - if (string.size() == 0) { - return @""; - } else { - return [[NSString alloc] initWithBytes:string.data() length:string.size() encoding:NSUTF8StringEncoding]; - } -} - -static NSData * _Nullable readSecureString(td::SecureString &string) { - if (string.size() == 0) { - return [NSData data]; - } else { - return [[NSData alloc] initWithBytes:string.data() length:string.size()]; - } -} - -static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::object_ptr &message) { - if (message == nullptr) { - return nil; - } - NSString *source = readString(message->source_->account_address_); - NSString *destination = readString(message->destination_->account_address_); - - id contents = nil; - if (message->msg_data_->get_id() == tonlib_api::msg_dataRaw::ID) { - auto msgData = tonlib_api::move_object_as(message->msg_data_); - contents = [[TONTransactionMessageContentsRawData alloc] initWithData:makeData(msgData->body_)]; - } else if (message->msg_data_->get_id() == tonlib_api::msg_dataText::ID) { - auto msgData = tonlib_api::move_object_as(message->msg_data_); - NSString *text = readString(msgData->text_); - if (text == nil) { - contents = [[TONTransactionMessageContentsPlainText alloc] initWithText:@""]; - } else { - contents = [[TONTransactionMessageContentsPlainText alloc] initWithText:text]; - } - } else if (message->msg_data_->get_id() == tonlib_api::msg_dataDecryptedText::ID) { - auto msgData = tonlib_api::move_object_as(message->msg_data_); - NSString *text = readString(msgData->text_); - if (text == nil) { - contents = [[TONTransactionMessageContentsPlainText alloc] initWithText:@""]; - } else { - contents = [[TONTransactionMessageContentsPlainText alloc] initWithText:text]; - } - } else if (message->msg_data_->get_id() == tonlib_api::msg_dataEncryptedText::ID) { - auto msgData = tonlib_api::move_object_as(message->msg_data_); - TONEncryptedData *encryptedData = [[TONEncryptedData alloc] initWithSourceAddress:source data:makeData(msgData->text_)]; - contents = [[TONTransactionMessageContentsEncryptedText alloc] initWithEncryptedData:encryptedData]; - } else { - contents = [[TONTransactionMessageContentsRawData alloc] initWithData:[NSData data]]; - } - - if (source == nil || destination == nil) { - return nil; - } - return [[TONTransactionMessage alloc] initWithValue:message->value_ source:source destination:destination contents:contents bodyHash:makeData(message->body_hash_)]; -} - -@implementation TONKey - -- (instancetype)initWithPublicKey:(NSString *)publicKey secret:(NSData *)secret { - self = [super init]; - if (self != nil) { - _publicKey = publicKey; - _secret = secret; - } - return self; -} - -@end - -@implementation TONAccountState - -- (instancetype)initWithIsInitialized:(bool)isInitialized isRWallet:(bool)isRWallet balance:(int64_t)balance unlockedBalance:(int64_t)unlockedBalance seqno:(int32_t)seqno lastTransactionId:(TONTransactionId * _Nullable)lastTransactionId syncUtime:(int64_t)syncUtime { - self = [super init]; - if (self != nil) { - _isInitialized = isInitialized; - _isRWallet = isRWallet; - _balance = balance; - _unlockedBalance = unlockedBalance; - _seqno = seqno; - _lastTransactionId = lastTransactionId; - _syncUtime = syncUtime; - } - return self; -} - -@end - -@implementation TONTransactionId - -- (instancetype)initWithLt:(int64_t)lt transactionHash:(NSData *)transactionHash { - self = [super init]; - if (self != nil) { - _lt = lt; - _transactionHash = transactionHash; - } - return self; -} - -@end - -@implementation TONTransactionMessageContentsRawData - -- (instancetype)initWithData:(NSData * _Nonnull)data { - self = [super init]; - if (self != nil) { - _data = data; - } - return self; -} - -@end - -@implementation TONTransactionMessageContentsPlainText - -- (instancetype)initWithText:(NSString * _Nonnull)text { - self = [super init]; - if (self != nil) { - _text = text; - } - return self; -} - -@end - -@implementation TONTransactionMessageContentsEncryptedText - -- (instancetype)initWithEncryptedData:(TONEncryptedData * _Nonnull)encryptedData { - self = [super init]; - if (self != nil) { - _encryptedData = encryptedData; - } - return self; -} - -@end - -@implementation TONTransactionMessage - -- (instancetype)initWithValue:(int64_t)value source:(NSString * _Nonnull)source destination:(NSString * _Nonnull)destination contents:(id _Nonnull)contents bodyHash:(NSData * _Nonnull)bodyHash { - self = [super init]; - if (self != nil) { - _value = value; - _source = source; - _destination = destination; - _contents = contents; - _bodyHash = bodyHash; - } - return self; -} - -@end - -@implementation TONTransaction - -- (instancetype)initWithData:(NSData * _Nonnull)data transactionId:(TONTransactionId * _Nonnull)transactionId timestamp:(int64_t)timestamp storageFee:(int64_t)storageFee otherFee:(int64_t)otherFee inMessage:(TONTransactionMessage * _Nullable)inMessage outMessages:(NSArray * _Nonnull)outMessages { - self = [super init]; - if (self != nil) { - _data = data; - _transactionId = transactionId; - _timestamp = timestamp; - _storageFee = storageFee; - _otherFee = otherFee; - _inMessage = inMessage; - _outMessages = outMessages; - } - return self; -} - -@end - -@implementation TONExternalRequest - -- (instancetype)initWithData:(NSData * _Nonnull)data onResult:(void (^)(NSData * _Nullable, NSString * _Nullable))onResult { - self = [super init]; - if (self != nil) { - _data = data; - _onResult = [onResult copy]; - } - return self; -} - -@end - -@implementation TONFees - -- (instancetype)initWithInFwdFee:(int64_t)inFwdFee storageFee:(int64_t)storageFee gasFee:(int64_t)gasFee fwdFee:(int64_t)fwdFee { - self = [super init]; - if (self != nil) { - _inFwdFee = inFwdFee; - _storageFee = storageFee; - _gasFee = gasFee; - _fwdFee = fwdFee; - } - return self; -} - -@end - -@implementation TONSendGramsQueryFees - -- (instancetype)initWithSourceFees:(TONFees * _Nonnull)sourceFees destinationFees:(NSArray * _Nonnull)destinationFees { - self = [super init]; - if (self != nil) { - _sourceFees = sourceFees; - _destinationFees = destinationFees; - } - return self; -} - -@end - -@implementation TONPreparedSendGramsQuery - -- (instancetype)initWithQueryId:(int64_t)queryId validUntil:(int64_t)validUntil bodyHash:(NSData *)bodyHash { - self = [super init]; - if (self != nil) { - _queryId = queryId; - _validUntil = validUntil; - _bodyHash = bodyHash; - } - return self; -} - -@end - -@implementation TONSendGramsResult - -- (instancetype)initWithSentUntil:(int64_t)sentUntil bodyHash:(NSData *)bodyHash { - self = [super init]; - if (self != nil) { - _sentUntil = sentUntil; - _bodyHash = bodyHash; - } - return self; -} - -@end - -@implementation TONValidatedConfig - -- (instancetype)initWithDefaultWalletId:(int64_t)defaultWalletId { - self = [super init]; - if (self != nil) { - _defaultWalletId = defaultWalletId; - } - return self; -} - -@end - -@implementation TONEncryptedData - -- (instancetype)initWithSourceAddress:(NSString * _Nonnull)sourceAddress data:(NSData * _Nonnull)data { - self = [super init]; - if (self != nil) { - _sourceAddress = sourceAddress; - _data = data; - } - return self; -} - -@end - -using tonlib_api::make_object; - -@interface TONReceiveThreadParams : NSObject - -@property (nonatomic, readonly) std::shared_ptr client; -@property (nonatomic, copy, readonly) void (^received)(tonlib::Client::Response &); - -@end - -@implementation TONReceiveThreadParams - -- (instancetype)initWithClient:(std::shared_ptr)client received:(void (^)(tonlib::Client::Response &))received { - self = [super init]; - if (self != nil) { - _client = client; - _received = [received copy]; - } - return self; -} - -@end - -@interface TONRequestHandler : NSObject - -@property (nonatomic, copy, readonly) void (^completion)(tonlib_api::object_ptr &); - -@end - -@implementation TONRequestHandler - -- (instancetype)initWithCompletion:(void (^)(tonlib_api::object_ptr &))completion { - self = [super init]; - if (self != nil) { - _completion = [completion copy]; - } - return self; -} - -@end - -@implementation TONError - -- (instancetype)initWithText:(NSString *)text { - self = [super init]; - if (self != nil) { - _text = text; - } - return self; -} - -@end - -typedef enum { - TONInitializationStatusInitializing, - TONInitializationStatusReady, - TONInitializationStatusError -} TONInitializationStatus; - -@interface TON () { - std::shared_ptr _client; - uint64_t _nextRequestId; - NSLock *_requestHandlersLock; - NSMutableDictionary *_requestHandlers; - SPipe *_initializedStatus; - NSMutableSet *_sendGramRandomIds; - SQueue *_queue; - bool _enableExternalRequests; -} - -@end - -@implementation TON - -+ (void)receiveThread:(TONReceiveThreadParams *)params { - while (true) { - auto response = params.client->receive(1000); - if (response.object) { - params.received(response); - } - } -} - -- (instancetype)initWithKeystoreDirectory:(NSString *)keystoreDirectory config:(NSString *)config blockchainName:(NSString *)blockchainName performExternalRequest:(void (^)(TONExternalRequest * _Nonnull))performExternalRequest enableExternalRequests:(bool)enableExternalRequests syncStateUpdated:(void (^)(float))syncStateUpdated { - self = [super init]; - if (self != nil) { - _queue = [SQueue mainQueue]; - _requestHandlersLock = [[NSLock alloc] init]; - _requestHandlers = [[NSMutableDictionary alloc] init]; - _initializedStatus = [[SPipe alloc] initWithReplay:true]; - _initializedStatus.sink(@(TONInitializationStatusInitializing)); - _nextRequestId = 1; - _sendGramRandomIds = [[NSMutableSet alloc] init]; - _enableExternalRequests = enableExternalRequests; - - _client = std::make_shared(); - - [self setupLogging]; - - std::weak_ptr weakClient = _client; - - NSLock *requestHandlersLock = _requestHandlersLock; - NSMutableDictionary *requestHandlers = _requestHandlers; - NSThread *thread = [[NSThread alloc] initWithTarget:[self class] selector:@selector(receiveThread:) object:[[TONReceiveThreadParams alloc] initWithClient:_client received:^(tonlib::Client::Response &response) { - if (response.object->get_id() == tonlib_api::updateSendLiteServerQuery::ID) { - auto result = tonlib_api::move_object_as(response.object); - int64_t requestId = result->id_; - NSData *data = makeData(result->data_); - if (performExternalRequest) { - performExternalRequest([[TONExternalRequest alloc] initWithData:data onResult:^(NSData * _Nullable result, NSString * _Nullable error) { - auto strongClient = weakClient.lock(); - if (strongClient != nullptr) { - if (result != nil) { - auto query = make_object( - requestId, - makeString(result) - ); - strongClient->send({ 1, std::move(query) }); - } else if (error != nil) { - auto query = make_object( - requestId, - make_object( - 400, - error.UTF8String - ) - ); - strongClient->send({ 1, std::move(query) }); - } - } - }]); - } - return; - } else if (response.object->get_id() == tonlib_api::updateSyncState::ID) { - auto result = tonlib_api::move_object_as(response.object); - if (result->sync_state_->get_id() == tonlib_api::syncStateInProgress::ID) { - auto syncStateInProgress = tonlib_api::move_object_as(result->sync_state_); - int32_t currentDelta = syncStateInProgress->current_seqno_ - syncStateInProgress->from_seqno_; - int32_t fullDelta = syncStateInProgress->to_seqno_ - syncStateInProgress->from_seqno_; - if (currentDelta > 0 && fullDelta > 0) { - float progress = ((float)currentDelta) / ((float)fullDelta); - syncStateUpdated(progress); - } else { - syncStateUpdated(0.0f); - } - } else if (result->sync_state_->get_id() == tonlib_api::syncStateDone::ID) { - syncStateUpdated(1.0f); - } - return; - } - NSNumber *requestId = @(response.id); - [requestHandlersLock lock]; - TONRequestHandler *handler = requestHandlers[requestId]; - [requestHandlers removeObjectForKey:requestId]; - [requestHandlersLock unlock]; - if (handler != nil) { - handler.completion(response.object); - } - }]]; - [thread start]; - - [[NSFileManager defaultManager] createDirectoryAtPath:keystoreDirectory withIntermediateDirectories:true attributes:nil error:nil]; - - SPipe *initializedStatus = _initializedStatus; - [[self requestInitWithConfigString:config blockchainName:blockchainName keystoreDirectory:keystoreDirectory enableExternalRequests:enableExternalRequests] startWithNext:nil error:^(id error) { - NSString *errorText = @"Unknown error"; - if ([error isKindOfClass:[TONError class]]) { - errorText = ((TONError *)error).text; - } - initializedStatus.sink(@(TONInitializationStatusError)); - } completed:^{ - initializedStatus.sink(@(TONInitializationStatusReady)); - }]; - } - return self; -} - -- (void)setupLogging { -#if DEBUG - auto query = make_object( - make_object() - ); - _client->execute({ INT16_MAX + 1, std::move(query) }); -#else - auto query = make_object( - make_object() - ); - _client->execute({ INT16_MAX + 1, std::move(query) }); -#endif -} - -- (NSData * __nullable)decrypt:(NSData *)encryptedData secret:(NSData *)data { - auto query = make_object(makeSecureString(encryptedData), makeSecureString(data)); - tonlib_api::object_ptr result = _client->execute({ INT16_MAX + 1, std::move(query) }).object; - - if (result->get_id() == tonlib_api::error::ID) { - return nil; - } else { - tonlib_api::object_ptr value = tonlib_api::move_object_as(result); - return readSecureString(value->bytes_); - } -} -- (NSData *)encrypt:(NSData *)decryptedData secret:(NSData *)data { - auto query = make_object(makeSecureString(decryptedData), makeSecureString(data)); - tonlib_api::object_ptr result = _client->execute({ INT16_MAX + 1, std::move(query) }).object; - - tonlib_api::object_ptr value = tonlib_api::move_object_as(result); - - return readSecureString(value->bytes_); -} - -- (SSignal *)requestInitWithConfigString:(NSString *)configString blockchainName:(NSString *)blockchainName keystoreDirectory:(NSString *)keystoreDirectory enableExternalRequests:(bool)enableExternalRequests { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else { - [subscriber putCompletion]; - } - }]; - - bool ignoreCache = false; - #if DEBUG - ignoreCache = true; - #endif - - auto query = make_object(make_object( - make_object( - configString.UTF8String, - blockchainName.UTF8String, - enableExternalRequests, - ignoreCache - ), - make_object( - keystoreDirectory.UTF8String - ) - )); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)updateConfig:(NSString *)config blockchainName:(NSString *)blockchainName { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else { - [subscriber putCompletion]; - } - }]; - - auto query = make_object( - make_object( - config.UTF8String, - blockchainName.UTF8String, - _enableExternalRequests, - false - ) - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)validateConfig:(NSString *)config blockchainName:(NSString *)blockchainName { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::options_configInfo::ID) { - auto result = tonlib_api::move_object_as(object); - [subscriber putNext:[[TONValidatedConfig alloc] initWithDefaultWalletId:result->default_wallet_id_]]; - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - - auto query = make_object( - make_object( - config.UTF8String, - blockchainName.UTF8String, - _enableExternalRequests, - false - ) - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)createKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::key::ID) { - auto result = tonlib_api::move_object_as(object); - NSString *publicKey = [[NSString alloc] initWithData:[[NSData alloc] initWithBytes:result->public_key_.data() length:result->public_key_.length()] encoding:NSUTF8StringEncoding]; - if (publicKey == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error decoding UTF8 string in createKeyWithLocalPassword"]]; - return; - } - NSData *secret = [[NSData alloc] initWithBytes:result->secret_.data() length:result->secret_.length()]; - [subscriber putNext:[[TONKey alloc] initWithPublicKey:publicKey secret:secret]]; - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - - auto query = make_object( - makeSecureString(localPassword), - makeSecureString(mnemonicPassword), - td::SecureString() - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)getWalletAccountAddressWithPublicKey:(NSString *)publicKey initialWalletId:(int64_t)initialWalletId rwalletInitialPublicKey:(NSString * _Nullable)rwalletInitialPublicKey { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - NSData *publicKeyData = [publicKey dataUsingEncoding:NSUTF8StringEncoding]; - if (publicKeyData == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in getWalletAccountAddressWithPublicKey"]]; - return [[SBlockDisposable alloc] initWithBlock:^{}]; - } - - NSData *rwalletInitialPublicKeyData = nil; - if (rwalletInitialPublicKey != nil) { - rwalletInitialPublicKeyData = [rwalletInitialPublicKey dataUsingEncoding:NSUTF8StringEncoding]; - if (rwalletInitialPublicKeyData == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string for rwalletInitialPublicKey in getWalletAccountAddressWithPublicKey"]]; - return [[SBlockDisposable alloc] initWithBlock:^{}]; - } - } - - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::accountAddress::ID) { - auto result = tonlib_api::move_object_as(object); - [subscriber putNext:[[NSString alloc] initWithUTF8String:result->account_address_.c_str()]]; - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - - tonlib_api::object_ptr initialAccountState; - - std::int32_t revision; - if (rwalletInitialPublicKey != nil) { - initialAccountState = make_object( - makeString(rwalletInitialPublicKeyData), - makeString(publicKeyData), - initialWalletId - ); - revision = -1; - } else { - initialAccountState = tonlib_api::move_object_as(make_object( - makeString(publicKeyData), - initialWalletId - )); - revision = 1; - } - - auto query = make_object( - tonlib_api::move_object_as(initialAccountState), - revision - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)getAccountStateWithAddress:(NSString *)accountAddress { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::fullAccountState::ID) { - auto fullAccountState = tonlib_api::move_object_as(object); - int32_t seqNo = -1; - - bool isRWallet = false; - int64_t unlockedBalance = INT64_MAX; - - if (fullAccountState->account_state_->get_id() == tonlib_api::uninited_accountState::ID) { - seqNo = -1; - } else if (fullAccountState->account_state_->get_id() == tonlib_api::wallet_v3_accountState::ID) { - auto v3AccountState = tonlib_api::move_object_as(fullAccountState->account_state_); - seqNo = v3AccountState->seqno_; - } else if (fullAccountState->account_state_->get_id() == tonlib_api::rwallet_accountState::ID) { - auto rwalletAccountState = tonlib_api::move_object_as(fullAccountState->account_state_); - isRWallet = true; - unlockedBalance = rwalletAccountState->unlocked_balance_; - seqNo = rwalletAccountState->seqno_; - }else { - [subscriber putError:[[TONError alloc] initWithText:@"Unknown type"]]; - return; - } - - TONTransactionId *lastTransactionId = nil; - if (fullAccountState->last_transaction_id_ != nullptr) { - lastTransactionId = [[TONTransactionId alloc] initWithLt:fullAccountState->last_transaction_id_->lt_ transactionHash:makeData(fullAccountState->last_transaction_id_->hash_)]; - } - [subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:false isRWallet:isRWallet balance:fullAccountState->balance_ unlockedBalance:unlockedBalance seqno:-1 lastTransactionId:lastTransactionId syncUtime:fullAccountState->sync_utime_]]; - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - - auto query = make_object(make_object(accountAddress.UTF8String)); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)generateSendGramsQueryFromKey:(TONKey *)key localPassword:(NSData *)localPassword fromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount comment:(NSData *)comment encryptComment:(bool)encryptComment forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout randomId:(int64_t)randomId { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - if ([_sendGramRandomIds containsObject:@(randomId)]) { - [_sendGramRandomIds addObject:@(randomId)]; - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - } - - NSData *publicKeyData = [key.publicKey dataUsingEncoding:NSUTF8StringEncoding]; - if (publicKeyData == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in sendGramsFromKey"]]; - return [[SBlockDisposable alloc] initWithBlock:^{}]; - } - - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - __weak TON *weakSelf = self; - SQueue *queue = _queue; - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - [queue dispatch:^{ - __strong TON *strongSelf = weakSelf; - if (strongSelf != nil) { - [_sendGramRandomIds removeObject:@(randomId)]; - } - }]; - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::query_info::ID) { - auto result = tonlib_api::move_object_as(object); - TONPreparedSendGramsQuery *preparedQuery = [[TONPreparedSendGramsQuery alloc] initWithQueryId:result->id_ validUntil:result->valid_until_ bodyHash:makeData(result->body_hash_)]; - [subscriber putNext:preparedQuery]; - [subscriber putCompletion]; - } else { - [subscriber putCompletion]; - } - }]; - - tonlib_api::object_ptr inputMessageData; - if (encryptComment && comment.length != 0) { - inputMessageData = make_object( - makeString(comment) - ); - } else { - inputMessageData = make_object( - makeString(comment) - ); - } - std::vector > inputMessages; - inputMessages.push_back(make_object( - make_object(address.UTF8String), - makeString([NSData data]), - amount, - tonlib_api::move_object_as(inputMessageData) - )); - auto inputAction = make_object( - std::move(inputMessages), - forceIfDestinationNotInitialized - ); - - auto query = make_object( - make_object( - make_object( - makeString(publicKeyData), - makeSecureString(key.secret) - ), - makeSecureString(localPassword) - ), - make_object(fromAddress.UTF8String), - timeout, - tonlib_api::move_object_as(inputAction), - nil - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)generateFakeSendGramsQueryFromAddress:(NSString *)fromAddress toAddress:(NSString *)address amount:(int64_t)amount comment:(NSData *)comment encryptComment:(bool)encryptComment forceIfDestinationNotInitialized:(bool)forceIfDestinationNotInitialized timeout:(int32_t)timeout { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::query_info::ID) { - auto result = tonlib_api::move_object_as(object); - TONPreparedSendGramsQuery *preparedQuery = [[TONPreparedSendGramsQuery alloc] initWithQueryId:result->id_ validUntil:result->valid_until_ bodyHash:makeData(result->body_hash_)]; - [subscriber putNext:preparedQuery]; - [subscriber putCompletion]; - } else { - [subscriber putCompletion]; - } - }]; - - tonlib_api::object_ptr inputMessageData; - if (encryptComment && comment.length != 0) { - inputMessageData = make_object( - makeString(comment) - ); - } else { - inputMessageData = make_object( - makeString(comment) - ); - } - std::vector > inputMessages; - inputMessages.push_back(make_object( - make_object(address.UTF8String), - makeString([NSData data]), - amount, - tonlib_api::move_object_as(inputMessageData) - )); - auto inputAction = make_object( - std::move(inputMessages), - forceIfDestinationNotInitialized - ); - - auto query = make_object( - make_object(), - make_object(fromAddress.UTF8String), - timeout, - tonlib_api::move_object_as(inputAction), - nil - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)estimateSendGramsQueryFees:(TONPreparedSendGramsQuery *)preparedQuery { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::query_fees::ID) { - auto result = tonlib_api::move_object_as(object); - TONFees *sourceFees = [[TONFees alloc] initWithInFwdFee:result->source_fees_->in_fwd_fee_ storageFee:result->source_fees_->storage_fee_ gasFee:result->source_fees_->gas_fee_ fwdFee:result->source_fees_->fwd_fee_]; - NSMutableArray *destinationFees = [[NSMutableArray alloc] init]; - for (auto &fee : result->destination_fees_) { - TONFees *destinationFee = [[TONFees alloc] initWithInFwdFee:fee->in_fwd_fee_ storageFee:fee->storage_fee_ gasFee:fee->gas_fee_ fwdFee:fee->fwd_fee_]; - [destinationFees addObject:destinationFee]; - } - - [subscriber putNext:[[TONSendGramsQueryFees alloc] initWithSourceFees:sourceFees destinationFees:destinationFees]]; - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - - auto query = make_object( - preparedQuery.queryId, - true - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)commitPreparedSendGramsQuery:(TONPreparedSendGramsQuery *)preparedQuery { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::ok::ID) { - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - - auto query = make_object( - preparedQuery.queryId - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)exportKey:(TONKey *)key localPassword:(NSData *)localPassword { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - NSData *publicKeyData = [key.publicKey dataUsingEncoding:NSUTF8StringEncoding]; - if (publicKeyData == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in exportKey"]]; - return [[SBlockDisposable alloc] initWithBlock:^{}]; - } - - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::exportedKey::ID) { - auto result = tonlib_api::move_object_as(object); - NSMutableArray *wordList = [[NSMutableArray alloc] init]; - for (auto &it : result->word_list_) { - NSString *string = [[NSString alloc] initWithData:[[NSData alloc] initWithBytes:it.data() length:it.size()] encoding:NSUTF8StringEncoding]; - if (string == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error decoding UTF8 string in exportedKey::word_list"]]; - return; - } - [wordList addObject:string]; - } - [subscriber putNext:wordList]; - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - auto query = make_object( - make_object( - make_object( - makeString(publicKeyData), - makeSecureString(key.secret) - ), - makeSecureString(localPassword) - ) - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)importKeyWithLocalPassword:(NSData *)localPassword mnemonicPassword:(NSData *)mnemonicPassword wordList:(NSArray *)wordList { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::key::ID) { - auto result = tonlib_api::move_object_as(object); - NSString *publicKey = [[NSString alloc] initWithData:[[NSData alloc] initWithBytes:result->public_key_.data() length:result->public_key_.length()] encoding:NSUTF8StringEncoding]; - if (publicKey == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error decoding UTF8 string in importKeyWithLocalPassword"]]; - return; - } - NSData *secret = [[NSData alloc] initWithBytes:result->secret_.data() length:result->secret_.length()]; - [subscriber putNext:[[TONKey alloc] initWithPublicKey:publicKey secret:secret]]; - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - - std::vector wordVector; - for (NSString *word in wordList) { - NSData *wordData = [word dataUsingEncoding:NSUTF8StringEncoding]; - wordVector.push_back(makeSecureString(wordData)); - } - - auto query = make_object( - makeSecureString(localPassword), - makeSecureString(mnemonicPassword), - make_object(std::move(wordVector))); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)deleteKey:(TONKey *)key { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - NSData *publicKeyData = [key.publicKey dataUsingEncoding:NSUTF8StringEncoding]; - if (publicKeyData == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in deleteKey"]]; - return [[SBlockDisposable alloc] initWithBlock:^{}]; - } - - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else { - [subscriber putCompletion]; - } - }]; - - auto query = make_object( - make_object( - makeString(publicKeyData), - makeSecureString(key.secret) - ) - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)deleteAllKeys { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else { - [subscriber putCompletion]; - } - }]; - - auto query = make_object(); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)getTransactionListWithAddress:(NSString * _Nonnull)address lt:(int64_t)lt hash:(NSData * _Nonnull)hash { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - NSData *addressData = [address dataUsingEncoding:NSUTF8StringEncoding]; - if (addressData == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in getTransactionListWithAddress"]]; - return [[SBlockDisposable alloc] initWithBlock:^{}]; - } - - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::raw_transactions::ID) { - auto result = tonlib_api::move_object_as(object); - NSMutableArray *transactions = [[NSMutableArray alloc] init]; - for (auto &it : result->transactions_) { - TONTransactionId *transactionId = [[TONTransactionId alloc] initWithLt:it->transaction_id_->lt_ transactionHash:makeData(it->transaction_id_->hash_)]; - TONTransactionMessage *inMessage = parseTransactionMessage(it->in_msg_); - NSMutableArray * outMessages = [[NSMutableArray alloc] init]; - for (auto &messageIt : it->out_msgs_) { - TONTransactionMessage *outMessage = parseTransactionMessage(messageIt); - if (outMessage != nil) { - [outMessages addObject:outMessage]; - } - } - [transactions addObject:[[TONTransaction alloc] initWithData:makeData(it->data_) transactionId:transactionId timestamp:it->utime_ storageFee:it->storage_fee_ otherFee:it->other_fee_ inMessage:inMessage outMessages:outMessages]]; - } - [subscriber putNext:transactions]; - [subscriber putCompletion]; - } else { - assert(false); - } - }]; - - auto query = make_object( - make_object(), - make_object( - makeString(addressData) - ), - make_object( - lt, - makeString(hash) - ) - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -- (SSignal *)decryptMessagesWithKey:(TONKey * _Nonnull)key localPassword:(NSData * _Nonnull)localPassword messages:(NSArray * _Nonnull)messages { - return [[[[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - NSData *publicKeyData = [key.publicKey dataUsingEncoding:NSUTF8StringEncoding]; - if (publicKeyData == nil) { - [subscriber putError:[[TONError alloc] initWithText:@"Error encoding UTF8 string in decryptMessagesWithKey"]]; - return [[SBlockDisposable alloc] initWithBlock:^{}]; - } - - uint64_t requestId = _nextRequestId; - _nextRequestId += 1; - - _requestHandlers[@(requestId)] = [[TONRequestHandler alloc] initWithCompletion:^(tonlib_api::object_ptr &object) { - if (object->get_id() == tonlib_api::error::ID) { - auto error = tonlib_api::move_object_as(object); - [subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]]; - } else if (object->get_id() == tonlib_api::msg_dataDecryptedArray::ID) { - auto result = tonlib_api::move_object_as(object); - if (result->elements_.size() != messages.count) { - [subscriber putError:[[TONError alloc] initWithText:@"API interaction error"]]; - } else { - NSMutableArray > *resultMessages = [[NSMutableArray alloc] init]; - int index = 0; - for (auto &it : result->elements_) { - if (it->data_->get_id() == tonlib_api::msg_dataDecryptedText::ID) { - auto dataDecryptedText = tonlib_api::move_object_as(it->data_); - NSString *decryptedString = readString(dataDecryptedText->text_); - if (decryptedString != nil) { - [resultMessages addObject:[[TONTransactionMessageContentsPlainText alloc] initWithText:decryptedString]]; - } else { - [resultMessages addObject:[[TONTransactionMessageContentsEncryptedText alloc] initWithEncryptedData:messages[index]]]; - } - } else { - [resultMessages addObject:[[TONTransactionMessageContentsEncryptedText alloc] initWithEncryptedData:messages[index]]]; - } - index++; - } - [subscriber putNext:resultMessages]; - [subscriber putCompletion]; - } - } else { - assert(false); - } - }]; - - std::vector> inputData; - for (TONEncryptedData *message in messages) { - NSData *sourceAddressData = [message.sourceAddress dataUsingEncoding:NSUTF8StringEncoding]; - if (sourceAddressData == nil) { - continue; - } - - inputData.push_back(make_object( - make_object( - makeString(sourceAddressData) - ), - make_object( - makeString(message.data) - ) - )); - } - - auto query = make_object( - make_object( - make_object( - makeString(publicKeyData), - makeSecureString(key.secret) - ), - makeSecureString(localPassword) - ), - make_object( - std::move(inputData) - ) - ); - _client->send({ requestId, std::move(query) }); - - return [[SBlockDisposable alloc] initWithBlock:^{ - }]; - }] startOn:[SQueue mainQueue]] deliverOn:[SQueue mainQueue]]; -} - -@end diff --git a/submodules/UrlHandling/BUILD b/submodules/UrlHandling/BUILD index 4d6dcfb0a7..f1ecafd4b7 100644 --- a/submodules/UrlHandling/BUILD +++ b/submodules/UrlHandling/BUILD @@ -11,7 +11,6 @@ swift_library( ], deps = [ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/MtProtoKit:MtProtoKit", "//submodules/AccountContext:AccountContext", diff --git a/submodules/WallpaperResources/BUILD b/submodules/WallpaperResources/BUILD index 999d61068c..96000b45f6 100644 --- a/submodules/WallpaperResources/BUILD +++ b/submodules/WallpaperResources/BUILD @@ -11,7 +11,6 @@ swift_library( ], deps = [ "//submodules/TelegramCore:TelegramCore", - "//submodules/Postbox:Postbox", "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/Display:Display", "//submodules/LocalMediaResources:LocalMediaResources", diff --git a/submodules/WallpaperResources/Sources/WallpaperResources.swift b/submodules/WallpaperResources/Sources/WallpaperResources.swift index 07dd9e52d0..490a1d162f 100644 --- a/submodules/WallpaperResources/Sources/WallpaperResources.swift +++ b/submodules/WallpaperResources/Sources/WallpaperResources.swift @@ -3,7 +3,6 @@ import UIKit import SwiftSignalKit import Display import CoreImage -import Postbox import TelegramCore import MediaResources import ImageBlur @@ -21,17 +20,17 @@ import GZip public func wallpaperDatas(account: Account, accountManager: AccountManager, fileReference: FileMediaReference? = nil, representations: [ImageRepresentationWithReference], alwaysShowThumbnailFirst: Bool = false, thumbnail: Bool = false, onlyFullSize: Bool = false, autoFetchFullSize: Bool = false, synchronousLoad: Bool = false) -> Signal<(Data?, Data?, Bool), NoError> { if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) { - let maybeFullSize: Signal + let maybeFullSize: Signal if thumbnail, let file = fileReference?.media { maybeFullSize = combineLatest(accountManager.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: false, fetch: false, attemptSynchronously: synchronousLoad), account.postbox.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: false, fetch: false, attemptSynchronously: synchronousLoad)) - |> mapToSignal { maybeSharedData, maybeData -> Signal in + |> mapToSignal { maybeSharedData, maybeData -> Signal in if maybeSharedData.complete { return .single(maybeSharedData) } else if maybeData.complete { return .single(maybeData) } else { return combineLatest(accountManager.mediaBox.resourceData(file.resource), account.postbox.mediaBox.resourceData(file.resource)) - |> mapToSignal { maybeSharedData, maybeData -> Signal in + |> mapToSignal { maybeSharedData, maybeData -> Signal in if maybeSharedData.complete { return accountManager.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: false, fetch: true) } @@ -46,7 +45,7 @@ public func wallpaperDatas(account: Account, accountManager: AccountManager mapToSignal { maybeSharedData, maybeData -> Signal in + |> mapToSignal { maybeSharedData, maybeData -> Signal in if maybeSharedData.complete { return .single(maybeSharedData) } else if maybeData.complete { @@ -57,7 +56,7 @@ public func wallpaperDatas(account: Account, accountManager: AccountManager map { sharedData, data -> MediaResourceData in + |> map { sharedData, data -> EngineRawMediaResourceData in if sharedData.complete && data.complete { if sharedData.size > data.size { return sharedData @@ -87,7 +86,7 @@ public func wallpaperDatas(account: Account, accountManager: AccountManager + let fetchedThumbnail: Signal fetchedThumbnail = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: representations[smallestIndex].reference) let fetchedFullSize = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: representations[largestIndex].reference) @@ -839,7 +838,7 @@ private func builtinWallpaperData() -> Signal { } |> runOn(Queue.concurrentDefaultQueue()) } -public func settingsBuiltinWallpaperImage(account: Account, thumbnail: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { +public func settingsBuiltinWallpaperImage(thumbnail: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { return builtinWallpaperData() |> map { fullSizeImage in return { arguments in guard let context = DrawingContext(size: arguments.drawingSize, clear: true) else { @@ -877,7 +876,7 @@ public func settingsBuiltinWallpaperImage(account: Account, thumbnail: Bool = fa } } -public func photoWallpaper(postbox: Postbox, photoLibraryResource: PhotoLibraryMediaResource) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { +public func photoWallpaper(photoLibraryResource: PhotoLibraryMediaResource) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { let thumbnail = fetchPhotoLibraryImage(localIdentifier: photoLibraryResource.localIdentifier, thumbnail: true) let fullSize = fetchPhotoLibraryImage(localIdentifier: photoLibraryResource.localIdentifier, thumbnail: false) @@ -1172,7 +1171,7 @@ public func themeImage(account: Account, accountManager: AccountManager + let fetchedThumbnail: Signal if let previewRepresentation = previewRepresentation { fetchedThumbnail = fetchedMediaResource(mediaBox: account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: fileReference.resourceReference(previewRepresentation.resource)) } else { diff --git a/third-party/AppCenter/AppCenter.BUILD b/third-party/AppCenter/AppCenter.BUILD deleted file mode 100644 index ce677b8e72..0000000000 --- a/third-party/AppCenter/AppCenter.BUILD +++ /dev/null @@ -1,15 +0,0 @@ -load("@build_bazel_rules_apple//apple:apple.bzl", - "apple_static_framework_import", -) - -apple_static_framework_import( - name = "AppCenter", - framework_imports = glob(["AppCenter-SDK-Apple/iOS/AppCenter.framework/**"]), - visibility = ["//visibility:public"], -) - -apple_static_framework_import( - name = "AppCenterCrashes", - framework_imports = glob(["AppCenter-SDK-Apple/iOS/AppCenterCrashes.framework/**"]), - visibility = ["//visibility:public"], -) diff --git a/third-party/AppCenter/BUILD b/third-party/AppCenter/BUILD deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/third-party/SwiftColor/BUILD b/third-party/SwiftColor/BUILD deleted file mode 100644 index a45048f861..0000000000 --- a/third-party/SwiftColor/BUILD +++ /dev/null @@ -1,17 +0,0 @@ -load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") - -swift_library( - name = "SwiftColor", - module_name = "SwiftColor", - srcs = glob([ - "Sources/**/*.swift", - ]), - copts = [ - "-suppress-warnings", - ], - deps = [ - ], - visibility = [ - "//visibility:public", - ], -) diff --git a/third-party/SwiftColor/Sources/Clamping.swift b/third-party/SwiftColor/Sources/Clamping.swift deleted file mode 100644 index 4154946f98..0000000000 --- a/third-party/SwiftColor/Sources/Clamping.swift +++ /dev/null @@ -1,20 +0,0 @@ -@propertyWrapper -public struct Clamping { - var value: Value - let range: ClosedRange - - public init(wrappedValue value: Value, _ range: ClosedRange) { - precondition(range.contains(value)) - self.value = value - self.range = range - } - - public var wrappedValue: Value { - get { - value - } - set(newValue) { - value = min(max(range.lowerBound, newValue), range.upperBound) - } - } -} diff --git a/third-party/SwiftColor/Sources/ColorSpace.swift b/third-party/SwiftColor/Sources/ColorSpace.swift deleted file mode 100644 index fef838c450..0000000000 --- a/third-party/SwiftColor/Sources/ColorSpace.swift +++ /dev/null @@ -1,3 +0,0 @@ -public enum ColorSpace: Equatable, Sendable { - case rgba -} diff --git a/third-party/SwiftColor/Sources/Pigment+AppKit.swift b/third-party/SwiftColor/Sources/Pigment+AppKit.swift deleted file mode 100644 index 38c875d965..0000000000 --- a/third-party/SwiftColor/Sources/Pigment+AppKit.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Foundation -#if canImport(AppKit) && !targetEnvironment(macCatalyst) -import AppKit - -public extension Pigment { - /// Initialize a `Pigment` using an `NSColor`. - init(_ color: NSColor) { - red = color.redComponent - green = color.greenComponent - blue = color.blueComponent - alpha = color.alphaComponent - } - - var nsColor: NSColor { - NSColor(red: red, green: green, blue: blue, alpha: alpha) - } -} - -public extension NSColor { - var pigment: Pigment { - Pigment(self) - } -} -#endif diff --git a/third-party/SwiftColor/Sources/Pigment+CoreGraphics.swift b/third-party/SwiftColor/Sources/Pigment+CoreGraphics.swift deleted file mode 100644 index 29eaba236e..0000000000 --- a/third-party/SwiftColor/Sources/Pigment+CoreGraphics.swift +++ /dev/null @@ -1,39 +0,0 @@ -import Foundation -#if canImport(CoreGraphics) -import CoreGraphics - -public extension Pigment { - /// Initialize a `Pigment` using an `CGColor`. - init?(_ color: CGColor) { - let components = color.components ?? [] - switch components.count { - case 2: - // Monochrome/Grayscale - // TODO: Express this in 'Color'. - red = 0.0 - green = 0.0 - blue = 0.0 - alpha = components[1] - case 4: - // RGB - red = components[0] - green = components[1] - blue = components[2] - alpha = components[3] - default: - return nil - } - } -} - -public extension CGColor { - static func make(_ color: Pigment) -> CGColor { - if color.red == 0.0, color.green == 0.0, color.blue == 0.0, color.alpha == 0.0 { - // Return the CG color equivalent of `UIColor.clear`. - return CGColor(genericGrayGamma2_2Gray: 0.0, alpha: 0.0) - } - - return CGColor(srgbRed: color.red, green: color.green, blue: color.blue, alpha: color.alpha) - } -} -#endif diff --git a/third-party/SwiftColor/Sources/Pigment+Float.swift b/third-party/SwiftColor/Sources/Pigment+Float.swift deleted file mode 100644 index fbcaf7001a..0000000000 --- a/third-party/SwiftColor/Sources/Pigment+Float.swift +++ /dev/null @@ -1,95 +0,0 @@ -import Foundation - -public extension Pigment { - /// Initialize a `Pigment` using `Float` values leaning towards the 'Red' spectrum. - /// - /// - parameters - /// - red: A value in the range of 0.0 to 1.0 representing the **red** percent. - /// - green: A value in the range of 0.0 to 1.0 representing the **green** percent. - /// - blue: A value in the range of 0.0 to 1.0 representing the **blue** percent. - /// - alpha: A value in the range of 0.0 to 1.0 representing the **alpha/opacity/transparency** percent. - init( - red: Float, - green: Float = 0.0, - blue: Float = 0.0, - alpha: Float = 1.0 - ) { - self.red = Double(red) - self.green = Double(green) - self.blue = Double(blue) - self.alpha = Double(alpha) - } - - /// Initialize a `Pigment` using `Float` values leaning towards the 'Green' spectrum. - /// - /// - parameters: - /// - green: A value in the range of 0.0 to 1.0 representing the **green** percent. - /// - blue: A value in the range of 0.0 to 1.0 representing the **blue** percent. - /// - red: A value in the range of 0.0 to 1.0 representing the **red** percent. - /// - alpha: A value in the range of 0.0 to 1.0 representing the **alpha/opacity/transparency** percent. - init( - green: Float, - blue: Float = 0.0, - red: Float = 0.0, - alpha: Float = 1.0 - ) { - self.red = Double(red) - self.green = Double(green) - self.blue = Double(blue) - self.alpha = Double(alpha) - } - - /// Initialize a `Pigment` using `Float` values leaning towards the 'Blue' spectrum. - /// - /// - parameter: - /// - blue: A value in the range of 0.0 to 1.0 representing the **blue** percent. - /// - red: A value in the range of 0.0 to 1.0 representing the **red** percent. - /// - green: A value in the range of 0.0 to 1.0 representing the **green** percent. - /// - alpha: A value in the range of 0.0 to 1.0 representing the **alpha/opacity/transparency** percent. - init( - blue: Float, - red: Float = 0.0, - green: Float = 0.0, - alpha: Float = 1.0 - ) { - self.red = Double(red) - self.green = Double(green) - self.blue = Double(blue) - self.alpha = Double(alpha) - } - - /// Initialize a `Pigment` using variadic `Float` values. - /// - /// All _values_ should be expressed in the range of 0.0 to 1.0. - /// - /// - parameters: - /// - values: A number of `Float` which are mapped to **red**, **green**, **blue** in that order. - /// - alpha: Amount of _opacity/transparency_ to apply. - init( - _ values: Float..., - alpha: Float - ) { - if values.count > 0 { - red = Double(values[0].clamped(to: 0 ... 1)) - } else { - red = 0.0 - } - if values.count > 1 { - green = Double(values[1].clamped(to: 0 ... 1)) - } else { - green = 0.0 - } - if values.count > 2 { - blue = Double(values[2].clamped(to: 0 ... 1)) - } else { - blue = 0.0 - } - self.alpha = Double(alpha.clamped(to: 0 ... 1)) - } -} - -extension Float { - func clamped(to range: ClosedRange) -> Float { - min(max(range.lowerBound, self), range.upperBound) - } -} diff --git a/third-party/SwiftColor/Sources/Pigment+Hex.swift b/third-party/SwiftColor/Sources/Pigment+Hex.swift deleted file mode 100644 index c969b9538c..0000000000 --- a/third-party/SwiftColor/Sources/Pigment+Hex.swift +++ /dev/null @@ -1,145 +0,0 @@ -import Foundation - -public extension Pigment { - /// Initializes a `Pigment` with an `Int` in the expected format of **0x000**. - /// - /// Used as a short-hand. If the hex 0x123 is provided, it is interpreted as 0x112233. - init( - hex3 hex: Int, - @Clamping(0 ... 1) alpha: Double = 1.0 - ) { - let values = Self.hex3(hex: hex, alpha: alpha) - red = values.red - green = values.green - blue = values.blue - self.alpha = values.alpha - } - - /// Shorthand **0x0000** initializer similar to `init(hex3:alpha:)` where - /// the last digit represent the alpha component. - init( - hex4 hex: Int - ) { - let values = Self.hex4(hex: hex) - red = values.red - green = values.green - blue = values.blue - alpha = values.alpha - } - - /// Initializes with a standard format hex representation of color in the form of **0x1E2C3D**. - init( - hex6 hex: Int, - @Clamping(0 ... 1) alpha: Double = 1.0 - ) { - let values = Self.hex6(hex: hex, alpha: alpha) - red = values.red - green = values.green - blue = values.blue - self.alpha = values.alpha - } - - #if !os(watchOS) - /// Extended form of `init(hex6:alpha:)` expecting **0x112233FF**, that uses the last - /// bits for the alpha component. - init( - hex8 hex: Int - ) { - let values = Self.hex8(hex: hex) - red = values.red - green = values.green - blue = values.blue - alpha = values.alpha - } - #endif - - /// Initializes a `Pigment` with an `Int` representation of an RGB(a) Hex Value - /// - /// This initializer will do its best to interpret the intentions of what is provided. - /// **YOUR RESULTS WILL VARY**, and it's best to use one of the `init(hex?:)` initializers. - /// - /// - Parameter hex: Hex value - /// - Parameter alpha: The opacity value of the color object - init( - _ hex: Int, - alpha: Double? = nil - ) { - #if !os(watchOS) - if hex > 0xFFFFFF { - let values = Self.hex8(hex: hex) - red = values.red - green = values.green - blue = values.blue - self.alpha = values.alpha - return - } - #endif - if hex > 0xFFFF { - let values = Self.hex6(hex: hex, alpha: alpha ?? 1.0) - red = values.red - green = values.green - blue = values.blue - self.alpha = values.alpha - } else if hex > 0xFFF { - let values = Self.hex4(hex: hex) - red = values.red - green = values.green - blue = values.blue - self.alpha = values.alpha - } else { - let values = Self.hex3(hex: hex, alpha: alpha ?? 1.0) - red = values.red - green = values.green - blue = values.blue - self.alpha = values.alpha - } - } -} - -extension Pigment { - static func hex3( - hex: Int, - @Clamping(0 ... 1) alpha: Double = 1.0 - ) -> (red: Double, green: Double, blue: Double, alpha: Double) { - let red = Double(duplicateBits((hex & 0xF00) >> 8)) / 255.0 - let green = Double(duplicateBits((hex & 0x0F0) >> 4)) / 255.0 - let blue = Double(duplicateBits((hex & 0x00F) >> 0)) / 255.0 - return (red, green, blue, alpha) - } - - static func hex4( - hex: Int - ) -> (red: Double, green: Double, blue: Double, alpha: Double) { - let red = Double(duplicateBits((hex & 0xF000) >> 12)) / 255.0 - let green = Double(duplicateBits((hex & 0x0F00) >> 8)) / 255.0 - let blue = Double(duplicateBits((hex & 0x00F0) >> 4)) / 255.0 - let alpha = Double(duplicateBits((hex & 0x000F) >> 0)) / 255.0 - return (red, green, blue, alpha) - } - - static func hex6( - hex: Int, - @Clamping(0 ... 1) alpha: Double = 1.0 - ) -> (red: Double, green: Double, blue: Double, alpha: Double) { - let red = Double((hex & 0xFF0000) >> 16) / 255.0 - let green = Double((hex & 0x00FF00) >> 8) / 255.0 - let blue = Double((hex & 0x0000FF) >> 0) / 255.0 - return (red, green, blue, alpha) - } - - #if !os(watchOS) - static func hex8( - hex: Int - ) -> (red: Double, green: Double, blue: Double, alpha: Double) { - let red = Double((hex & 0xFF00_0000) >> 24) / 255.0 - let green = Double((hex & 0x00FF_0000) >> 16) / 255.0 - let blue = Double((hex & 0x0000_FF00) >> 8) / 255.0 - let alpha = Double((hex & 0x0000_00FF) >> 0) / 255.0 - return (red, green, blue, alpha) - } - #endif - - static func duplicateBits(_ value: Int) -> Int { - (value << 4) + value - } -} diff --git a/third-party/SwiftColor/Sources/Pigment+Int.swift b/third-party/SwiftColor/Sources/Pigment+Int.swift deleted file mode 100644 index 16568d0142..0000000000 --- a/third-party/SwiftColor/Sources/Pigment+Int.swift +++ /dev/null @@ -1,89 +0,0 @@ -import Foundation - -public extension Pigment { - /// Initialize a `Pigment` using `Int` values leaning towards the 'Red' spectrum. - /// - /// - parameters: - /// - red: A value in the range of 0 to 255 representing the **red** bits - /// - green: A value in the range of 0 to 255 representing the **green** bits - /// - blue: A value in the range of 0 to 255 representing the **blue** bits - /// - alpha: A value in the range of 0.0 to 1.0 representing the **alpha/opacity/transparency** percent. - init( - @Clamping(0 ... 255) red: Int, - @Clamping(0 ... 255) green: Int = 0, - @Clamping(0 ... 255) blue: Int = 0, - @Clamping(0.0 ... 1.0) alpha: Double = 1.0 - ) { - self.red = Double(red) / 255.0 - self.green = Double(green) / 255.0 - self.blue = Double(blue) / 255.0 - self.alpha = alpha - } - - /// Initialize a `Pigment` using `Int` values leaning towards the 'Green' spectrum. - /// - /// - parameters: - /// - green: A value in the range of 0 to 255 representing the **green** bits - /// - blue: A value in the range of 0 to 255 representing the **blue** bits - /// - red: A value in the range of 0 to 255 representing the **red** bits - /// - alpha: A value in the range of 0.0 to 1.0 representing the **alpha/opacity/transparency** percent. - init( - @Clamping(0 ... 255) green: Int, - @Clamping(0 ... 255) blue: Int = 0, - @Clamping(0 ... 255) red: Int = 0, - @Clamping(0.0 ... 1.0) alpha: Double = 1.0 - ) { - self.red = Double(red) / 255.0 - self.green = Double(green) / 255.0 - self.blue = Double(blue) / 255.0 - self.alpha = alpha - } - - /// Initialize a `Pigment` using `Int` values leaning towards the 'Blue' spectrum. - /// - /// - parameters: - /// - blue: A value in the range of 0 to 255 representing the **blue** bits - /// - red: A value in the range of 0 to 255 representing the **red** bits - /// - green: A value in the range of 0 to 255 representing the **green** bits - /// - alpha: A value in the range of 0.0 to 1.0 representing the **alpha/opacity/transparency** percent. - init( - @Clamping(0 ... 255) blue: Int, - @Clamping(0 ... 255) red: Int = 0, - @Clamping(0 ... 255) green: Int = 0, - @Clamping(0.0 ... 1.0) alpha: Double = 1.0 - ) { - self.red = Double(red) / 255.0 - self.green = Double(green) / 255.0 - self.blue = Double(blue) / 255.0 - self.alpha = alpha - } - - /// Initialize a `Pigment` using variadic `Int` values. - /// - /// All _values_ should be expressed in the range of 0 to 255. - /// - /// - parameters: - /// - values: A number of `Int` which are mapped to **red**, **green**, **blue** in that order. - /// - alpha: A value in the range of 0.0 to 1.0 representing the **alpha/opacity/transparency** percent. - init( - _ values: Int..., - @Clamping(0 ... 1) alpha: Double - ) { - if values.count > 0 { - red = Double(values[0]) / 255.0 - } else { - red = 0.0 - } - if values.count > 1 { - green = Double(values[1]) / 255.0 - } else { - green = 0.0 - } - if values.count > 2 { - blue = Double(values[2]) / 255.0 - } else { - blue = 0.0 - } - self.alpha = alpha - } -} diff --git a/third-party/SwiftColor/Sources/Pigment+Name.swift b/third-party/SwiftColor/Sources/Pigment+Name.swift deleted file mode 100644 index 8857f8f450..0000000000 --- a/third-party/SwiftColor/Sources/Pigment+Name.swift +++ /dev/null @@ -1,470 +0,0 @@ -import Foundation - -public extension Pigment { - @available(*, deprecated, renamed: "Name") - typealias Keyword = Name - - enum Name: String, CaseIterable { - case aliceBlue - case antiqueWhite - case aqua - case aquamarine - case azure - case beige - case bisque - case black - case blanchedAlmond - case blue - case blueViolet - case brown - case burlywood - case cadetBlue - case chartreuse - case chocolate - case coral - case cornflowerBlue - case cornsilk - case crimson - case cyan - case darkBlue - case darkCyan - case darkGoldenrod - case darkGray - case darkGreen - case darkGrey - case darkKhaki - case darkMagenta - case darkOliveGreen - case darkOrange - case darkOrchid - case darkRed - case darkSalmon - case darkSeagreen - case darkSlateBlue - case darkSlateGray - case darkSlateGrey - case darkTurquoise - case darkViolet - case deepPink - case deepSkyblue - case dimGray - case dimGrey - case dodgerBlue - case firebrick - case floralWhite - case forestGreen - case fuchsia - case gainsboro - case ghostWhite - case gold - case goldenrod - case gray - case green - case greenYellow - case grey - case honeydew - case hotPink - case indianRed - case indigo - case ivory - case khaki - case lavender - case lavenderBlush - case lawnGreen - case lemonChiffon - case lightBlue - case lightCoral - case lightCyan - case lightGoldenrodYellow - case lightGray - case lightGreen - case lightGrey - case lightPink - case lightSalmon - case lightSeagreen - case lightSkyBlue - case lightSlateGray - case lightSlateGrey - case lightSteelBlue - case lightYellow - case lime - case limeGreen - case linen - case magenta - case maroon - case mediumAquamarine - case mediumBlue - case mediumOrchid - case mediumPurple - case mediumSeagreen - case mediumSlateBlue - case mediumSpringGreen - case mediumTurquoise - case mediumVioletRed - case midnightBlue - case mintCream - case mistyRose - case moccasin - case navajoWhite - case navy - case oldLace - case olive - case oliveDrab - case orange - case orangeRed - case orchid - case paleGoldenrod - case paleGreen - case paleTurquoise - case paleVioletRed - case papayaWhip - case peachPuff - case peru - case pink - case plum - case powderBlue - case purple - case red - case rosyBrown - case royalBlue - case saddleBrown - case salmon - case sandyBrown - case seagreen - case seashell - case sienna - case silver - case skyBlue - case slateBlue - case slateGray - case slateGrey - case snow - case springGreen - case steelBlue - case tan - case teal - case thistle - case tomato - case turquoise - case violet - case wheat - case white - case whitesmoke - case yellow - case yellowGreen - - public var rgb: (red: Int, green: Int, blue: Int) { - switch self { - case .aliceBlue: (240, 248, 255) - case .antiqueWhite: (250, 235, 215) - case .aqua: (0, 255, 255) - case .aquamarine: (127, 255, 212) - case .azure: (240, 255, 255) - case .beige: (245, 245, 220) - case .bisque: (255, 228, 196) - case .black: (0, 0, 0) - case .blanchedAlmond: (255, 235, 205) - case .blue: (0, 0, 255) - case .blueViolet: (138, 43, 226) - case .brown: (165, 42, 42) - case .burlywood: (222, 184, 135) - case .cadetBlue: (95, 158, 160) - case .chartreuse: (127, 255, 0) - case .chocolate: (210, 105, 30) - case .coral: (255, 127, 80) - case .cornflowerBlue: (100, 149, 237) - case .cornsilk: (255, 248, 220) - case .crimson: (220, 20, 60) - case .cyan: (0, 255, 255) - case .darkBlue: (0, 0, 139) - case .darkCyan: (0, 139, 139) - case .darkGoldenrod: (184, 134, 11) - case .darkGray: (169, 169, 169) - case .darkGreen: (0, 100, 0) - case .darkGrey: (169, 169, 169) - case .darkKhaki: (189, 183, 107) - case .darkMagenta: (139, 0, 139) - case .darkOliveGreen: (85, 107, 47) - case .darkOrange: (255, 140, 0) - case .darkOrchid: (153, 50, 204) - case .darkRed: (139, 0, 0) - case .darkSalmon: (233, 150, 122) - case .darkSeagreen: (143, 188, 143) - case .darkSlateBlue: (72, 61, 139) - case .darkSlateGray: (47, 79, 79) - case .darkSlateGrey: (47, 79, 79) - case .darkTurquoise: (0, 206, 209) - case .darkViolet: (148, 0, 211) - case .deepPink: (255, 20, 147) - case .deepSkyblue: (0, 191, 255) - case .dimGray: (105, 105, 105) - case .dimGrey: (105, 105, 105) - case .dodgerBlue: (30, 144, 255) - case .firebrick: (178, 34, 34) - case .floralWhite: (255, 250, 240) - case .forestGreen: (34, 139, 34) - case .fuchsia: (255, 0, 255) - case .gainsboro: (220, 220, 220) - case .ghostWhite: (248, 248, 255) - case .gold: (255, 215, 0) - case .goldenrod: (218, 165, 32) - case .gray: (128, 128, 128) - case .green: (0, 128, 0) - case .greenYellow: (173, 255, 47) - case .grey: (128, 128, 128) - case .honeydew: (240, 255, 240) - case .hotPink: (255, 105, 180) - case .indianRed: (205, 92, 92) - case .indigo: (75, 0, 130) - case .ivory: (255, 255, 240) - case .khaki: (240, 230, 140) - case .lavender: (230, 230, 250) - case .lavenderBlush: (255, 240, 245) - case .lawnGreen: (124, 252, 0) - case .lemonChiffon: (255, 250, 205) - case .lightBlue: (173, 216, 230) - case .lightCoral: (240, 128, 128) - case .lightCyan: (224, 255, 255) - case .lightGoldenrodYellow: (250, 250, 210) - case .lightGray: (211, 211, 211) - case .lightGreen: (144, 238, 144) - case .lightGrey: (211, 211, 211) - case .lightPink: (255, 182, 193) - case .lightSalmon: (255, 160, 122) - case .lightSeagreen: (32, 178, 170) - case .lightSkyBlue: (135, 206, 250) - case .lightSlateGray: (119, 136, 153) - case .lightSlateGrey: (119, 136, 153) - case .lightSteelBlue: (176, 196, 222) - case .lightYellow: (255, 255, 224) - case .lime: (0, 255, 0) - case .limeGreen: (50, 205, 50) - case .linen: (250, 240, 230) - case .magenta: (255, 0, 255) - case .maroon: (128, 0, 0) - case .mediumAquamarine: (102, 205, 170) - case .mediumBlue: (0, 0, 205) - case .mediumOrchid: (186, 85, 211) - case .mediumPurple: (147, 112, 219) - case .mediumSeagreen: (60, 179, 113) - case .mediumSlateBlue: (123, 104, 238) - case .mediumSpringGreen: (0, 250, 154) - case .mediumTurquoise: (72, 209, 204) - case .mediumVioletRed: (199, 21, 133) - case .midnightBlue: (25, 25, 112) - case .mintCream: (245, 255, 250) - case .mistyRose: (255, 228, 225) - case .moccasin: (255, 228, 181) - case .navajoWhite: (255, 222, 173) - case .navy: (0, 0, 128) - case .oldLace: (253, 245, 230) - case .olive: (128, 128, 0) - case .oliveDrab: (107, 142, 35) - case .orange: (255, 165, 0) - case .orangeRed: (255, 69, 0) - case .orchid: (218, 112, 214) - case .paleGoldenrod: (238, 232, 170) - case .paleGreen: (152, 251, 152) - case .paleTurquoise: (175, 238, 238) - case .paleVioletRed: (219, 112, 147) - case .papayaWhip: (255, 239, 213) - case .peachPuff: (255, 218, 185) - case .peru: (205, 133, 63) - case .pink: (255, 192, 203) - case .plum: (221, 160, 221) - case .powderBlue: (176, 224, 230) - case .purple: (128, 0, 128) - case .red: (255, 0, 0) - case .rosyBrown: (188, 143, 143) - case .royalBlue: (65, 105, 225) - case .saddleBrown: (139, 69, 19) - case .salmon: (250, 128, 114) - case .sandyBrown: (244, 164, 96) - case .seagreen: (46, 139, 87) - case .seashell: (255, 245, 238) - case .sienna: (160, 82, 45) - case .silver: (192, 192, 192) - case .skyBlue: (135, 206, 235) - case .slateBlue: (106, 90, 205) - case .slateGray: (112, 128, 144) - case .slateGrey: (112, 128, 144) - case .snow: (255, 250, 250) - case .springGreen: (0, 255, 127) - case .steelBlue: (70, 130, 180) - case .tan: (210, 180, 140) - case .teal: (0, 128, 128) - case .thistle: (216, 191, 216) - case .tomato: (255, 99, 71) - case .turquoise: (64, 224, 208) - case .violet: (238, 130, 238) - case .wheat: (245, 222, 179) - case .white: (255, 255, 255) - case .whitesmoke: (245, 245, 245) - case .yellow: (255, 255, 0) - case .yellowGreen: (154, 205, 50) - } - } - - public var pigment: Pigment { - switch self { - case .aliceBlue: Pigment(240, 248, 255, alpha: 1.0) - case .antiqueWhite: Pigment(250, 235, 215, alpha: 1.0) - case .aqua: Pigment(0, 255, 255, alpha: 1.0) - case .aquamarine: Pigment(127, 255, 212, alpha: 1.0) - case .azure: Pigment(240, 255, 255, alpha: 1.0) - case .beige: Pigment(245, 245, 220, alpha: 1.0) - case .bisque: Pigment(255, 228, 196, alpha: 1.0) - case .black: Pigment(0, 0, 0, alpha: 1.0) - case .blanchedAlmond: Pigment(255, 235, 205, alpha: 1.0) - case .blue: Pigment(0, 0, 255, alpha: 1.0) - case .blueViolet: Pigment(138, 43, 226, alpha: 1.0) - case .brown: Pigment(165, 42, 42, alpha: 1.0) - case .burlywood: Pigment(222, 184, 135, alpha: 1.0) - case .cadetBlue: Pigment(95, 158, 160, alpha: 1.0) - case .chartreuse: Pigment(127, 255, 0, alpha: 1.0) - case .chocolate: Pigment(210, 105, 30, alpha: 1.0) - case .coral: Pigment(255, 127, 80, alpha: 1.0) - case .cornflowerBlue: Pigment(100, 149, 237, alpha: 1.0) - case .cornsilk: Pigment(255, 248, 220, alpha: 1.0) - case .crimson: Pigment(220, 20, 60, alpha: 1.0) - case .cyan: Pigment(0, 255, 255, alpha: 1.0) - case .darkBlue: Pigment(0, 0, 139, alpha: 1.0) - case .darkCyan: Pigment(0, 139, 139, alpha: 1.0) - case .darkGoldenrod: Pigment(184, 134, 11, alpha: 1.0) - case .darkGray: Pigment(169, 169, 169, alpha: 1.0) - case .darkGreen: Pigment(0, 100, 0, alpha: 1.0) - case .darkGrey: Pigment(169, 169, 169, alpha: 1.0) - case .darkKhaki: Pigment(189, 183, 107, alpha: 1.0) - case .darkMagenta: Pigment(139, 0, 139, alpha: 1.0) - case .darkOliveGreen: Pigment(85, 107, 47, alpha: 1.0) - case .darkOrange: Pigment(255, 140, 0, alpha: 1.0) - case .darkOrchid: Pigment(153, 50, 204, alpha: 1.0) - case .darkRed: Pigment(139, 0, 0, alpha: 1.0) - case .darkSalmon: Pigment(233, 150, 122, alpha: 1.0) - case .darkSeagreen: Pigment(143, 188, 143, alpha: 1.0) - case .darkSlateBlue: Pigment(72, 61, 139, alpha: 1.0) - case .darkSlateGray: Pigment(47, 79, 79, alpha: 1.0) - case .darkSlateGrey: Pigment(47, 79, 79, alpha: 1.0) - case .darkTurquoise: Pigment(0, 206, 209, alpha: 1.0) - case .darkViolet: Pigment(148, 0, 211, alpha: 1.0) - case .deepPink: Pigment(255, 20, 147, alpha: 1.0) - case .deepSkyblue: Pigment(0, 191, 255, alpha: 1.0) - case .dimGray: Pigment(105, 105, 105, alpha: 1.0) - case .dimGrey: Pigment(105, 105, 105, alpha: 1.0) - case .dodgerBlue: Pigment(30, 144, 255, alpha: 1.0) - case .firebrick: Pigment(178, 34, 34, alpha: 1.0) - case .floralWhite: Pigment(255, 250, 240, alpha: 1.0) - case .forestGreen: Pigment(34, 139, 34, alpha: 1.0) - case .fuchsia: Pigment(255, 0, 255, alpha: 1.0) - case .gainsboro: Pigment(220, 220, 220, alpha: 1.0) - case .ghostWhite: Pigment(248, 248, 255, alpha: 1.0) - case .gold: Pigment(255, 215, 0, alpha: 1.0) - case .goldenrod: Pigment(218, 165, 32, alpha: 1.0) - case .gray: Pigment(128, 128, 128, alpha: 1.0) - case .green: Pigment(0, 128, 0, alpha: 1.0) - case .greenYellow: Pigment(173, 255, 47, alpha: 1.0) - case .grey: Pigment(128, 128, 128, alpha: 1.0) - case .honeydew: Pigment(240, 255, 240, alpha: 1.0) - case .hotPink: Pigment(255, 105, 180, alpha: 1.0) - case .indianRed: Pigment(205, 92, 92, alpha: 1.0) - case .indigo: Pigment(75, 0, 130, alpha: 1.0) - case .ivory: Pigment(255, 255, 240, alpha: 1.0) - case .khaki: Pigment(240, 230, 140, alpha: 1.0) - case .lavender: Pigment(230, 230, 250, alpha: 1.0) - case .lavenderBlush: Pigment(255, 240, 245, alpha: 1.0) - case .lawnGreen: Pigment(124, 252, 0, alpha: 1.0) - case .lemonChiffon: Pigment(255, 250, 205, alpha: 1.0) - case .lightBlue: Pigment(173, 216, 230, alpha: 1.0) - case .lightCoral: Pigment(240, 128, 128, alpha: 1.0) - case .lightCyan: Pigment(224, 255, 255, alpha: 1.0) - case .lightGoldenrodYellow: Pigment(250, 250, 210, alpha: 1.0) - case .lightGray: Pigment(211, 211, 211, alpha: 1.0) - case .lightGreen: Pigment(144, 238, 144, alpha: 1.0) - case .lightGrey: Pigment(211, 211, 211, alpha: 1.0) - case .lightPink: Pigment(255, 182, 193, alpha: 1.0) - case .lightSalmon: Pigment(255, 160, 122, alpha: 1.0) - case .lightSeagreen: Pigment(32, 178, 170, alpha: 1.0) - case .lightSkyBlue: Pigment(135, 206, 250, alpha: 1.0) - case .lightSlateGray: Pigment(119, 136, 153, alpha: 1.0) - case .lightSlateGrey: Pigment(119, 136, 153, alpha: 1.0) - case .lightSteelBlue: Pigment(176, 196, 222, alpha: 1.0) - case .lightYellow: Pigment(255, 255, 224, alpha: 1.0) - case .lime: Pigment(0, 255, 0, alpha: 1.0) - case .limeGreen: Pigment(50, 205, 50, alpha: 1.0) - case .linen: Pigment(250, 240, 230, alpha: 1.0) - case .magenta: Pigment(255, 0, 255, alpha: 1.0) - case .maroon: Pigment(128, 0, 0, alpha: 1.0) - case .mediumAquamarine: Pigment(102, 205, 170, alpha: 1.0) - case .mediumBlue: Pigment(0, 0, 205, alpha: 1.0) - case .mediumOrchid: Pigment(186, 85, 211, alpha: 1.0) - case .mediumPurple: Pigment(147, 112, 219, alpha: 1.0) - case .mediumSeagreen: Pigment(60, 179, 113, alpha: 1.0) - case .mediumSlateBlue: Pigment(123, 104, 238, alpha: 1.0) - case .mediumSpringGreen: Pigment(0, 250, 154, alpha: 1.0) - case .mediumTurquoise: Pigment(72, 209, 204, alpha: 1.0) - case .mediumVioletRed: Pigment(199, 21, 133, alpha: 1.0) - case .midnightBlue: Pigment(25, 25, 112, alpha: 1.0) - case .mintCream: Pigment(245, 255, 250, alpha: 1.0) - case .mistyRose: Pigment(255, 228, 225, alpha: 1.0) - case .moccasin: Pigment(255, 228, 181, alpha: 1.0) - case .navajoWhite: Pigment(255, 222, 173, alpha: 1.0) - case .navy: Pigment(0, 0, 128, alpha: 1.0) - case .oldLace: Pigment(253, 245, 230, alpha: 1.0) - case .olive: Pigment(128, 128, 0, alpha: 1.0) - case .oliveDrab: Pigment(107, 142, 35, alpha: 1.0) - case .orange: Pigment(255, 165, 0, alpha: 1.0) - case .orangeRed: Pigment(255, 69, 0, alpha: 1.0) - case .orchid: Pigment(218, 112, 214, alpha: 1.0) - case .paleGoldenrod: Pigment(238, 232, 170, alpha: 1.0) - case .paleGreen: Pigment(152, 251, 152, alpha: 1.0) - case .paleTurquoise: Pigment(175, 238, 238, alpha: 1.0) - case .paleVioletRed: Pigment(219, 112, 147, alpha: 1.0) - case .papayaWhip: Pigment(255, 239, 213, alpha: 1.0) - case .peachPuff: Pigment(255, 218, 185, alpha: 1.0) - case .peru: Pigment(205, 133, 63, alpha: 1.0) - case .pink: Pigment(255, 192, 203, alpha: 1.0) - case .plum: Pigment(221, 160, 221, alpha: 1.0) - case .powderBlue: Pigment(176, 224, 230, alpha: 1.0) - case .purple: Pigment(128, 0, 128, alpha: 1.0) - case .red: Pigment(255, 0, 0, alpha: 1.0) - case .rosyBrown: Pigment(188, 143, 143, alpha: 1.0) - case .royalBlue: Pigment(65, 105, 225, alpha: 1.0) - case .saddleBrown: Pigment(139, 69, 19, alpha: 1.0) - case .salmon: Pigment(250, 128, 114, alpha: 1.0) - case .sandyBrown: Pigment(244, 164, 96, alpha: 1.0) - case .seagreen: Pigment(46, 139, 87, alpha: 1.0) - case .seashell: Pigment(255, 245, 238, alpha: 1.0) - case .sienna: Pigment(160, 82, 45, alpha: 1.0) - case .silver: Pigment(192, 192, 192, alpha: 1.0) - case .skyBlue: Pigment(135, 206, 235, alpha: 1.0) - case .slateBlue: Pigment(106, 90, 205, alpha: 1.0) - case .slateGray: Pigment(112, 128, 144, alpha: 1.0) - case .slateGrey: Pigment(112, 128, 144, alpha: 1.0) - case .snow: Pigment(255, 250, 250, alpha: 1.0) - case .springGreen: Pigment(0, 255, 127, alpha: 1.0) - case .steelBlue: Pigment(70, 130, 180, alpha: 1.0) - case .tan: Pigment(210, 180, 140, alpha: 1.0) - case .teal: Pigment(0, 128, 128, alpha: 1.0) - case .thistle: Pigment(216, 191, 216, alpha: 1.0) - case .tomato: Pigment(255, 99, 71, alpha: 1.0) - case .turquoise: Pigment(64, 224, 208, alpha: 1.0) - case .violet: Pigment(238, 130, 238, alpha: 1.0) - case .wheat: Pigment(245, 222, 179, alpha: 1.0) - case .white: Pigment(255, 255, 255, alpha: 1.0) - case .whitesmoke: Pigment(245, 245, 245, alpha: 1.0) - case .yellow: Pigment(255, 255, 0, alpha: 1.0) - case .yellowGreen: Pigment(154, 205, 50, alpha: 1.0) - } - } - } - - init( - _ name: Name, - @Clamping(0 ... 1) alpha: Double = 1.0 - ) { - red = Double(name.rgb.red) / 255.0 - green = Double(name.rgb.green) / 255.0 - blue = Double(name.rgb.blue) / 255.0 - self.alpha = alpha - } -} diff --git a/third-party/SwiftColor/Sources/Pigment+String.swift b/third-party/SwiftColor/Sources/Pigment+String.swift deleted file mode 100644 index 22c7b01124..0000000000 --- a/third-party/SwiftColor/Sources/Pigment+String.swift +++ /dev/null @@ -1,76 +0,0 @@ -import Foundation - -public extension Pigment { - init(_ value: String, alpha: Double = 1.0) { - if let keyword = Name.allCases.first(where: { $0.rawValue.caseInsensitiveCompare(value) == .orderedSame }) { - red = keyword.pigment.red - green = keyword.pigment.green - blue = keyword.pigment.blue - self.alpha = alpha - return - } - - if ExtendedKeyword.allCases.contains(where: { $0.rawValue.caseInsensitiveCompare(value) == .orderedSame }) { - red = 1.0 - green = 1.0 - blue = 1.0 - self.alpha = alpha - return - } - - var hex = value - if hex.hasPrefix("#") { - hex = String(hex.dropFirst()) - } - - guard let hexValue = Int(hex, radix: 16) else { - red = 1.0 - green = 1.0 - blue = 1.0 - self.alpha = alpha - return - } - - switch hex.count { - case 3: - let values = Self.hex3(hex: hexValue) - red = values.red - green = values.green - blue = values.blue - self.alpha = values.alpha - case 4: - let values = Self.hex4(hex: hexValue) - red = values.red - green = values.green - blue = values.blue - self.alpha = values.alpha - case 6: - let values = Self.hex6(hex: hexValue, alpha: alpha) - red = values.red - green = values.green - blue = values.blue - self.alpha = values.alpha - #if !os(watchOS) - case 8: - let values = Self.hex8(hex: hexValue) - red = values.red - green = values.green - blue = values.blue - self.alpha = values.alpha - #endif - default: - red = 1.0 - green = 1.0 - blue = 1.0 - self.alpha = alpha - } - } -} - -private extension Pigment { - enum ExtendedKeyword: String, CaseIterable { - case none - case clear - case transparent - } -} diff --git a/third-party/SwiftColor/Sources/Pigment+SwiftUI.swift b/third-party/SwiftColor/Sources/Pigment+SwiftUI.swift deleted file mode 100644 index d07aa1aec1..0000000000 --- a/third-party/SwiftColor/Sources/Pigment+SwiftUI.swift +++ /dev/null @@ -1,9 +0,0 @@ -#if canImport(SwiftUI) -import SwiftUI - -public extension Pigment { - var color: Color { - Color(red: red, green: green, blue: blue, opacity: alpha) - } -} -#endif diff --git a/third-party/SwiftColor/Sources/Pigment+UIKit.swift b/third-party/SwiftColor/Sources/Pigment+UIKit.swift deleted file mode 100644 index 8c96c2cc7e..0000000000 --- a/third-party/SwiftColor/Sources/Pigment+UIKit.swift +++ /dev/null @@ -1,37 +0,0 @@ -import Foundation -#if canImport(UIKit) -import UIKit - -public extension Pigment { - init(_ color: UIColor) { - var redComponent: CGFloat = 1.0 - var greenComponent: CGFloat = 1.0 - var blueComponent: CGFloat = 1.0 - var alphaComponent: CGFloat = 1.0 - - guard color.getRed(&redComponent, green: &greenComponent, blue: &blueComponent, alpha: &alphaComponent) else { - // TODO: Fail Initializer? Default Colors? - red = redComponent - green = greenComponent - blue = blueComponent - alpha = alphaComponent - return - } - - red = redComponent - green = greenComponent - blue = blueComponent - alpha = alphaComponent - } - - var uiColor: UIColor { - UIColor(red: red, green: green, blue: blue, alpha: alpha) - } -} - -public extension UIColor { - var pigment: Pigment { - Pigment(self) - } -} -#endif diff --git a/third-party/SwiftColor/Sources/Pigment.swift b/third-party/SwiftColor/Sources/Pigment.swift deleted file mode 100644 index 3db75b50bb..0000000000 --- a/third-party/SwiftColor/Sources/Pigment.swift +++ /dev/null @@ -1,53 +0,0 @@ -/// A platform agnostic representation of Color -/// -/// The components - red, green, blue, & alpha - are maintained as a floating-point representation. -/// Each value can range from 0.0 to 1.0 (e.g. 0 to 100 percent). -/// -/// 'Pure White' is represented by values all equal to **1.0**. -public struct Pigment: Sendable { - - public let colorSpace: ColorSpace = .rgba - public let red: Double - public let green: Double - public let blue: Double - public let alpha: Double - - public init( - @Clamping(0 ... 1) red: Double = 1.0, - @Clamping(0 ... 1) green: Double = 1.0, - @Clamping(0 ... 1) blue: Double = 1.0, - @Clamping(0 ... 1) alpha: Double = 1.0 - ) { - self.red = red - self.green = green - self.blue = blue - self.alpha = alpha - } -} - -extension Pigment: CustomStringConvertible { - public var description: String { - String(format: "Pigment(red: %.4f, green: %.4f, blue: %.4f, alpha: %.2f)", red, green, blue, alpha) - } -} - -extension Pigment: Equatable { - public static func == (lhs: Pigment, rhs: Pigment) -> Bool { - guard lhs.red == rhs.red else { - return false - } - guard lhs.green == rhs.green else { - return false - } - guard lhs.blue == rhs.blue else { - return false - } - guard lhs.alpha == rhs.alpha else { - return false - } - guard lhs.colorSpace == rhs.colorSpace else { - return false - } - return true - } -} diff --git a/third-party/SwiftSVG/BUILD b/third-party/SwiftSVG/BUILD deleted file mode 100644 index 565ad88ec4..0000000000 --- a/third-party/SwiftSVG/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") - -swift_library( - name = "SwiftSVG", - module_name = "SwiftSVG", - srcs = glob([ - "Sources/**/*.swift", - ]), - copts = [ - "-warnings-as-errors", - ], - deps = [ - "//third-party/XMLCoder", - "//third-party/Swift2D", - ], - visibility = [ - "//visibility:public", - ], -) diff --git a/third-party/SwiftSVG/Sources/Circle.swift b/third-party/SwiftSVG/Sources/Circle.swift deleted file mode 100644 index d42c8b9c73..0000000000 --- a/third-party/SwiftSVG/Sources/Circle.swift +++ /dev/null @@ -1,93 +0,0 @@ -import Swift2D -import XMLCoder - -/// Basic shape, used to draw circles based on a center point and a radius. -/// -/// The arc of a ‘circle’ element begins at the "3 o'clock" point on the radius and progresses towards the -/// "9 o'clock" point. The starting point and direction of the arc are affected by the user space transform -/// in the same manner as the geometry of the element. -/// -/// ## Documentation -/// [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle) -/// | [W3](https://www.w3.org/TR/SVG11/shapes.html#CircleElement) -public struct Circle: Element { - - /// The x-axis coordinate of the center of the circle. - public var x: Double = 0.0 - /// The y-axis coordinate of the center of the circle. - public var y: Double = 0.0 - /// The radius of the circle. - public var r: Double = 0.0 - - // MARK: CoreAttributes - - public var id: String? - - // MARK: PresentationAttributes - - public var fillColor: String? - public var fillOpacity: Double? - public var fillRule: Fill.Rule? - public var strokeColor: String? - public var strokeWidth: Double? - public var strokeOpacity: Double? - public var strokeLineCap: Stroke.LineCap? - public var strokeLineJoin: Stroke.LineJoin? - public var strokeMiterLimit: Double? - public var transform: String? - - // MARK: StylingAttributes - - public var style: String? - - enum CodingKeys: String, CodingKey { - case x = "cx" - case y = "cy" - case r - case id - case fillColor = "fill" - case fillOpacity = "fill-opacity" - case fillRule = "fill-rule" - case strokeColor = "stroke" - case strokeWidth = "stroke-width" - case strokeOpacity = "stroke-opacity" - case strokeLineCap = "stroke-linecap" - case strokeLineJoin = "stroke-linejoin" - case strokeMiterLimit = "stroke-miterlimit" - case transform - case style - } - - public init() {} - - public init(x: Double, y: Double, r: Double) { - self.x = x - self.y = y - self.r = r - } -} - -extension Circle: CustomStringConvertible { - public var description: String { - let desc = "" - } -} - -extension Circle: DirectionalCommandRepresentable { - public func commands(clockwise: Bool) throws -> [Path.Command] { - EllipseProcessor(circle: self).commands(clockwise: clockwise) - } -} - -extension Circle: DynamicNodeDecoding { - public static func nodeDecoding(for key: any CodingKey) -> XMLDecoder.NodeDecoding { - .attribute - } -} - -extension Circle: DynamicNodeEncoding { - public static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { - .attribute - } -} diff --git a/third-party/SwiftSVG/Sources/CommandRepresentable.swift b/third-party/SwiftSVG/Sources/CommandRepresentable.swift deleted file mode 100644 index f6bb79f05d..0000000000 --- a/third-party/SwiftSVG/Sources/CommandRepresentable.swift +++ /dev/null @@ -1,15 +0,0 @@ -/// Elements conforming to `CommandRepresentable` can be expressed in the form of `Path.Command`s. -public protocol CommandRepresentable { - func commands() throws -> [Path.Command] -} - -public protocol DirectionalCommandRepresentable: CommandRepresentable { - func commands(clockwise: Bool) throws -> [Path.Command] -} - -public extension DirectionalCommandRepresentable { - /// Defaults to anti/counter-clockwise commands. - func commands() throws -> [Path.Command] { - try commands(clockwise: false) - } -} diff --git a/third-party/SwiftSVG/Sources/Container.swift b/third-party/SwiftSVG/Sources/Container.swift deleted file mode 100644 index c90f0ea33a..0000000000 --- a/third-party/SwiftSVG/Sources/Container.swift +++ /dev/null @@ -1,58 +0,0 @@ -public protocol Container { - var circles: [Circle]? { get set } - var ellipses: [Ellipse]? { get set } - var groups: [Group]? { get set } - var lines: [Line]? { get set } - var paths: [Path]? { get set } - var polygons: [Polygon]? { get set } - var polylines: [Polyline]? { get set } - var rectangles: [Rectangle]? { get set } - var texts: [Text]? { get set } -} - -enum ContainerKeys: String, CodingKey { - case circles = "circle" - case ellipses = "ellipse" - case groups = "g" - case lines = "line" - case paths = "path" - case polylines = "polyline" - case polygons = "polygon" - case rectangles = "rect" - case texts = "text" -} - -public extension Container { - var containerDescription: String { - var contents: String = "" - - let circles = circles?.compactMap(\.description) ?? [] - circles.forEach { contents.append("\n\($0)") } - - let ellipses = ellipses?.compactMap(\.description) ?? [] - ellipses.forEach { contents.append("\n\($0)") } - - let groups = groups?.compactMap(\.description) ?? [] - groups.forEach { contents.append("\n\($0)") } - - let lines = lines?.compactMap(\.description) ?? [] - lines.forEach { contents.append("\n\($0)") } - - let paths = paths?.compactMap(\.description) ?? [] - paths.forEach { contents.append("\n\($0)") } - - let polylines = polylines?.compactMap(\.description) ?? [] - polylines.forEach { contents.append("\n\($0)") } - - let polygons = polygons?.compactMap(\.description) ?? [] - polygons.forEach { contents.append("\n\($0)") } - - let rectangles = rectangles?.compactMap(\.description) ?? [] - rectangles.forEach { contents.append("\n\($0)") } - - let texts = texts?.compactMap(\.description) ?? [] - texts.forEach { contents.append("\n\($0)") } - - return contents - } -} diff --git a/third-party/SwiftSVG/Sources/CoreAttributes.swift b/third-party/SwiftSVG/Sources/CoreAttributes.swift deleted file mode 100644 index df93043baa..0000000000 --- a/third-party/SwiftSVG/Sources/CoreAttributes.swift +++ /dev/null @@ -1,17 +0,0 @@ -public protocol CoreAttributes { - var id: String? { get set } -} - -enum CoreAttributesKeys: String, CodingKey { - case id -} - -public extension CoreAttributes { - var coreDescription: String { - if let id { - "\(CoreAttributesKeys.id.rawValue)=\"\(id)\"" - } else { - "" - } - } -} diff --git a/third-party/SwiftSVG/Sources/Element.swift b/third-party/SwiftSVG/Sources/Element.swift deleted file mode 100644 index d9a612ef8e..0000000000 --- a/third-party/SwiftSVG/Sources/Element.swift +++ /dev/null @@ -1,46 +0,0 @@ -public protocol Element: CoreAttributes, PresentationAttributes, StylingAttributes {} - -public extension Element { - var attributeDescription: String { - var components: [String] = [] - - if !coreDescription.isEmpty { - components.append(coreDescription) - } - if !presentationDescription.isEmpty { - components.append(presentationDescription) - } - if !stylingDescription.isEmpty { - components.append(stylingDescription) - } - - return components.joined(separator: " ") - } -} - -public extension CommandRepresentable where Self: Element { - /// When a `Path` is accessed on an element, the path that is returned should have the supplied transformations - /// applied. - /// - /// For instance, if - /// * a `Path.data` contains relative elements, - /// * and `transformations` contains a `.translate` - /// - /// Than the path created will not only use 'absolute' instructions, but those instructions will be modified to - /// include the required transformation. - func path(applying transformations: [Transformation] = []) throws -> Path { - var _transformations = transformations - _transformations.append(contentsOf: self.transformations) - - let commands = try commands().map { $0.applying(transformations: _transformations) } - - var path = Path(commands: commands) - path.fillColor = fillColor - path.fillOpacity = fillOpacity - path.strokeColor = strokeColor - path.strokeOpacity = strokeOpacity - path.strokeWidth = strokeWidth - - return path - } -} diff --git a/third-party/SwiftSVG/Sources/Ellipse.swift b/third-party/SwiftSVG/Sources/Ellipse.swift deleted file mode 100644 index bbabf36e61..0000000000 --- a/third-party/SwiftSVG/Sources/Ellipse.swift +++ /dev/null @@ -1,93 +0,0 @@ -import Swift2D -import XMLCoder - -/// SVG basic shape, used to create ellipses based on a center coordinate, and both their x and y radius. -/// -/// The arc of an ‘ellipse’ element begins at the "3 o'clock" point on the radius and progresses towards the -/// "9 o'clock" point. The starting point and direction of the arc are affected by the user space transform in the same -/// manner as the geometry of the element. -public struct Ellipse: Element { - - /// The x position of the ellipse. - public var x: Double = 0.0 - /// The y position of the ellipse. - public var y: Double = 0.0 - /// The radius of the ellipse on the x axis. - public var rx: Double = 0.0 - /// The radius of the ellipse on the y axis. - public var ry: Double = 0.0 - - // MARK: CoreAttributes - - public var id: String? - - // MARK: PresentationAttributes - - public var fillColor: String? - public var fillOpacity: Double? - public var fillRule: Fill.Rule? - public var strokeColor: String? - public var strokeWidth: Double? - public var strokeOpacity: Double? - public var strokeLineCap: Stroke.LineCap? - public var strokeLineJoin: Stroke.LineJoin? - public var strokeMiterLimit: Double? - public var transform: String? - - // MARK: StylingAttributes - - public var style: String? - - enum CodingKeys: String, CodingKey { - case x = "cx" - case y = "cy" - case rx - case ry - case id - case fillColor = "fill" - case fillOpacity = "fill-opacity" - case fillRule = "fill-rule" - case strokeColor = "stroke" - case strokeWidth = "stroke-width" - case strokeOpacity = "stroke-opacity" - case strokeLineCap = "stroke-linecap" - case strokeLineJoin = "stroke-linejoin" - case strokeMiterLimit = "stroke-miterlimit" - case transform - case style - } - - public init() {} - - public init(x: Double, y: Double, rx: Double, ry: Double) { - self.x = x - self.y = y - self.rx = rx - self.ry = ry - } -} - -extension Ellipse: CustomStringConvertible { - public var description: String { - let desc = "" - } -} - -extension Ellipse: DirectionalCommandRepresentable { - public func commands(clockwise: Bool) throws -> [Path.Command] { - EllipseProcessor(ellipse: self).commands(clockwise: clockwise) - } -} - -extension Ellipse: DynamicNodeDecoding { - public static func nodeDecoding(for key: any CodingKey) -> XMLDecoder.NodeDecoding { - .attribute - } -} - -extension Ellipse: DynamicNodeEncoding { - public static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { - .attribute - } -} diff --git a/third-party/SwiftSVG/Sources/Extensions/Point+SwiftSVG.swift b/third-party/SwiftSVG/Sources/Extensions/Point+SwiftSVG.swift deleted file mode 100644 index 0c789bcae3..0000000000 --- a/third-party/SwiftSVG/Sources/Extensions/Point+SwiftSVG.swift +++ /dev/null @@ -1,37 +0,0 @@ -import Swift2D - -extension Point { - static var nan: Point { - Point(x: Double.nan, y: Double.nan) - } - - var hasNaN: Bool { - x.isNaN || y.isNaN - } - - /// Returns a copy of the instance with the **x** value replaced with the provided value. - func with(x value: Double) -> Point { - Point(x: value, y: y) - } - - /// Returns a copy of the instance with the **y** value replaced with the provided value. - func with(y value: Double) -> Point { - Point(x: x, y: value) - } - - /// Adjusts the **x** value by the provided amount. - /// - /// This will explicitly check for `.isNaN`, and if encountered, will simply - /// use the provided value. - func adjusting(x value: Double) -> Point { - (x.isNaN) ? with(x: value) : with(x: x + value) - } - - /// Adjusts the **y** value by the provided amount. - /// - /// This will explicitly check for `.isNaN`, and if encountered, will simply - /// use the provided value. - func adjusting(y value: Double) -> Point { - (y.isNaN) ? with(y: value) : with(y: y + value) - } -} diff --git a/third-party/SwiftSVG/Sources/Fill.swift b/third-party/SwiftSVG/Sources/Fill.swift deleted file mode 100644 index 608192aa29..0000000000 --- a/third-party/SwiftSVG/Sources/Fill.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Swift2D - -public struct Fill { - - public var color: String? - public var opacity: Double? - public var rule: Rule = .nonZero - - public init() {} - - /// Presentation attribute defining the algorithm to use to determine the inside part of a shape. - /// - /// The default `Rule` is `.nonzero`. - public enum Rule: String, Sendable, Codable, CaseIterable { - /// The value evenodd determines the "insideness" of a point in the shape by drawing a ray from that point to - /// infinity in any direction and counting the number of path segments from the given shape that the ray - /// crosses. If this number is odd, the point is inside; if even, the point is outside. - case evenOdd = "evenodd" - /// The value nonzero determines the "insideness" of a point in the shape by drawing a ray from that point to - /// infinity in any direction, and then examining the places where a segment of the shape crosses the ray. - /// Starting with a count of zero, add one each time a path segment crosses the ray from left to right and - /// subtract one each time a path segment crosses the ray from right to left. After counting the crossings, if - /// the result is zero then the point is outside the path. Otherwise, it is inside. - case nonZero = "nonzero" - - public init(from decoder: any Decoder) throws { - let container = try decoder.singleValueContainer() - let rawValue = try container.decode(String.self) - guard let rule = Rule(rawValue: rawValue) else { - print("Attempts to decode Fill.Rule with rawValue: '\(rawValue)'") - self = .nonZero - return - } - - self = rule - } - } -} - -extension Fill.Rule: CustomStringConvertible { - public var description: String { - rawValue - } -} diff --git a/third-party/SwiftSVG/Sources/Group.swift b/third-party/SwiftSVG/Sources/Group.swift deleted file mode 100644 index c95d2d0ad5..0000000000 --- a/third-party/SwiftSVG/Sources/Group.swift +++ /dev/null @@ -1,152 +0,0 @@ -import XMLCoder - -/// A container used to group other SVG elements. -/// -/// Grouping constructs, when used in conjunction with the ‘desc’ and ‘title’ elements, provide information -/// about document structure and semantics. -/// -/// ## Documentation -/// [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g) -/// | [W3](https://www.w3.org/TR/SVG11/struct.html#Groups) -public struct Group: Container, Element { - - // Container - public var circles: [Circle]? - public var ellipses: [Ellipse]? - public var groups: [Group]? - public var lines: [Line]? - public var paths: [Path]? - public var polygons: [Polygon]? - public var polylines: [Polyline]? - public var rectangles: [Rectangle]? - public var texts: [Text]? - - // MARK: CoreAttributes - - public var id: String? - public var title: String? - public var desc: String? - - // MARK: PresentationAttributes - - public var fillColor: String? - public var fillOpacity: Double? - public var fillRule: Fill.Rule? - public var strokeColor: String? - public var strokeWidth: Double? - public var strokeOpacity: Double? - public var strokeLineCap: Stroke.LineCap? - public var strokeLineJoin: Stroke.LineJoin? - public var strokeMiterLimit: Double? - public var transform: String? - - // MARK: StylingAttributes - - public var style: String? - - enum CodingKeys: String, CodingKey { - case circles = "circle" - case ellipses = "ellipse" - case groups = "g" - case lines = "line" - case paths = "path" - case polylines = "polyline" - case polygons = "polygon" - case rectangles = "rect" - case texts = "text" - case id - case title - case desc - case fillColor = "fill" - case fillOpacity = "fill-opacity" - case fillRule = "fill-rule" - case strokeColor = "stroke" - case strokeWidth = "stroke-width" - case strokeOpacity = "stroke-opacity" - case strokeLineCap = "stroke-linecap" - case strokeLineJoin = "stroke-linejoin" - case strokeMiterLimit = "stroke-miterlimit" - case transform - case style - } - - public init() {} - - /// A representation of all the sub-`Path`s in the `Group`. - public func subpaths(applying transformations: [Transformation] = []) throws -> [Path] { - var _transformations = transformations - _transformations.append(contentsOf: self.transformations) - - var output: [Path] = [] - - if let circles { - try output.append(contentsOf: circles.compactMap { try $0.path(applying: _transformations) }) - } - - if let ellipses { - try output.append(contentsOf: ellipses.compactMap { try $0.path(applying: _transformations) }) - } - - if let rectangles { - try output.append(contentsOf: rectangles.compactMap { try $0.path(applying: _transformations) }) - } - - if let polygons { - try output.append(contentsOf: polygons.compactMap { try $0.path(applying: _transformations) }) - } - - if let polylines { - try output.append(contentsOf: polylines.compactMap { try $0.path(applying: _transformations) }) - } - - if let paths { - try output.append(contentsOf: paths.map { try $0.path(applying: _transformations) }) - } - - if let groups { - try groups.forEach { - try output.append(contentsOf: $0.subpaths(applying: _transformations)) - } - } - - return output - } -} - -extension Group: CustomStringConvertible { - public var description: String { - var contents: String = "" - - if let title { - contents.append("\n\(title)") - } - - if let desc { - contents.append("\n\(desc)") - } - - contents.append(containerDescription) - - return "\(contents)\n" - } -} - -extension Group: DynamicNodeDecoding { - public static func nodeDecoding(for key: any CodingKey) -> XMLDecoder.NodeDecoding { - if let _ = ContainerKeys(stringValue: key.stringValue) { - return .element - } - - return .attribute - } -} - -extension Group: DynamicNodeEncoding { - public static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { - if let _ = ContainerKeys(stringValue: key.stringValue) { - return .element - } - - return .attribute - } -} diff --git a/third-party/SwiftSVG/Sources/Internal/EllipseProcessor.swift b/third-party/SwiftSVG/Sources/Internal/EllipseProcessor.swift deleted file mode 100644 index 409c2a7163..0000000000 --- a/third-party/SwiftSVG/Sources/Internal/EllipseProcessor.swift +++ /dev/null @@ -1,88 +0,0 @@ -import Foundation -import Swift2D - -struct EllipseProcessor { - - let x: Double - let y: Double - let rx: Double - let ry: Double - - /// The _optimal_ offset for control points when representing a - /// circle/ellipse as 4 bezier curves. - /// - /// [Stack Overflow](https://stackoverflow.com/questions/1734745/how-to-create-circle-with-bézier-curves) - static func controlPointOffset(_ radius: Double) -> Double { - (Double(4.0 / 3.0) * tan(Double.pi / 8.0)) * radius - } - - init(ellipse: Ellipse) { - x = ellipse.x - y = ellipse.y - rx = ellipse.rx - ry = ellipse.ry - } - - init(circle: Circle) { - x = circle.x - y = circle.y - rx = circle.r - ry = circle.r - } - - func commands(clockwise: Bool) -> [Path.Command] { - var commands: [Path.Command] = [] - - let xOffset = Self.controlPointOffset(rx) - let yOffset = Self.controlPointOffset(ry) - - let zero = Point(x: x + rx, y: y) - let ninety = Point(x: x, y: y - ry) - let oneEighty = Point(x: x - rx, y: y) - let twoSeventy = Point(x: x, y: y + ry) - - var cp1: Point = .zero - var cp2: Point = .zero - - // Starting at degree 0 (the right most point) - commands.append(.moveTo(point: zero)) - - if clockwise { - cp1 = Point(x: zero.x, y: zero.y + yOffset) - cp2 = Point(x: twoSeventy.x + xOffset, y: twoSeventy.y) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: twoSeventy)) - - cp1 = Point(x: twoSeventy.x - xOffset, y: twoSeventy.y) - cp2 = Point(x: oneEighty.x, y: oneEighty.y + yOffset) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: oneEighty)) - - cp1 = Point(x: oneEighty.x, y: oneEighty.y - yOffset) - cp2 = Point(x: ninety.x - xOffset, y: ninety.y) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: ninety)) - - cp1 = Point(x: ninety.x + xOffset, y: ninety.y) - cp2 = Point(x: zero.x, y: zero.y - yOffset) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: zero)) - } else { - cp1 = Point(x: zero.x, y: zero.y - yOffset) - cp2 = Point(x: ninety.x + xOffset, y: ninety.y) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: ninety)) - - cp1 = Point(x: ninety.x - xOffset, y: ninety.y) - cp2 = Point(x: oneEighty.x, y: oneEighty.y - yOffset) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: oneEighty)) - - cp1 = Point(x: oneEighty.x, y: oneEighty.y + yOffset) - cp2 = Point(x: twoSeventy.x - xOffset, y: twoSeventy.y) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: twoSeventy)) - - cp1 = Point(x: twoSeventy.x + xOffset, y: twoSeventy.y) - cp2 = Point(x: zero.x, y: zero.y + yOffset) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: zero)) - } - - commands.append(.closePath) - - return commands - } -} diff --git a/third-party/SwiftSVG/Sources/Internal/PathProcessor.swift b/third-party/SwiftSVG/Sources/Internal/PathProcessor.swift deleted file mode 100644 index 25c808c4d7..0000000000 --- a/third-party/SwiftSVG/Sources/Internal/PathProcessor.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Foundation - -struct PathProcessor { - - let data: String - - func commands() throws -> [Path.Command] { - let parser = Path.ComponentParser() - let components = try Path.Component.components(from: data) - return try parser.parse(components) - } -} diff --git a/third-party/SwiftSVG/Sources/Internal/PolygonProcressor.swift b/third-party/SwiftSVG/Sources/Internal/PolygonProcressor.swift deleted file mode 100644 index d05ab1a408..0000000000 --- a/third-party/SwiftSVG/Sources/Internal/PolygonProcressor.swift +++ /dev/null @@ -1,52 +0,0 @@ -import Foundation -import Swift2D - -struct PolygonProcessor { - - let points: String - - func commands() throws -> [Path.Command] { - let pairs = points.components(separatedBy: " ") - let components = pairs.flatMap { $0.components(separatedBy: ",") } - guard components.count > 0 else { - return [] - } - - guard components.count % 2 == 0 else { - // An odd number of components means that parsing probably failed - return [] - } - - var commands: [Path.Command] = [] - - var firstValue: Bool = true - for (idx, component) in components.enumerated() { - guard let _value = Double(component) else { - return commands - } - - let value = Double(_value) - - if firstValue { - if idx == 0 { - commands.append(.moveTo(point: Point(x: value, y: .nan))) - } else { - commands.append(.lineTo(point: Point(x: value, y: .nan))) - } - firstValue = false - } else { - let count = commands.count - guard let modified = try? commands.last?.adjustingArgument(at: 1, by: value) else { - return commands - } - - commands[count - 1] = modified - firstValue = true - } - } - - commands.append(.closePath) - - return commands - } -} diff --git a/third-party/SwiftSVG/Sources/Internal/PolylineProcessor.swift b/third-party/SwiftSVG/Sources/Internal/PolylineProcessor.swift deleted file mode 100644 index a909c4ed3f..0000000000 --- a/third-party/SwiftSVG/Sources/Internal/PolylineProcessor.swift +++ /dev/null @@ -1,54 +0,0 @@ -import Foundation -import Swift2D - -struct PolylineProcessor { - - let points: String - - func commands() throws -> [Path.Command] { - let pairs = points.components(separatedBy: " ") - let components = pairs.flatMap { $0.components(separatedBy: ",") } - let values = components.compactMap { Double($0) }.map { Double($0) } - - guard values.count > 2 else { - // More than just a starting point is required. - return [] - } - - guard values.count % 2 == 0 else { - // An odd number of components means that parsing probably failed - return [] - } - - var commands: [Path.Command] = [] - - let move = values.prefix(upTo: 2) - let segments = values.suffix(from: 2) - - commands.append(.moveTo(point: Point(x: move[0], y: move[1]))) - - var _value: Double = .nan - for value in segments { - if _value.isNaN { - _value = value - } else { - commands.append(.lineTo(point: Point(x: _value, y: value))) - _value = .nan - } - } - - let reversedSegments = segments.dropLast(2).reversed() - for value in reversedSegments { - if _value.isNaN { - _value = value - } else { - commands.append(.lineTo(point: Point(x: _value, y: value))) - _value = .nan - } - } - - commands.append(.closePath) - - return commands - } -} diff --git a/third-party/SwiftSVG/Sources/Internal/RectangleProcessor.swift b/third-party/SwiftSVG/Sources/Internal/RectangleProcessor.swift deleted file mode 100644 index 2b93440834..0000000000 --- a/third-party/SwiftSVG/Sources/Internal/RectangleProcessor.swift +++ /dev/null @@ -1,175 +0,0 @@ -import Swift2D - -struct RectangleProcessor { - - let rectangle: Rectangle - - func commands(clockwise: Bool) -> [Path.Command] { - var rx = rectangle.rx - var ry = rectangle.ry - - if let _rx = rx, _rx > (rectangle.width / 2.0) { - rx = rectangle.width / 2.0 - } - - if let _ry = ry, _ry > (rectangle.height / 2.0) { - ry = rectangle.height / 2.0 - } - - var commands: [Path.Command] = [] - - switch (rx, ry) { - case (.some(let radiusX), .some(let radiusY)) where radiusX != radiusY: - // Use Cubic Bezier Curve to form rounded corners - // TODO: Verify that the control points are right - - var cp1: Point = .zero - var cp2: Point = .zero - var point: Point = Point(x: rectangle.x + radiusX, y: rectangle.y) - - commands.append(.moveTo(point: point)) - - if clockwise { - point = .init(x: rectangle.x + rectangle.width - radiusX, y: rectangle.y) - commands.append(.lineTo(point: point)) - - cp1 = .init(x: rectangle.x + rectangle.width, y: rectangle.y) - cp2 = cp1 - point = .init(x: rectangle.x + rectangle.width, y: rectangle.y + radiusY) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: point)) - - point = .init(x: rectangle.x + rectangle.width, y: rectangle.y + rectangle.height - radiusY) - commands.append(.lineTo(point: point)) - - cp1 = .init(x: rectangle.x + rectangle.width, y: rectangle.y + rectangle.height) - cp2 = cp1 - point = .init(x: rectangle.x + rectangle.width - radiusX, y: rectangle.y + rectangle.height) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: point)) - - point = .init(x: rectangle.x + radiusX, y: rectangle.y + rectangle.height) - commands.append(.lineTo(point: point)) - - cp1 = .init(x: rectangle.x, y: rectangle.y + rectangle.height) - cp2 = cp1 - point = .init(x: rectangle.x, y: rectangle.y + rectangle.height - radiusY) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: point)) - - point = .init(x: rectangle.x, y: rectangle.y + radiusY) - commands.append(.lineTo(point: point)) - - cp1 = .init(x: rectangle.x, y: rectangle.y) - cp2 = cp1 - point = .init(x: rectangle.x + radiusX, y: rectangle.y) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: point)) - } else { - cp1 = .init(x: rectangle.x, y: rectangle.y) - cp2 = cp1 - point = .init(x: rectangle.x, y: rectangle.y + radiusY) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: point)) - - point = .init(x: rectangle.x, y: rectangle.y + rectangle.height - radiusY) - commands.append(.lineTo(point: point)) - - cp1 = .init(x: rectangle.x, y: rectangle.y + rectangle.height) - cp2 = cp1 - point = .init(x: rectangle.x + radiusX, y: rectangle.y + rectangle.height) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: point)) - - point = .init(x: rectangle.x + rectangle.width - radiusX, y: rectangle.y + rectangle.height) - commands.append(.lineTo(point: point)) - - cp1 = .init(x: rectangle.x + rectangle.width, y: rectangle.y + rectangle.height) - cp2 = cp1 - point = .init(x: rectangle.x + rectangle.width, y: rectangle.y + rectangle.height - radiusY) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: point)) - - point = .init(x: rectangle.x + rectangle.width, y: rectangle.y + radiusY) - commands.append(.lineTo(point: point)) - - cp1 = .init(x: rectangle.x + rectangle.width, y: rectangle.y) - cp2 = cp1 - point = .init(x: rectangle.x + rectangle.width - radiusX, y: rectangle.y) - commands.append(.cubicBezierCurve(cp1: cp1, cp2: cp2, point: point)) - } - case (.some(let radius), .none), (.none, .some(let radius)), (.some(let radius), _): - // use Quadratic Bezier Curve to form rounded corners - - var cp: Point = .zero - var point: Point = Point(x: rectangle.x + radius, y: rectangle.y) - - commands.append(.moveTo(point: point)) - - if clockwise { - point = .init(x: (rectangle.x + rectangle.width) - radius, y: rectangle.y) - commands.append(.lineTo(point: point)) - - cp = .init(x: rectangle.x + rectangle.width, y: rectangle.y) - point = .init(x: rectangle.x + rectangle.width, y: rectangle.y + radius) - commands.append(.quadraticBezierCurve(cp: cp, point: point)) - - point = .init(x: rectangle.x + rectangle.width, y: (rectangle.y + rectangle.height) - radius) - commands.append(.lineTo(point: point)) - - cp = .init(x: rectangle.x + rectangle.width, y: rectangle.y + rectangle.height) - point = .init(x: rectangle.x + rectangle.width - radius, y: rectangle.y + rectangle.height) - commands.append(.quadraticBezierCurve(cp: cp, point: point)) - - point = .init(x: rectangle.x + radius, y: rectangle.y + rectangle.height) - commands.append(.lineTo(point: point)) - - cp = .init(x: rectangle.x, y: rectangle.y + rectangle.height) - point = .init(x: rectangle.x, y: rectangle.y + rectangle.height - radius) - commands.append(.quadraticBezierCurve(cp: cp, point: point)) - - point = .init(x: rectangle.x, y: rectangle.y + radius) - commands.append(.lineTo(point: point)) - - cp = .init(x: rectangle.x, y: rectangle.y) - point = .init(x: rectangle.x + radius, y: rectangle.y) - commands.append(.quadraticBezierCurve(cp: cp, point: point)) - } else { - cp = .init(x: rectangle.x, y: rectangle.y) - point = .init(x: rectangle.x, y: rectangle.y + radius) - commands.append(.quadraticBezierCurve(cp: cp, point: point)) - - point = .init(x: rectangle.x, y: rectangle.y + rectangle.height - radius) - commands.append(.lineTo(point: point)) - - cp = .init(x: rectangle.x, y: rectangle.y + rectangle.height) - point = .init(x: rectangle.x + radius, y: rectangle.y + rectangle.height) - commands.append(.quadraticBezierCurve(cp: cp, point: point)) - - point = .init(x: rectangle.x + rectangle.width - radius, y: rectangle.y + rectangle.height) - commands.append(.lineTo(point: point)) - - cp = .init(x: rectangle.x + rectangle.width, y: rectangle.y + rectangle.height) - point = .init(x: rectangle.x + rectangle.width, y: rectangle.y + rectangle.height - radius) - commands.append(.quadraticBezierCurve(cp: cp, point: point)) - - point = .init(x: rectangle.x + rectangle.width, y: rectangle.y + radius) - commands.append(.lineTo(point: point)) - - cp = .init(x: rectangle.x + rectangle.width, y: rectangle.y) - point = .init(x: rectangle.x + rectangle.width - radius, y: rectangle.y) - commands.append(.quadraticBezierCurve(cp: cp, point: point)) - } - case (.none, .none): - // draw three line segments. - commands.append(.moveTo(point: Point(x: rectangle.x, y: rectangle.y))) - - if clockwise { - commands.append(.lineTo(point: Point(x: rectangle.x + rectangle.width, y: rectangle.y))) - commands.append(.lineTo(point: Point(x: rectangle.x + rectangle.width, y: rectangle.y + rectangle.height))) - commands.append(.lineTo(point: Point(x: rectangle.x, y: rectangle.y + rectangle.height))) - } else { - commands.append(.lineTo(point: Point(x: rectangle.x, y: rectangle.y + rectangle.height))) - commands.append(.lineTo(point: Point(x: rectangle.x + rectangle.width, y: rectangle.y + rectangle.height))) - commands.append(.lineTo(point: Point(x: rectangle.x + rectangle.width, y: rectangle.y))) - } - } - - commands.append(.closePath) - - return commands - } -} diff --git a/third-party/SwiftSVG/Sources/Line.swift b/third-party/SwiftSVG/Sources/Line.swift deleted file mode 100644 index 08ee77488f..0000000000 --- a/third-party/SwiftSVG/Sources/Line.swift +++ /dev/null @@ -1,98 +0,0 @@ -import Swift2D -import XMLCoder - -/// SVG basic shape used to create a line connecting two points. -/// -/// ## Documentation -/// [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line) -/// | [W3](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line) -public struct Line: Element { - - /// Defines the x-axis coordinate of the line starting point. - public var x1: Double = 0.0 - /// Defines the x-axis coordinate of the line ending point. - public var y1: Double = 0.0 - /// Defines the y-axis coordinate of the line starting point. - public var x2: Double = 0.0 - /// Defines the y-axis coordinate of the line ending point. - public var y2: Double = 0.0 - - // MARK: CoreAttributes - - public var id: String? - - // MARK: PresentationAttributes - - public var fillColor: String? - public var fillOpacity: Double? - public var fillRule: Fill.Rule? - public var strokeColor: String? - public var strokeWidth: Double? - public var strokeOpacity: Double? - public var strokeLineCap: Stroke.LineCap? - public var strokeLineJoin: Stroke.LineJoin? - public var strokeMiterLimit: Double? - public var transform: String? - - // MARK: StylingAttributes - - public var style: String? - - enum CodingKeys: String, CodingKey { - case x1 - case y1 - case x2 - case y2 - case id - case fillColor = "fill" - case fillOpacity = "fill-opacity" - case fillRule = "fill-rule" - case strokeColor = "stroke" - case strokeWidth = "stroke-width" - case strokeOpacity = "stroke-opacity" - case strokeLineCap = "stroke-linecap" - case strokeLineJoin = "stroke-linejoin" - case strokeMiterLimit = "stroke-miterlimit" - case transform - case style - } - - public init() {} - - public init(x1: Double, y1: Double, x2: Double, y2: Double) { - self.x1 = x1 - self.y1 = y1 - self.x2 = x2 - self.y2 = y2 - } -} - -extension Line: CommandRepresentable { - public func commands() throws -> [Path.Command] { - [ - .moveTo(point: Point(x: x1, y: y1)), - .lineTo(point: Point(x: x2, y: y2)), - .lineTo(point: Point(x: x1, y: y1)), - .closePath, - ] - } -} - -extension Line: CustomStringConvertible { - public var description: String { - let desc = "" - } -} - -extension Line: DynamicNodeDecoding { - public static func nodeDecoding(for key: any CodingKey) -> XMLDecoder.NodeDecoding { - .attribute - } -} - -extension Line: DynamicNodeEncoding { - public static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { - .attribute - } -} diff --git a/third-party/SwiftSVG/Sources/Path.Command.swift b/third-party/SwiftSVG/Sources/Path.Command.swift deleted file mode 100644 index e0fb49a729..0000000000 --- a/third-party/SwiftSVG/Sources/Path.Command.swift +++ /dev/null @@ -1,276 +0,0 @@ -import Foundation -import Swift2D - -public extension Path { - /// Path commands are instructions that define a path to be drawn. - /// - /// Each command is composed of a command letter and numbers that represent the command parameters. - enum Command: Equatable, Sendable, CustomStringConvertible { - /// Moves the current drawing point - case moveTo(point: Point) - /// Draw a straight line from the current point to the point provided - case lineTo(point: Point) - /// Draw a smooth curve using three points (+ origin) - case cubicBezierCurve(cp1: Point, cp2: Point, point: Point) - /// Draw a smooth curve using two points (+ origin) - case quadraticBezierCurve(cp: Point, point: Point) - /// Draw a curve defined as a portion of an ellipse - case ellipticalArcCurve(rx: Double, ry: Double, angle: Double, largeArc: Bool, clockwise: Bool, point: Point) - /// ClosePath instructions draw a straight line from the current position to the first point in the path. - case closePath - - public enum Prefix: Character, CaseIterable { - case move = "M" - case relativeMove = "m" - case line = "L" - case relativeLine = "l" - case horizontalLine = "H" - case relativeHorizontalLine = "h" - case verticalLine = "V" - case relativeVerticalLine = "v" - case cubicBezierCurve = "C" - case relativeCubicBezierCurve = "c" - case smoothCubicBezierCurve = "S" - case relativeSmoothCubicBezierCurve = "s" - case quadraticBezierCurve = "Q" - case relativeQuadraticBezierCurve = "q" - case smoothQuadraticBezierCurve = "T" - case relativeSmoothQuadraticBezierCurve = "t" - case ellipticalArcCurve = "A" - case relativeEllipticalArcCurve = "a" - case close = "Z" - case relativeClose = "z" - - public static var characterSet: CharacterSet { - CharacterSet(charactersIn: allCases.map { String($0.rawValue) }.joined()) - } - } - - public enum Coordinates { - case absolute - case relative - } - - public enum Error: Swift.Error { - case message(String) - case invalidAdjustment(Path.Command) - case invalidArgumentPosition(Int, Path.Command) - case invalidRelativeCommand - } - - public var description: String { - switch self { - case .moveTo(let point): - return "\(Prefix.move.rawValue)\(point.x),\(point.y)" - case .lineTo(let point): - return "\(Prefix.line.rawValue)\(point.x),\(point.y)" - case .cubicBezierCurve(let cp1, let cp2, let point): - return "\(Prefix.cubicBezierCurve.rawValue)\(cp1.x),\(cp1.y) \(cp2.x),\(cp2.y) \(point.x),\(point.y)" - case .quadraticBezierCurve(let cp, let point): - return "\(Prefix.quadraticBezierCurve.rawValue)\(cp.x),\(cp.y) \(point.x),\(point.y)" - case .ellipticalArcCurve(let rx, let ry, let angle, let largeArc, let clockwise, let point): - let la = largeArc ? 1 : 0 - let cw = clockwise ? 1 : 0 - return "\(Prefix.ellipticalArcCurve.rawValue)\(rx) \(ry) \(angle) \(la) \(cw) \(point.x) \(point.y)" - case .closePath: - return "\(Prefix.close.rawValue)" - } - } - - /// The primary point that dictates the commands action. - public var point: Point { - switch self { - case .moveTo(let point): point - case .lineTo(let point): point - case .cubicBezierCurve(_, _, let point): point - case .quadraticBezierCurve(_, let point): point - case .ellipticalArcCurve(_, _, _, _, _, let point): point - case .closePath: .zero - } - } - } -} - -public extension Path.Command { - /// Applies the provided `Transformation` to the instances values. - func applying(transformation: Transformation) -> Path.Command { - switch transformation { - case .translate(let x, let y): - switch self { - case .moveTo(let point): - let _point = point.adjusting(x: x).adjusting(y: y) - return .moveTo(point: _point) - case .lineTo(let point): - let _point = point.adjusting(x: x).adjusting(y: y) - return .lineTo(point: _point) - case .cubicBezierCurve(let cp1, let cp2, let point): - let _cp1 = cp1.adjusting(x: x).adjusting(y: y) - let _cp2 = cp2.adjusting(x: x).adjusting(y: y) - let _point = point.adjusting(x: x).adjusting(y: y) - return .cubicBezierCurve(cp1: _cp1, cp2: _cp2, point: _point) - case .quadraticBezierCurve(let cp, let point): - let _cp = cp.adjusting(x: x).adjusting(y: y) - let _point = point.adjusting(x: x).adjusting(y: y) - return .quadraticBezierCurve(cp: _cp, point: _point) - case .ellipticalArcCurve(let rx, let ry, let angle, let largeArc, let clockwise, let point): - let _point = point.adjusting(x: x).adjusting(y: y) - return .ellipticalArcCurve(rx: rx, ry: ry, angle: angle, largeArc: largeArc, clockwise: clockwise, point: _point) - case .closePath: - return self - } - case .matrix: - // TODO: What should occur here? - return self - } - } - - /// Applies multiple transformations in the order they are specified. - func applying(transformations: [Transformation]) -> Path.Command { - var command = self - - for transformation in transformations { - command = command.applying(transformation: transformation) - } - - return command - } -} - -extension Path.Command { - /// Determines if all values are provided (i.e. !.isNaN) - var isComplete: Bool { - switch self { - case .moveTo(let point), .lineTo(let point): - !point.hasNaN - case .cubicBezierCurve(let cp1, let cp2, let point): - !cp1.hasNaN && !cp2.hasNaN && !point.hasNaN - case .quadraticBezierCurve(let cp, let point): - !cp.hasNaN && !point.hasNaN - case .ellipticalArcCurve(let rx, let ry, let angle, _, _, let point): - !rx.isNaN && !ry.isNaN && !angle.isNaN && !point.hasNaN - case .closePath: - true - } - } - - /// The last control point used in drawing the path. - /// - /// Only valid for curves. - var lastControlPoint: Point? { - switch self { - case .cubicBezierCurve(_, let cp2, _): - cp2 - case .quadraticBezierCurve(let cp, _): - cp - default: - nil - } - } - - /// A mirror representation of `lastControlPoint`. - var lastControlPointMirror: Point? { - guard let cp = lastControlPoint else { - return nil - } - - return Point(x: point.x + (point.x - cp.x), y: point.y + (point.y - cp.y)) - } - - /// The total number of argument values the command requires. - var arguments: Int { - switch self { - case .moveTo: 2 - case .lineTo: 2 - case .cubicBezierCurve: 6 - case .quadraticBezierCurve: 4 - case .ellipticalArcCurve: 7 - case .closePath: 0 - } - } - - /// Adjusts a Command argument by a specified amount. - /// - /// A `Point` consumes two positions. So, in the example `.quadraticBezierCurve(cp: .zero, point: .zero)`: - /// * position 0 = Control Point X - /// * position 1 = Control Point Y - /// * position 2 = Point X - /// * position 3 = Point Y - /// - /// - parameter position: The index of the argument parameter to adjust. - /// - parameter value: The value to add to the existing value. If the current value equal `.isNaN`, than the - /// supplied value is used as-is. - /// - throws: `Path.Command.Error` - func adjustingArgument(at position: Int, by value: Double) throws -> Path.Command { - switch self { - case .moveTo(let point): - switch position { - case 0: - return .moveTo(point: point.adjusting(x: value)) - case 1: - return .moveTo(point: point.adjusting(y: value)) - default: - throw Path.Command.Error.invalidArgumentPosition(position, self) - } - case .lineTo(let point): - switch position { - case 0: - return .lineTo(point: point.adjusting(x: value)) - case 1: - return .lineTo(point: point.adjusting(y: value)) - default: - throw Path.Command.Error.invalidArgumentPosition(position, self) - } - case .cubicBezierCurve(let cp1, let cp2, let point): - switch position { - case 0: - return .cubicBezierCurve(cp1: cp1.adjusting(x: value), cp2: cp2, point: point) - case 1: - return .cubicBezierCurve(cp1: cp1.adjusting(y: value), cp2: cp2, point: point) - case 2: - return .cubicBezierCurve(cp1: cp1, cp2: cp2.adjusting(x: value), point: point) - case 3: - return .cubicBezierCurve(cp1: cp1, cp2: cp2.adjusting(y: value), point: point) - case 4: - return .cubicBezierCurve(cp1: cp1, cp2: cp2, point: point.adjusting(x: value)) - case 5: - return .cubicBezierCurve(cp1: cp1, cp2: cp2, point: point.adjusting(y: value)) - default: - throw Path.Command.Error.invalidArgumentPosition(position, self) - } - case .quadraticBezierCurve(let cp, let point): - switch position { - case 0: - return .quadraticBezierCurve(cp: cp.adjusting(x: value), point: point) - case 1: - return .quadraticBezierCurve(cp: cp.adjusting(y: value), point: point) - case 2: - return .quadraticBezierCurve(cp: cp, point: point.adjusting(x: value)) - case 3: - return .quadraticBezierCurve(cp: cp, point: point.adjusting(y: value)) - default: - throw Path.Command.Error.invalidArgumentPosition(position, self) - } - case .ellipticalArcCurve(let rx, let ry, let angle, let largeArc, let clockwise, let point): - switch position { - case 0: - return .ellipticalArcCurve(rx: value, ry: ry, angle: angle, largeArc: largeArc, clockwise: clockwise, point: point) - case 1: - return .ellipticalArcCurve(rx: rx, ry: value, angle: angle, largeArc: largeArc, clockwise: clockwise, point: point) - case 2: - return .ellipticalArcCurve(rx: rx, ry: ry, angle: value, largeArc: largeArc, clockwise: clockwise, point: point) - case 3: - return .ellipticalArcCurve(rx: rx, ry: ry, angle: angle, largeArc: !value.isZero, clockwise: clockwise, point: point) - case 4: - return .ellipticalArcCurve(rx: rx, ry: ry, angle: angle, largeArc: largeArc, clockwise: !value.isZero, point: point) - case 5: - return .ellipticalArcCurve(rx: rx, ry: ry, angle: angle, largeArc: largeArc, clockwise: clockwise, point: point.adjusting(x: value)) - case 6: - return .ellipticalArcCurve(rx: rx, ry: ry, angle: angle, largeArc: largeArc, clockwise: clockwise, point: point.adjusting(y: value)) - default: - throw Path.Command.Error.invalidArgumentPosition(position, self) - } - case .closePath: - throw Path.Command.Error.invalidAdjustment(self) - } - } -} diff --git a/third-party/SwiftSVG/Sources/Path.Component.swift b/third-party/SwiftSVG/Sources/Path.Component.swift deleted file mode 100644 index 6c02251142..0000000000 --- a/third-party/SwiftSVG/Sources/Path.Component.swift +++ /dev/null @@ -1,98 +0,0 @@ -import Foundation - -public extension Path { - /// A unit of a SVG path data string. - enum Component { - case prefix(Command.Prefix) - case value(Double) - - /// Interprets a `Path` `data` attribute into individual `Component`s for command processing. - public static func components(from data: String) throws -> [Component] { - var blocks: [String] = [] - var block: String = "" - - for scalar in data.unicodeScalars { - if scalar == "e" { - // Account for exponential value notation. - block.append(String(scalar)) - continue - } - - if CharacterSet.letters.contains(scalar) { - if !block.isEmpty { - blocks.append(block) - block = "" - } - - blocks.append(String(scalar)) - continue - } - - if CharacterSet.whitespaces.contains(scalar) { - if !block.isEmpty { - blocks.append(block) - block = "" - } - - continue - } - - if CharacterSet(charactersIn: ",").contains(scalar) { - if !block.isEmpty { - blocks.append(block) - block = "" - } - - continue - } - - if CharacterSet(charactersIn: "-").contains(scalar) { - if !block.isEmpty, block.last != "e" { - // Again, account for exponential values. - blocks.append(block) - block = "" - } - - block.append(String(scalar)) - continue - } - - if CharacterSet(charactersIn: ".").contains(scalar) { - if block.contains(".") { - // Already decimal value, this is a new value - blocks.append(block) - block = "" - } - - block.append(String(scalar)) - continue - } - - if CharacterSet.decimalDigits.contains(scalar) { - block.append(String(scalar)) - continue - } - - print("Unhandled Character: \(scalar)") - } - - if !block.isEmpty { - blocks.append(block) - block = "" - } - - return blocks - .filter { !$0.isEmpty } - .compactMap { - if let prefix = Path.Command.Prefix(rawValue: $0.first!) { - .prefix(prefix) - } else if let value = Double($0) { - .value(value) - } else { - // throw in the future? - nil - } - } - } - } -} diff --git a/third-party/SwiftSVG/Sources/Path.ComponentParser.swift b/third-party/SwiftSVG/Sources/Path.ComponentParser.swift deleted file mode 100644 index c64c682a6b..0000000000 --- a/third-party/SwiftSVG/Sources/Path.ComponentParser.swift +++ /dev/null @@ -1,275 +0,0 @@ -import Swift2D - -public extension Path { - /// Utility used to construct a collection of `Path.Command` from a collection of `Path.Component`. - class ComponentParser { - /// The command currently being built - private var command: Path.Command? - /// Coordinate system being used - private var coordinates: Path.Command.Coordinates = .absolute - /// The argument position of the _command_ to be processed. - private var position: Int = 0 - /// Indicates that only a single value will be processed on the next component pass. - private var singleValue: Bool = false - /// The originating coordinates of the path. - private var pathOrigin: Point = .nan - /// The last point as processed by the parser. - private var currentPoint: Point = .zero - - public init() {} - - public func parse(_ components: [Path.Component]) throws -> [Path.Command] { - var commands: [Path.Command] = [] - - try components.forEach { component in - if let command = try parse(component, lastCommand: commands.last) { - commands.append(command) - } - } - - return commands - } - - private func parse(_ component: Path.Component, lastCommand: Path.Command?) throws -> Path.Command? { - switch component { - case .prefix(let prefix): - setup(prefix: prefix, lastCommand: lastCommand) - case .value(let value): - try process(value: value, lastCommand: lastCommand) - } - } - - private func setup(prefix: Path.Command.Prefix, lastCommand: Path.Command?) -> Path.Command? { - position = 0 - singleValue = false - - switch prefix { - case .move: - command = .moveTo(point: .nan) - coordinates = .absolute - case .relativeMove: - command = .moveTo(point: currentPoint) - coordinates = .relative - case .line: - command = .lineTo(point: .nan) - coordinates = .absolute - case .relativeLine: - command = .lineTo(point: currentPoint) - coordinates = .relative - case .horizontalLine: - command = .lineTo(point: currentPoint.with(x: .nan)) - coordinates = .absolute - case .relativeHorizontalLine: - command = .lineTo(point: currentPoint) - coordinates = .relative - singleValue = true - case .verticalLine: - command = .lineTo(point: currentPoint.with(y: .nan)) - coordinates = .absolute - position = 1 - case .relativeVerticalLine: - command = .lineTo(point: currentPoint) - coordinates = .relative - position = 1 - singleValue = true - case .cubicBezierCurve: - command = .cubicBezierCurve(cp1: .nan, cp2: .nan, point: .nan) - coordinates = .absolute - case .relativeCubicBezierCurve: - command = .cubicBezierCurve(cp1: currentPoint, cp2: currentPoint, point: currentPoint) - coordinates = .relative - case .smoothCubicBezierCurve: - if case .cubicBezierCurve(_, let cp, _) = lastCommand { - command = .cubicBezierCurve(cp1: cp.reflecting(around: currentPoint), cp2: .nan, point: .nan) - } else { - command = .cubicBezierCurve(cp1: currentPoint, cp2: .nan, point: .nan) - } - coordinates = .absolute - position = 2 - case .relativeSmoothCubicBezierCurve: - if case .cubicBezierCurve(_, let cp, _) = lastCommand { - command = .cubicBezierCurve(cp1: cp.reflecting(around: cp.reflecting(around: currentPoint)), cp2: currentPoint, point: currentPoint) - } else { - command = .cubicBezierCurve(cp1: currentPoint, cp2: currentPoint, point: currentPoint) - } - coordinates = .relative - position = 2 - case .quadraticBezierCurve: - command = .quadraticBezierCurve(cp: .nan, point: .nan) - coordinates = .absolute - case .relativeQuadraticBezierCurve: - command = .quadraticBezierCurve(cp: currentPoint, point: currentPoint) - coordinates = .relative - case .smoothQuadraticBezierCurve: - if case .quadraticBezierCurve(let cp, _) = lastCommand { - command = .quadraticBezierCurve(cp: cp.reflecting(around: currentPoint), point: .nan) - } else { - command = .quadraticBezierCurve(cp: currentPoint, point: .nan) - } - coordinates = .absolute - position = 2 - case .relativeSmoothQuadraticBezierCurve: - if case .quadraticBezierCurve(let cp, _) = lastCommand { - command = .quadraticBezierCurve(cp: cp.reflecting(around: currentPoint), point: currentPoint) - } else { - command = .quadraticBezierCurve(cp: currentPoint, point: currentPoint) - } - coordinates = .relative - position = 2 - case .ellipticalArcCurve: - command = .ellipticalArcCurve(rx: .nan, ry: .nan, angle: .nan, largeArc: false, clockwise: false, point: .nan) - coordinates = .absolute - case .relativeEllipticalArcCurve: - command = .ellipticalArcCurve(rx: .nan, ry: .nan, angle: .nan, largeArc: false, clockwise: false, point: currentPoint) - coordinates = .relative - case .close, .relativeClose: - currentPoint = pathOrigin - reset() - return .closePath - } - - return nil - } - - private func process(value: Double, lastCommand: Path.Command?) throws -> Path.Command? { - if let command { - try continueCommand(command, with: value) - } else { - try nextCommand(with: value, lastCommand: lastCommand) - } - - if let command, command.isComplete { - switch coordinates { - case .relative: - guard position == -1 else { - return nil - } - - fallthrough - case .absolute: - currentPoint = command.point - if case .moveTo = command { - pathOrigin = command.point - } - reset() - return command - } - } else { - return nil - } - } - - private func continueCommand(_ command: Path.Command, with value: Double) throws { - switch command { - case .moveTo, .cubicBezierCurve, .quadraticBezierCurve, .ellipticalArcCurve: - self.command = try command.adjustingArgument(at: position, by: value) - switch coordinates { - case .absolute: - position += 1 - case .relative: - switch position { - case 0 ... (command.arguments - 2): - position += 1 - case command.arguments - 1: - position = -1 - default: - break // throw? - } - } - case .lineTo: - self.command = try command.adjustingArgument(at: position, by: value) - switch coordinates { - case .absolute: - position += 1 - case .relative: - switch position { - case 0: - if singleValue { - singleValue = false - position = -1 - } else { - position += 1 - } - case 1: - if singleValue { - singleValue = false - } - position = -1 - default: - break // throw? - } - } - case .closePath: - break - } - } - - private func nextCommand(with value: Double, lastCommand: Path.Command?) throws { - guard let command = lastCommand else { - throw Path.Command.Error.invalidRelativeCommand - } - - switch command { - case .moveTo: - switch coordinates { - case .absolute: - self.command = .lineTo(point: Point(x: value, y: .nan)) - position = 1 - case .relative: - let c = Path.Command.lineTo(point: command.point) - self.command = try c.adjustingArgument(at: 0, by: value) - position = 1 - } - case .lineTo: - switch coordinates { - case .absolute: - self.command = .lineTo(point: Point(x: value, y: .nan)) - position = 1 - case .relative: - let c = Path.Command.lineTo(point: command.point) - self.command = try c.adjustingArgument(at: 0, by: value) - position = 1 - } - case .cubicBezierCurve: - switch coordinates { - case .absolute: - self.command = .cubicBezierCurve(cp1: Point(x: value, y: .nan), cp2: .nan, point: .nan) - position = 1 - case .relative: - let c = Path.Command.cubicBezierCurve(cp1: command.point, cp2: command.point, point: command.point) - self.command = try c.adjustingArgument(at: 0, by: value) - position = 1 - } - case .quadraticBezierCurve: - switch coordinates { - case .absolute: - self.command = .quadraticBezierCurve(cp: Point(x: value, y: .nan), point: .nan) - position = 1 - case .relative: - let c = Path.Command.quadraticBezierCurve(cp: command.point, point: command.point) - self.command = try c.adjustingArgument(at: 0, by: value) - position = 1 - } - case .ellipticalArcCurve: - switch coordinates { - case .absolute: - self.command = .ellipticalArcCurve(rx: value, ry: .nan, angle: .nan, largeArc: false, clockwise: false, point: .nan) - position = 1 - case .relative: - let c = Path.Command.ellipticalArcCurve(rx: .nan, ry: .nan, angle: .nan, largeArc: false, clockwise: false, point: command.point) - self.command = try c.adjustingArgument(at: 0, by: value) - position = 1 - } - case .closePath: - break - } - } - - private func reset() { - command = nil - coordinates = .absolute - position = 0 - singleValue = false - } - } -} diff --git a/third-party/SwiftSVG/Sources/Path.swift b/third-party/SwiftSVG/Sources/Path.swift deleted file mode 100644 index 9c02c65704..0000000000 --- a/third-party/SwiftSVG/Sources/Path.swift +++ /dev/null @@ -1,101 +0,0 @@ -import XMLCoder - -/// Generic element to define a shape. -/// -/// A path is defined by including a ‘path’ element in a SVG document which contains a **d="(path data)"** -/// attribute, where the **‘d’** attribute contains the moveto, line, curve (both Cubic and Quadratic Bézier), -/// arc and closepath instructions. -/// -/// ## Documentation -/// [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/path) -/// | [W3](https://www.w3.org/TR/SVG11/paths.html) -public struct Path: Element { - - /// The definition of the outline of a shape. - public var data: String = "" - - // MARK: CoreAttributes - - public var id: String? - - // MARK: PresentationAttributes - - public var fillColor: String? - public var fillOpacity: Double? - public var fillRule: Fill.Rule? - public var strokeColor: String? - public var strokeWidth: Double? - public var strokeOpacity: Double? - public var strokeLineCap: Stroke.LineCap? - public var strokeLineJoin: Stroke.LineJoin? - public var strokeMiterLimit: Double? - public var transform: String? - - // MARK: StylingAttributes - - public var style: String? - - enum CodingKeys: String, CodingKey { - case data = "d" - case id - case fillColor = "fill" - case fillOpacity = "fill-opacity" - case fillRule = "fill-rule" - case strokeColor = "stroke" - case strokeWidth = "stroke-width" - case strokeOpacity = "stroke-opacity" - case strokeLineCap = "stroke-linecap" - case strokeLineJoin = "stroke-linejoin" - case strokeMiterLimit = "stroke-miterlimit" - case transform - case style - } - - public init() {} - - public init(data: String) { - self.init() - self.data = data - } - - public init(commands: [Path.Command]) { - self.init() - data = commands.map(\.description).joined() - } -} - -extension Path: CommandRepresentable { - public func commands() throws -> [Command] { - try PathProcessor(data: data).commands() - } -} - -extension Path: CustomStringConvertible { - public var description: String { - "" - } -} - -extension Path: DynamicNodeDecoding { - public static func nodeDecoding(for key: any CodingKey) -> XMLDecoder.NodeDecoding { - .attribute - } -} - -extension Path: DynamicNodeEncoding { - public static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { - .attribute - } -} - -extension Path: Equatable { - public static func == (lhs: Path, rhs: Path) -> Bool { - do { - let lhsCommands = try lhs.commands() - let rhsCommands = try rhs.commands() - return lhsCommands == rhsCommands - } catch { - return false - } - } -} diff --git a/third-party/SwiftSVG/Sources/Polygon.swift b/third-party/SwiftSVG/Sources/Polygon.swift deleted file mode 100644 index 84320b929f..0000000000 --- a/third-party/SwiftSVG/Sources/Polygon.swift +++ /dev/null @@ -1,82 +0,0 @@ -import XMLCoder - -/// Defines a closed shape consisting of a set of connected straight line segments. -/// -/// The last point is connected to the first point. For open shapes, see the `Polyline` element. If an odd number of -/// coordinates is provided, then the element is in error. -/// -/// ## Documentation -/// [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polygon) -/// | [W3](https://www.w3.org/TR/SVG11/shapes.html#PolygonElement) -public struct Polygon: Element { - - /// The points that make up the polygon. - public var points: String = "" - - // MARK: CoreAttributes - - public var id: String? - - // MARK: PresentationAttributes - - public var fillColor: String? - public var fillOpacity: Double? - public var fillRule: Fill.Rule? - public var strokeColor: String? - public var strokeWidth: Double? - public var strokeOpacity: Double? - public var strokeLineCap: Stroke.LineCap? - public var strokeLineJoin: Stroke.LineJoin? - public var strokeMiterLimit: Double? - public var transform: String? - - // MARK: StylingAttributes - - public var style: String? - - enum CodingKeys: String, CodingKey { - case points - case id - case fillColor = "fill" - case fillOpacity = "fill-opacity" - case fillRule = "fill-rule" - case strokeColor = "stroke" - case strokeWidth = "stroke-width" - case strokeOpacity = "stroke-opacity" - case strokeLineCap = "stroke-linecap" - case strokeLineJoin = "stroke-linejoin" - case strokeMiterLimit = "stroke-miterlimit" - case transform - case style - } - - public init() {} - - public init(points: String) { - self.points = points - } -} - -extension Polygon: CommandRepresentable { - public func commands() throws -> [Path.Command] { - try PolygonProcessor(points: points).commands() - } -} - -extension Polygon: CustomStringConvertible { - public var description: String { - "" - } -} - -extension Polygon: DynamicNodeDecoding { - public static func nodeDecoding(for key: any CodingKey) -> XMLDecoder.NodeDecoding { - .attribute - } -} - -extension Polygon: DynamicNodeEncoding { - public static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { - .attribute - } -} diff --git a/third-party/SwiftSVG/Sources/Polyline.swift b/third-party/SwiftSVG/Sources/Polyline.swift deleted file mode 100644 index 5fb8c930c4..0000000000 --- a/third-party/SwiftSVG/Sources/Polyline.swift +++ /dev/null @@ -1,81 +0,0 @@ -import XMLCoder - -/// SVG basic shape that creates straight lines connecting several points. -/// -/// Typically a polyline is used to create open shapes as the last point doesn't have to be connected to the first -/// point. For closed shapes see the `Polygon` element. -/// -/// ## Documentation -/// [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/polyline) -/// | [W3](https://www.w3.org/TR/SVG11/shapes.html#PolylineElement) -public struct Polyline: Element { - - public var points: String = "" - - // MARK: CoreAttributes - - public var id: String? - - // MARK: PresentationAttributes - - public var fillColor: String? - public var fillOpacity: Double? - public var fillRule: Fill.Rule? - public var strokeColor: String? - public var strokeWidth: Double? - public var strokeOpacity: Double? - public var strokeLineCap: Stroke.LineCap? - public var strokeLineJoin: Stroke.LineJoin? - public var strokeMiterLimit: Double? - public var transform: String? - - // MARK: StylingAttributes - - public var style: String? - - enum CodingKeys: String, CodingKey { - case points - case id - case fillColor = "fill" - case fillOpacity = "fill-opacity" - case fillRule = "fill-rule" - case strokeColor = "stroke" - case strokeWidth = "stroke-width" - case strokeOpacity = "stroke-opacity" - case strokeLineCap = "stroke-linecap" - case strokeLineJoin = "stroke-linejoin" - case strokeMiterLimit = "stroke-miterlimit" - case transform - case style - } - - public init() {} - - public init(points: String) { - self.points = points - } -} - -extension Polyline: CommandRepresentable { - public func commands() throws -> [Path.Command] { - try PolylineProcessor(points: points).commands() - } -} - -extension Polyline: CustomStringConvertible { - public var description: String { - "" - } -} - -extension Polyline: DynamicNodeDecoding { - public static func nodeDecoding(for key: any CodingKey) -> XMLDecoder.NodeDecoding { - .attribute - } -} - -extension Polyline: DynamicNodeEncoding { - public static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { - .attribute - } -} diff --git a/third-party/SwiftSVG/Sources/PresentationAttributes.swift b/third-party/SwiftSVG/Sources/PresentationAttributes.swift deleted file mode 100644 index 5cd6598df3..0000000000 --- a/third-party/SwiftSVG/Sources/PresentationAttributes.swift +++ /dev/null @@ -1,120 +0,0 @@ -import Foundation -import Swift2D - -public protocol PresentationAttributes { - var fillColor: String? { get set } - var fillOpacity: Double? { get set } - var fillRule: Fill.Rule? { get set } - var strokeColor: String? { get set } - var strokeWidth: Double? { get set } - var strokeOpacity: Double? { get set } - var strokeLineCap: Stroke.LineCap? { get set } - var strokeLineJoin: Stroke.LineJoin? { get set } - var strokeMiterLimit: Double? { get set } - var transform: String? { get set } -} - -enum PresentationAttributesKeys: String, CodingKey { - case fillColor = "fill" - case fillOpacity = "fill-opacity" - case fillRule = "fill-rule" - case strokeColor = "stroke" - case strokeWidth = "stroke-width" - case strokeOpacity = "stroke-opacity" - case strokeLineCap = "stroke-linecap" - case strokeLineJoin = "stroke-linejoin" - case strokeMiterLimit = "stroke-miterlimit" - case transform -} - -public extension PresentationAttributes { - var presentationDescription: String { - var attributes: [String] = [] - - if let fillColor { - attributes.append("\(PresentationAttributesKeys.fillColor.rawValue)=\"\(fillColor)\"") - } - if let fillOpacity { - attributes.append("\(PresentationAttributesKeys.fillOpacity.rawValue)=\"\(fillOpacity)\"") - } - if let fillRule { - attributes.append("\(PresentationAttributesKeys.fillRule.rawValue)=\"\(fillRule.description)\"") - } - if let strokeColor { - attributes.append("\(PresentationAttributesKeys.strokeColor.rawValue)=\"\(strokeColor)\"") - } - if let strokeWidth { - attributes.append("\(PresentationAttributesKeys.strokeWidth.rawValue)=\"\(strokeWidth)\"") - } - if let strokeOpacity { - attributes.append("\(PresentationAttributesKeys.strokeOpacity.rawValue)=\"\(strokeOpacity)\"") - } - if let strokeLineCap { - attributes.append("\(PresentationAttributesKeys.strokeLineCap.rawValue)=\"\(strokeLineCap.description)\"") - } - if let strokeLineJoin { - attributes.append("\(PresentationAttributesKeys.strokeLineJoin.rawValue)=\"\(strokeLineJoin.description)\"") - } - if let strokeMiterLimit { - attributes.append("\(PresentationAttributesKeys.strokeMiterLimit.rawValue)=\"\(strokeMiterLimit)\"") - } - if let transform { - attributes.append("\(PresentationAttributesKeys.transform.rawValue)=\"\(transform)\"") - } - - return attributes.joined(separator: " ") - } - - var transformations: [Transformation] { - let value = transform?.replacingOccurrences(of: " ", with: "") ?? "" - guard !value.isEmpty else { - return [] - } - - let values = value.split(separator: ")").map { $0.appending(")") } - return values.compactMap { Transformation($0) } - } - - var fill: Fill? { - get { - if fillColor == nil, fillOpacity == nil { - return nil - } - - var fill = Fill() - fill.color = fillColor ?? "black" - fill.opacity = fillOpacity ?? 1.0 - return fill - } - set { - fillColor = newValue?.color - fillOpacity = newValue?.opacity - fillRule = newValue?.rule - } - } - - var stroke: Stroke? { - get { - if strokeColor == nil, strokeOpacity == nil { - return nil - } - - var stroke = Stroke() - stroke.color = strokeColor ?? "black" - stroke.opacity = strokeOpacity ?? 1.0 - stroke.width = strokeWidth ?? 1.0 - stroke.lineCap = strokeLineCap ?? .butt - stroke.lineJoin = strokeLineJoin ?? .miter - stroke.miterLimit = strokeMiterLimit - return stroke - } - set { - strokeColor = newValue?.color - strokeOpacity = newValue?.opacity - strokeWidth = newValue?.width - strokeLineCap = newValue?.lineCap - strokeLineJoin = newValue?.lineJoin - strokeMiterLimit = newValue?.miterLimit - } - } -} diff --git a/third-party/SwiftSVG/Sources/Rectangle.swift b/third-party/SwiftSVG/Sources/Rectangle.swift deleted file mode 100644 index 4f663b846d..0000000000 --- a/third-party/SwiftSVG/Sources/Rectangle.swift +++ /dev/null @@ -1,115 +0,0 @@ -import Swift2D -import XMLCoder - -/// Basic SVG shape that draws rectangles, defined by their position, width, and height. -/// -/// The values used for the x- and y-axis rounded corner radii are determined implicitly -/// if the ‘rx’ or ‘ry’ attributes (or both) are not specified, or are specified but with invalid values. -/// -/// ## Documentation -/// [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect) -/// | [W3](https://www.w3.org/TR/SVG11/shapes.html#RectElement) -public struct Rectangle: Element { - - /// The x-axis coordinate of the side of the rectangle which - /// has the smaller x-axis coordinate value. - public var x: Double = 0.0 - /// The y-axis coordinate of the side of the rectangle which - /// has the smaller y-axis coordinate value - public var y: Double = 0.0 - /// The width of the rectangle. - public var width: Double = 0.0 - /// The height of the rectangle. - public var height: Double = 0.0 - /// For rounded rectangles, the x-axis radius of the ellipse used - /// to round off the corners of the rectangle. - public var rx: Double? - /// For rounded rectangles, the y-axis radius of the ellipse used - /// to round off the corners of the rectangle. - public var ry: Double? - - // MARK: CoreAttributes - - public var id: String? - - // MARK: PresentationAttributes - - public var fillColor: String? - public var fillOpacity: Double? - public var fillRule: Fill.Rule? - public var strokeColor: String? - public var strokeWidth: Double? - public var strokeOpacity: Double? - public var strokeLineCap: Stroke.LineCap? - public var strokeLineJoin: Stroke.LineJoin? - public var strokeMiterLimit: Double? - public var transform: String? - - // MARK: StylingAttributes - - public var style: String? - - enum CodingKeys: String, CodingKey { - case x - case y - case width - case height - case rx - case ry - case id - case fillColor = "fill" - case fillOpacity = "fill-opacity" - case fillRule = "fill-rule" - case strokeColor = "stroke" - case strokeWidth = "stroke-width" - case strokeOpacity = "stroke-opacity" - case strokeLineCap = "stroke-linecap" - case strokeLineJoin = "stroke-linejoin" - case strokeMiterLimit = "stroke-miterlimit" - case transform - case style - } - - public init() {} - - public init(x: Double, y: Double, width: Double, height: Double, rx: Double? = nil, ry: Double? = nil) { - self.x = x - self.y = y - self.width = width - self.height = height - self.rx = rx - self.ry = ry - } -} - -extension Rectangle: CustomStringConvertible { - public var description: String { - var desc = "" - } -} - -extension Rectangle: DirectionalCommandRepresentable { - public func commands(clockwise: Bool) throws -> [Path.Command] { - RectangleProcessor(rectangle: self).commands(clockwise: clockwise) - } -} - -extension Rectangle: DynamicNodeDecoding { - public static func nodeDecoding(for key: any CodingKey) -> XMLDecoder.NodeDecoding { - .attribute - } -} - -extension Rectangle: DynamicNodeEncoding { - public static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { - .attribute - } -} diff --git a/third-party/SwiftSVG/Sources/SVG+Swift2D.swift b/third-party/SwiftSVG/Sources/SVG+Swift2D.swift deleted file mode 100644 index abf62de434..0000000000 --- a/third-party/SwiftSVG/Sources/SVG+Swift2D.swift +++ /dev/null @@ -1,62 +0,0 @@ -import Foundation -import Swift2D - -public extension SVG { - /// Original size of the document image. - /// - /// Primarily uses the `viewBox` attribute, and will fallback to the 'pixelSize' - var originalSize: Size { - (viewBoxSize ?? pixelSize) ?? .zero - } - - /// Size of the design in a square 'viewBox'. - /// - /// All paths created by this framework are outputted in a 'square'. - var outputSize: Size { - let size = (pixelSize ?? viewBoxSize) ?? .zero - let maxDimension = max(size.width, size.height) - return Size(width: maxDimension, height: maxDimension) - } - - /// Size derived from the `viewBox` document attribute - var viewBoxSize: Size? { - guard let viewBox else { - return nil - } - - let components = viewBox.components(separatedBy: .whitespaces) - guard components.count == 4 else { - return nil - } - - guard let width = Double(components[2]) else { - return nil - } - - guard let height = Double(components[3]) else { - return nil - } - - return Size(width: width, height: height) - } - - /// Size derived from the 'width' & 'height' document attributes - var pixelSize: Size? { - guard let width, !width.isEmpty else { - return nil - } - - guard let height, !height.isEmpty else { - return nil - } - - let widthRawValue = width.replacingOccurrences(of: "px", with: "", options: .caseInsensitive, range: nil) - let heightRawValue = height.replacingOccurrences(of: "px", with: "", options: .caseInsensitive, range: nil) - - guard let w = Double(widthRawValue), let h = Double(heightRawValue) else { - return nil - } - - return Size(width: w, height: h) - } -} diff --git a/third-party/SwiftSVG/Sources/SVG.swift b/third-party/SwiftSVG/Sources/SVG.swift deleted file mode 100644 index cbf3117bbc..0000000000 --- a/third-party/SwiftSVG/Sources/SVG.swift +++ /dev/null @@ -1,160 +0,0 @@ -import Foundation -import XMLCoder - -/// SVG is a language for describing two-dimensional graphics in XML. -/// -/// The svg element is a container that defines a new coordinate system and viewport. It is used as the outermost -/// element of SVG documents, but it can also be used to embed a SVG fragment inside an SVG or HTML document. -/// -/// ## Documentation -/// [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/svg) -/// | [W3](https://www.w3.org/TR/SVG11/) -public struct SVG: Container { - - public var viewBox: String? - public var width: String? - public var height: String? - public var title: String? - public var desc: String? - - // Container - public var circles: [Circle]? - public var ellipses: [Ellipse]? - public var groups: [Group]? - public var lines: [Line]? - public var paths: [Path]? - public var polygons: [Polygon]? - public var polylines: [Polyline]? - public var rectangles: [Rectangle]? - public var texts: [Text]? - - /// A non-optional, non-spaced representation of the `title`. - public var name: String { - let name = title ?? "SVG Document" - let newTitle = name.components(separatedBy: .punctuationCharacters).joined(separator: "_") - return newTitle.replacingOccurrences(of: " ", with: "_") - } - - enum CodingKeys: String, CodingKey { - case width - case height - case viewBox - case title - case desc - case circles = "circle" - case ellipses = "ellipse" - case groups = "g" - case lines = "line" - case paths = "path" - case polylines = "polyline" - case polygons = "polygon" - case rectangles = "rect" - case texts = "text" - } - - public init() {} - - public init(width: Int, height: Int) { - self.width = "\(width)px" - self.height = "\(height)px" - viewBox = "0 0 \(width) \(height)" - } - - public static func make(from url: URL) throws -> SVG { - guard FileManager.default.fileExists(atPath: url.path) else { - throw CocoaError(.fileNoSuchFile) - } - - let data = try Data(contentsOf: url) - return try make(with: data) - } - - public static func make(with data: Data, decoder: XMLDecoder = XMLDecoder()) throws -> SVG { - try decoder.decode(SVG.self, from: data) - } - - /// A collection of all `Path`s in the document. - public func subpaths() throws -> [Path] { - var output: [Path] = [] - let _transformations: [Transformation] = [] - - if let circles { - try output.append(contentsOf: circles.compactMap { try $0.path(applying: _transformations) }) - } - - if let ellipses { - try output.append(contentsOf: ellipses.compactMap { try $0.path(applying: _transformations) }) - } - - if let rectangles { - try output.append(contentsOf: rectangles.compactMap { try $0.path(applying: _transformations) }) - } - - if let polygons { - try output.append(contentsOf: polygons.compactMap { try $0.path(applying: _transformations) }) - } - - if let polylines { - try output.append(contentsOf: polylines.compactMap { try $0.path(applying: _transformations) }) - } - - if let paths { - try output.append(contentsOf: paths.map { try $0.path(applying: _transformations) }) - } - - if let groups { - try groups.forEach { - try output.append(contentsOf: $0.subpaths(applying: _transformations)) - } - } - - return output - } - - /// A singular path that represents all of the `Command`s within the document. - public func coalescedPath() throws -> Path { - let paths = try subpaths() - let commands = try paths.flatMap { try $0.commands() } - return Path(commands: commands) - } -} - -extension SVG: CustomStringConvertible { - public var description: String { - var contents: String = "" - - if let title { - contents.append("\n\(title)") - } - - if let desc { - contents.append("\n\(desc)") - } - - contents.append(containerDescription) - - return "\(contents)\n" - } -} - -extension SVG: DynamicNodeDecoding { - public static func nodeDecoding(for key: any CodingKey) -> XMLDecoder.NodeDecoding { - switch key { - case CodingKeys.width, CodingKeys.height, CodingKeys.viewBox: - .attribute - default: - .element - } - } -} - -extension SVG: DynamicNodeEncoding { - public static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { - switch key { - case CodingKeys.width, CodingKeys.height, CodingKeys.viewBox: - .attribute - default: - .element - } - } -} diff --git a/third-party/SwiftSVG/Sources/Stroke.swift b/third-party/SwiftSVG/Sources/Stroke.swift deleted file mode 100644 index d68cba3dd4..0000000000 --- a/third-party/SwiftSVG/Sources/Stroke.swift +++ /dev/null @@ -1,64 +0,0 @@ -import Swift2D - -public struct Stroke { - - public var color: String? - public var width: Double? - public var opacity: Double? - public var lineCap: LineCap = .butt - public var lineJoin: LineJoin = .miter - public var miterLimit: Double? - - public init() {} - - /// Presentation attribute defining the shape to be used at the end of open subpaths when they are stroked. - /// - /// The default `LineCap` is `.butt` - public enum LineCap: String, Sendable, Codable, CaseIterable { - /// The stroke for each subpath does not extend beyond its two endpoints. - case butt - /// The end of each subpath the stroke will be extended by a half circle with a diameter equal to the stroke - /// width. - case round - /// The end of each subpath the stroke will be extended by a rectangle with a width equal to half the width of - /// the stroke and a height equal to the width of the stroke. - case square - } - - /// Presentation attribute defining the shape to be used at the corners of paths when they are stroked. - /// - /// The default `LineJoin` is `.miter` - public enum LineJoin: String, Sendable, Codable, CaseIterable { - /// An arcs corner is to be used to join path segments. - /// - /// The arcs shape is formed by extending the outer edges of the stroke at the join point with arcs that have - /// the same curvature as the outer edges at the join point. - case arcs - /// The bevel value indicates that a bevelled corner is to be used to join path segments. - case bevel - /// Indicates that a sharp corner is to be used to join path segments. - /// - /// The corner is formed by extending the outer edges of the stroke at the tangents of the path segments until - /// they intersect. - case miter - /// A sharp corner is to be used to join path segments. - /// - /// The corner is formed by extending the outer edges of the stroke at the tangents of the path segments until - /// they intersect. - case miterClip = "miter-clip" - /// The round value indicates that a round corner is to be used to join path segments. - case round - } -} - -extension Stroke.LineCap: CustomStringConvertible { - public var description: String { - rawValue - } -} - -extension Stroke.LineJoin: CustomStringConvertible { - public var description: String { - rawValue - } -} diff --git a/third-party/SwiftSVG/Sources/StylingAttributes.swift b/third-party/SwiftSVG/Sources/StylingAttributes.swift deleted file mode 100644 index 8c597a42f4..0000000000 --- a/third-party/SwiftSVG/Sources/StylingAttributes.swift +++ /dev/null @@ -1,17 +0,0 @@ -public protocol StylingAttributes { - var style: String? { get set } -} - -enum StylingAttributesKeys: String, CodingKey { - case style -} - -public extension StylingAttributes { - var stylingDescription: String { - if let style { - "\(StylingAttributesKeys.style.rawValue)=\"\(style)\"" - } else { - "" - } - } -} diff --git a/third-party/SwiftSVG/Sources/Text.swift b/third-party/SwiftSVG/Sources/Text.swift deleted file mode 100644 index d54f62fcf6..0000000000 --- a/third-party/SwiftSVG/Sources/Text.swift +++ /dev/null @@ -1,110 +0,0 @@ -import Foundation -import XMLCoder - -/// Graphics element consisting of text -/// -/// It's possible to apply a gradient, pattern, clipping path, mask, or filter to `Text`, like any other SVG graphics element. -/// -/// ## Documentation -/// [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text) -/// | [W3](https://www.w3.org/TR/SVG11/text.html#TextElement) -public struct Text: Element { - - public var value: String = "" - public var x: Double? - public var y: Double? - public var dx: Double? - public var dy: Double? - - // MARK: CoreAttributes - - public var id: String? - - // MARK: PresentationAttributes - - public var fillColor: String? - public var fillOpacity: Double? - public var fillRule: Fill.Rule? - public var strokeColor: String? - public var strokeWidth: Double? - public var strokeOpacity: Double? - public var strokeLineCap: Stroke.LineCap? - public var strokeLineJoin: Stroke.LineJoin? - public var strokeMiterLimit: Double? - public var transform: String? - - // MARK: StylingAttributes - - public var style: String? - - enum CodingKeys: String, CodingKey { - case value = "" - case x - case y - case dx - case dy - case id - case fillColor = "fill" - case fillOpacity = "fill-opacity" - case fillRule = "fill-rule" - case strokeColor = "stroke" - case strokeWidth = "stroke-width" - case strokeOpacity = "stroke-opacity" - case strokeLineCap = "stroke-linecap" - case strokeLineJoin = "stroke-linejoin" - case strokeMiterLimit = "stroke-miterlimit" - case transform - case style - } - - public init() {} - - public init(value: String) { - self.value = value - } -} - -extension Text: CustomStringConvertible { - public var description: String { - var components: [String] = [] - - if let x, !x.isNaN, !x.isZero { - components.append(String(format: "x=\"%.5f\"", x)) - } - if let y, !y.isNaN, !y.isZero { - components.append(String(format: "y=\"%.5f\"", y)) - } - if let dx, !dx.isNaN, !dx.isZero { - components.append(String(format: "dx=\"%.5f\"", dx)) - } - if let dy, !dy.isNaN, !dy.isZero { - components.append(String(format: "dy=\"%.5f\"", dy)) - } - - components.append(attributeDescription) - - return "\(value)" - } -} - -extension Text: DynamicNodeDecoding { - public static func nodeDecoding(for key: any CodingKey) -> XMLDecoder.NodeDecoding { - switch key { - case CodingKeys.value: - .element - default: - .attribute - } - } -} - -extension Text: DynamicNodeEncoding { - public static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { - switch key { - case CodingKeys.value: - .element - default: - .attribute - } - } -} diff --git a/third-party/SwiftSVG/Sources/Transformation.swift b/third-party/SwiftSVG/Sources/Transformation.swift deleted file mode 100644 index 3fb086d55e..0000000000 --- a/third-party/SwiftSVG/Sources/Transformation.swift +++ /dev/null @@ -1,113 +0,0 @@ -import Foundation -import Swift2D - -/// A modification that should be applied to an element and its children. -/// -/// If a list of transforms is provided, then the net effect is as if each transform had been specified separately in -/// the order provided. -/// -/// For example, -/// ``` -/// -/// -/// -/// ``` -/// is functionally equivalent to: -/// ``` -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// ``` -/// -/// The ‘transform’ attribute is applied to an element before processing any other coordinate or length values supplied -/// for that element. -/// -/// ## Documentation -/// [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform) -/// | [W3](https://www.w3.org/TR/SVG11/coords.html#TransformAttribute) -public enum Transformation { - /// Moves an object by x & y. (Y is assumed to be '0' if not provided) - case translate(x: Double, y: Double) - /// Specifies a transformation in the form of a transformation matrix of six values. - case matrix(a: Double, b: Double, c: Double, d: Double, e: Double, f: Double) - - public enum Prefix: String, CaseIterable { - case translate - case matrix - } - - /// Initializes a new `Transformation` with a raw SVG transformation string. - public init?(_ string: String) { - guard let prefix = Prefix.allCases.first(where: { string.lowercased().hasPrefix($0.rawValue) }) else { - return nil - } - - switch prefix { - case .translate: - guard let start = string.firstIndex(of: "(") else { - return nil - } - - guard let stop = string.lastIndex(of: ")") else { - return nil - } - - var substring = String(string[start ... stop]) - substring = substring.replacingOccurrences(of: "(", with: "") - substring = substring.replacingOccurrences(of: ")", with: "") - - var components = substring.split(separator: " ", omittingEmptySubsequences: true).map { String($0) } - components = components.flatMap { $0.components(separatedBy: ",") } - - let values = components.compactMap { Double($0) }.map { Double($0) } - guard values.count > 0 else { - return nil - } - - if values.count > 1 { - self = .translate(x: values[0], y: values[1]) - } else { - self = .translate(x: values[0], y: 0.0) - } - case .matrix: - guard let start = string.firstIndex(of: "(") else { - return nil - } - - guard let stop = string.lastIndex(of: ")") else { - return nil - } - - var substring = String(string[start ... stop]) - substring = substring.replacingOccurrences(of: "(", with: "") - substring = substring.replacingOccurrences(of: ")", with: "") - - var components = substring.split(separator: " ", omittingEmptySubsequences: true).map { String($0) } - components = components.flatMap { $0.components(separatedBy: ",") } - - let values = components.compactMap { Double($0) }.map { Double($0) } - guard values.count > 5 else { - return nil - } - - self = .matrix(a: values[0], b: values[1], c: values[2], d: values[3], e: values[4], f: values[5]) - } - } -} - -extension Transformation: CustomStringConvertible { - public var description: String { - switch self { - case .translate(let x, let y): - "translate(\(x), \(y))" - case .matrix(let a, let b, let c, let d, let e, let f): - "matrix(\(a), \(b), \(c), \(d), \(e), \(f))" - } - } -} diff --git a/third-party/VectorPlus/BUILD b/third-party/VectorPlus/BUILD deleted file mode 100644 index c7f57a85a1..0000000000 --- a/third-party/VectorPlus/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") - -swift_library( - name = "VectorPlus", - module_name = "VectorPlus", - srcs = glob([ - "Sources/**/*.swift", - ]), - copts = [ - "-warnings-as-errors", - ], - deps = [ - "//third-party/SwiftColor", - "//third-party/SwiftSVG", - ], - visibility = [ - "//visibility:public", - ], -) diff --git a/third-party/VectorPlus/Sources/CoreGraphics/CGContext+Render.swift b/third-party/VectorPlus/Sources/CoreGraphics/CGContext+Render.swift deleted file mode 100644 index a6f3e94d73..0000000000 --- a/third-party/VectorPlus/Sources/CoreGraphics/CGContext+Render.swift +++ /dev/null @@ -1,72 +0,0 @@ -import Swift2D -import SwiftColor -import SwiftSVG -#if canImport(CoreGraphics) -import CoreGraphics - -public extension CGContext { - func render(path: Path, from: Rect, to: Rect) throws { - saveGState() - - let cgPath = CGMutablePath() - - let commands = (try? path.commands()) ?? [] - for (idx, command) in commands.enumerated() { - let previous: Point? = if idx > 0 { - commands[idx - 1].previousPoint - } else { - nil - } - - cgPath.addCommand(command, from: from, to: to, previousPoint: previous) - } - - if let fill = path.fill { - let _color = Pigment(fill.color ?? "black") - if _color.alpha != 0.0 { - let cgColor = CGColor.make(_color) - let color = cgColor.copy(alpha: CGFloat(fill.opacity ?? 1.0)) ?? cgColor - let rule = fill.rule.cgFillRule - - setFillColor(color) - addPath(cgPath) - fillPath(using: rule) - } - } - - if let stroke = path.stroke { - let _color = Pigment(stroke.color ?? "black") - if _color.alpha != 0.0 { - let cgColor = CGColor.make(_color) - let color = cgColor.copy(alpha: CGFloat(stroke.opacity ?? 1.0)) ?? cgColor - let width = stroke.width ?? 1.0 - let lineWidth = width * (to.size.width / from.size.width) - - setLineWidth(CGFloat(lineWidth)) - setStrokeColor(color) - setLineCap(stroke.lineCap.cgLineCap) - setLineJoin(stroke.lineJoin.cgLineJoin) - if let miterLimit = stroke.miterLimit, stroke.lineJoin == .miter { - setMiterLimit(CGFloat(miterLimit)) - } - addPath(cgPath) - strokePath() - } - } - - if path.fill == nil, path.stroke == nil { - let color = CGColor(srgbRed: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) - setFillColor(color) - addPath(cgPath) - fillPath(using: path.fill?.rule.cgFillRule ?? .winding) - } - - restoreGState() - } - - func render(path: Path, in rect: Rect) throws { - try render(path: path, from: rect, to: rect) - } -} - -#endif diff --git a/third-party/VectorPlus/Sources/CoreGraphics/CGMutablePath+Instruction.swift b/third-party/VectorPlus/Sources/CoreGraphics/CGMutablePath+Instruction.swift deleted file mode 100644 index f810e6d883..0000000000 --- a/third-party/VectorPlus/Sources/CoreGraphics/CGMutablePath+Instruction.swift +++ /dev/null @@ -1,45 +0,0 @@ -import Swift2D -import SwiftSVG -#if canImport(CoreGraphics) -import CoreGraphics - -public extension CGMutablePath { - /// Adds a `Path.Command` to a _CoreGraphics path_, using the provided rectangles to correctly scale the parameters. - /// - /// - parameter command: The `Path.Command` to append - /// - parameter from: The `Rect` which originally had the instruction. This is typically the `Document.originalSize`. - /// - parameter to: The `Rect` defining the new size. - /// - parameter previousPoint: The last `Point`, used for Elliptical Arc calculations - func addCommand(_ command: Path.Command, from: Rect, to: Rect, previousPoint: Point? = nil) { - let translated = command.translate(from: from, to: to) - switch translated { - case .moveTo(let point): - move(to: CGPoint(point)) - case .lineTo(let point): - addLine(to: CGPoint(point)) - case .cubicBezierCurve(let cp1, let cp2, let point): - addCurve(to: CGPoint(point), control1: CGPoint(cp1), control2: CGPoint(cp2)) - case .quadraticBezierCurve(let cp, let point): - addQuadCurve(to: CGPoint(point), control: CGPoint(cp)) - case .ellipticalArcCurve(_, _, _, _, _, let point): - guard let previousPoint else { - addLine(to: CGPoint(point)) - return - } - - do { - let curves = try command.convertToCubicBezierCurves(with: previousPoint) - for curve in curves { - addCommand(curve, from: from, to: to) - } - } catch { - print(error) - addLine(to: CGPoint(point)) - } - case .closePath: - closeSubpath() - } - } -} - -#endif diff --git a/third-party/VectorPlus/Sources/CoreGraphics/Fill+CoreGraphics.swift b/third-party/VectorPlus/Sources/CoreGraphics/Fill+CoreGraphics.swift deleted file mode 100644 index e038784c2c..0000000000 --- a/third-party/VectorPlus/Sources/CoreGraphics/Fill+CoreGraphics.swift +++ /dev/null @@ -1,14 +0,0 @@ -import Foundation -import SwiftSVG -#if canImport(CoreGraphics) -import CoreGraphics - -public extension Fill.Rule { - var cgFillRule: CGPathFillRule { - switch self { - case .evenOdd: .evenOdd - case .nonZero: .winding - } - } -} -#endif diff --git a/third-party/VectorPlus/Sources/CoreGraphics/SVG+CGPath.swift b/third-party/VectorPlus/Sources/CoreGraphics/SVG+CGPath.swift deleted file mode 100644 index ef4cadbb66..0000000000 --- a/third-party/VectorPlus/Sources/CoreGraphics/SVG+CGPath.swift +++ /dev/null @@ -1,37 +0,0 @@ -import Swift2D -import SwiftSVG -#if canImport(CoreGraphics) -import CoreGraphics - -public extension SVG { - func path(size: Size) -> CGPath { - guard size.height > 0.0, size.width > 0.0 else { - return CGMutablePath() - } - - guard let paths = try? subpaths() else { - return CGMutablePath() - } - - let from = Rect(origin: .zero, size: originalSize) - let to = Rect(origin: .zero, size: size) - - let path = CGMutablePath() - - for p in paths { - let commands = (try? p.commands()) ?? [] - for (idx, command) in commands.enumerated() { - let previous: Point? = if idx > 0 { - commands[idx - 1].previousPoint - } else { - nil - } - - path.addCommand(command, from: from, to: to, previousPoint: previous) - } - } - - return path - } -} -#endif diff --git a/third-party/VectorPlus/Sources/CoreGraphics/Stroke+CoreGraphics.swift b/third-party/VectorPlus/Sources/CoreGraphics/Stroke+CoreGraphics.swift deleted file mode 100644 index 3744223181..0000000000 --- a/third-party/VectorPlus/Sources/CoreGraphics/Stroke+CoreGraphics.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Foundation -import SwiftSVG -#if canImport(CoreGraphics) -import CoreGraphics - -public extension Stroke.LineCap { - var cgLineCap: CGLineCap { - switch self { - case .butt: .butt - case .round: .round - case .square: .square - } - } -} - -public extension Stroke.LineJoin { - var cgLineJoin: CGLineJoin { - switch self { - case .bevel: .bevel - case .arcs, .miter, .miterClip: .miter - case .round: .round - } - } -} -#endif diff --git a/third-party/VectorPlus/Sources/Fill+VectorPlus.swift b/third-party/VectorPlus/Sources/Fill+VectorPlus.swift deleted file mode 100644 index c7a66cf9fb..0000000000 --- a/third-party/VectorPlus/Sources/Fill+VectorPlus.swift +++ /dev/null @@ -1,29 +0,0 @@ -import SwiftColor -import SwiftSVG - -public extension Fill { - @available(*, deprecated, renamed: "pigment") - var swiftColor: Pigment? { pigment } - - var pigment: Pigment? { - guard let color, !color.isEmpty else { - return nil - } - - let _color = Pigment(color) - guard _color.alpha != 0.0 else { - return nil - } - - return _color - } -} - -public extension Fill.Rule { - var coreGraphicsDescription: String { - switch self { - case .evenOdd: ".evenOdd" - case .nonZero: ".winding" - } - } -} diff --git a/third-party/VectorPlus/Sources/Path+VectorPlus.swift b/third-party/VectorPlus/Sources/Path+VectorPlus.swift deleted file mode 100644 index 6511f6bbac..0000000000 --- a/third-party/VectorPlus/Sources/Path+VectorPlus.swift +++ /dev/null @@ -1,34 +0,0 @@ -import Swift2D -import SwiftSVG - -public extension Path { - func asCoreGraphicsDescription(variable: String = "path", originalSize: Size) throws -> String { - var outputs: [String] = [] - let commands = (try? commands()) ?? [] - for (idx, command) in commands.enumerated() { - let previous: Point? = if idx > 0 { - commands[idx - 1].previousPoint - } else { - nil - } - - let method = command.coreGraphicsDescription(originalSize: originalSize, previousPoint: previous) - let code = "\(variable)\(method)" - outputs.append(code) - } - return outputs.joined(separator: "\n ") - } -} - -public extension Path.Command { - var previousPoint: Point { - switch self { - case .moveTo(let point): point - case .lineTo(let point): point - case .cubicBezierCurve(_, _, let point): point - case .quadraticBezierCurve(_, let point): point - case .ellipticalArcCurve(_, _, _, _, _, let point): point - case .closePath: .zero - } - } -} diff --git a/third-party/VectorPlus/Sources/Path.Command+VectorPlus.swift b/third-party/VectorPlus/Sources/Path.Command+VectorPlus.swift deleted file mode 100644 index 226e57a643..0000000000 --- a/third-party/VectorPlus/Sources/Path.Command+VectorPlus.swift +++ /dev/null @@ -1,216 +0,0 @@ -import Foundation -import Swift2D -import SwiftSVG - -public extension Path.Command { - /// Uses the _Power of Math_ to translate a commands controls/points from one `Rect` to another `Rect`. - func translate(from: Rect, to: Rect) -> Path.Command { - switch self { - case .moveTo(let point): - let _point = VectorPoint(point: point, in: from).translate(to: to) - return .moveTo(point: _point) - case .lineTo(let point): - let _point = VectorPoint(point: point, in: from).translate(to: to) - return .lineTo(point: _point) - case .cubicBezierCurve(let cp1, let cp2, let point): - let _cp1 = VectorPoint(point: cp1, in: from).translate(to: to) - let _cp2 = VectorPoint(point: cp2, in: from).translate(to: to) - let _point = VectorPoint(point: point, in: from).translate(to: to) - return .cubicBezierCurve(cp1: _cp1, cp2: _cp2, point: _point) - case .quadraticBezierCurve(let cp, let point): - let _cp = VectorPoint(point: cp, in: from).translate(to: to) - let _point = VectorPoint(point: point, in: from).translate(to: to) - return .quadraticBezierCurve(cp: _cp, point: _point) - case .ellipticalArcCurve(let rx, let ry, let angle, let largeArc, let clockwise, let point): - let _rx = rx * (from.size.maxRadius / to.size.minRadius) - let _ry = ry * (from.size.maxRadius / to.size.minRadius) - let _point = VectorPoint(point: point, in: from).translate(to: to) - return .ellipticalArcCurve(rx: _rx, ry: _ry, angle: angle, largeArc: largeArc, clockwise: clockwise, point: _point) - case .closePath: - return self - } - } -} - -public extension Path.Command { - func coreGraphicsDescription(originalSize: Size, previousPoint: Point? = nil) -> String { - let rect = Rect(origin: .zero, size: originalSize) - - switch self { - case .moveTo(let point): - let _point = VectorPoint(point: point, in: rect) - return ".move(to: \(_point.coreGraphicsDescription))" - case .lineTo(let point): - let _point = VectorPoint(point: point, in: rect) - return ".addLine(to: \(_point.coreGraphicsDescription))" - case .cubicBezierCurve(let cp1, let cp2, let point): - let _cp1 = VectorPoint(point: cp1, in: rect) - let _cp2 = VectorPoint(point: cp2, in: rect) - let _point = VectorPoint(point: point, in: rect) - return ".addCurve(to: \(_point.coreGraphicsDescription), control1: \(_cp1.coreGraphicsDescription), control2: \(_cp2.coreGraphicsDescription))" - case .quadraticBezierCurve(let cp, let point): - let _cp = VectorPoint(point: cp, in: rect) - let _point = VectorPoint(point: point, in: rect) - return ".addQuadCurve(to: \(_point.coreGraphicsDescription), control: \(_cp.coreGraphicsDescription))" - case .ellipticalArcCurve(_, _, _, _, _, let point): - guard let previousPoint else { - return Path.Command.lineTo(point: point).coreGraphicsDescription(originalSize: originalSize) - } - - do { - let curves = try convertToCubicBezierCurves(with: previousPoint) - return curves.map { $0.coreGraphicsDescription(originalSize: originalSize) }.joined(separator: "\n") - } catch { - print(error) - return Path.Command.lineTo(point: point).coreGraphicsDescription(originalSize: originalSize) - } - case .closePath: - return ".closeSubpath()" - } - } -} - -extension Path.Command { - /// Converts an `.ellipticalArcCurve` into one or more `.cubicBezierCurve`s. - /// https://github.com/colinmeinke/svg-arc-to-cubic-bezier/blob/master/src/index.js - func convertToCubicBezierCurves(with previousPoint: Point) throws -> [Path.Command] { - guard case let .ellipticalArcCurve(rx, ry, angle, largeArg, clockwise, point) = self else { - throw Path.Command.Error.message("\(#function); Only .ellipticalArcCurve is allowed.") - } - - var curves: [Path.Command] = [] - - guard rx > 0.0, ry > 0.0 else { - throw Path.Command.Error.message("\(#function); rx/ry must be greater than 0.0 (zero).") - } - - let sinφ = sin(angle * (.pi * 2.0) / 360.0) - let cosφ = cos(angle * (.pi * 2.0) / 360.0) - - let pxp = cosφ * (previousPoint.x - point.x) / 2 + sinφ * (previousPoint.y - point.y) / 2.0 - let pyp = -sinφ * (previousPoint.x - point.x) / 2 + cosφ * (previousPoint.y - point.y) / 2.0 - - guard pxp != 0.0, pyp != 0.0 else { - throw Path.Command.Error.message("\(#function); math") - } - - var _rx = abs(rx) - var _ry = abs(ry) - - let λ = pow(pxp, 2.0) / pow(_rx, 2.0) + pow(pyp, 2.0) / pow(_ry, 2.0) - - if λ > 1.0 { - _rx *= sqrt(λ) - _ry *= sqrt(λ) - } - - let _arcCenter = arcCenter(previousPoint: previousPoint, point: point, rx: _rx, ry: _ry, largeArc: largeArg, clockwise: clockwise, sinφ: sinφ, cosφ: cosφ, pxp: pxp, pyp: pyp) - let center = _arcCenter.center - var angle1 = _arcCenter.angle1 - var angle2 = _arcCenter.angle2 - - var ratio = abs(angle2) / ((.pi * 2.0) / 4.0) - if abs(1.0 - ratio) < 0.0000001 { - ratio = 1.0 - } - - let segments = max(ceil(ratio), 1) - - angle2 /= segments - - var rawCurves: [(Point, Point, Point)] = [] - for _ in 0 ... Int(segments) { - rawCurves.append(approximateUnitArc(angle1: angle1, angle2: angle2)) - angle1 += angle2 - } - - for rawCurf in rawCurves { - let _cp1 = mapToEllipse(point: rawCurf.0, rx: _rx, ry: _ry, sinφ: sinφ, cosφ: cosφ, center: center) - let _cp2 = mapToEllipse(point: rawCurf.1, rx: _rx, ry: _ry, sinφ: sinφ, cosφ: cosφ, center: center) - let _point = mapToEllipse(point: rawCurf.2, rx: _rx, ry: _ry, sinφ: sinφ, cosφ: cosφ, center: center) - curves.append(.cubicBezierCurve(cp1: _cp1, cp2: _cp2, point: _point)) - } - - return curves - } -} - -private func arcCenter(previousPoint: Point, point: Point, rx: Double, ry: Double, largeArc: Bool, clockwise: Bool, sinφ: Double, cosφ: Double, pxp: Double, pyp: Double) -> - (center: Point, angle1: Double, angle2: Double) -{ - - let rxsq = pow(rx, 2.0) - let rysq = pow(ry, 2.0) - let pxpsq = pow(pxp, 2.0) - let pypsq = pow(pyp, 2.0) - - var radicant = (rxsq * rysq) - (rxsq * pypsq) - (rysq * pxpsq) - if radicant < 0.0 { - radicant = 0.0 - } - - radicant /= (rxsq * pypsq) + (rysq * pxpsq) - radicant = sqrt(radicant) * (largeArc == clockwise ? -1.0 : 1.0) - - let centerxp = radicant * rx / ry * pyp - let centeryp = radicant * -ry / rx * pxp - - let centerx = cosφ * centerxp - sinφ * centeryp + (previousPoint.x + point.x) / 2.0 - let centery = sinφ * centerxp + cosφ * centeryp + (previousPoint.x + point.x) / 2.0 - - let vx1 = (pxp - centerxp) / rx - let vy1 = (pyp - centeryp) / ry - let vx2 = (-pxp - centerxp) / rx - let vy2 = (-pyp - centeryp) / ry - - let angle1 = vectorAngle(u: Point(x: 1, y: 0), v: Point(x: vx1, y: vy1)) - var angle2 = vectorAngle(u: Point(x: vx1, y: vy1), v: Point(x: vx2, y: vy2)) - - if clockwise == false, angle2 > 0.0 { - angle2 -= (.pi * 2.0) - } else if clockwise == true, angle2 < 0.0 { - angle2 += (.pi * 2.0) - } - - return (Point(x: centerx, y: centery), angle1, angle2) -} - -private func vectorAngle(u: Point, v: Point) -> Double { - let sign: Double = ((u.x * v.y - u.y * v.x) < 0.0) ? -1.0 : 1.0 - var dot = u.x * v.x + u.y * v.y - if dot > 1.0 { - dot = 1.0 - } else if dot < -1.0 { - dot = -1.0 - } - - return sign * acos(dot) -} - -private func approximateUnitArc(angle1: Double, angle2: Double) -> (Point, Point, Point) { - // If 90 degree circular arc, use a constant - // as derived from http://spencermortensen.com/articles/bezier-circle - let a: Double = switch angle2 { - case 1.5707963267948966: - 0.551915024494 - case -1.5707963267948966: - -0.551915024494 - default: - 4.0 / 3.0 * tan(angle2 / 4.0) - } - - let x1 = cos(angle1) - let y1 = sin(angle1) - let x2 = cos(angle1 + angle2) - let y2 = sin(angle1 + angle2) - - return (Point(x: x1 - y1 * a, y: y1 + x1 * a), Point(x: x2 + y2 * a, y: y2 - x2 * 1), Point(x: x2, y: y2)) -} - -private func mapToEllipse(point: Point, rx: Double, ry: Double, sinφ: Double, cosφ: Double, center: Point) -> Point { - let x = point.x * rx - let y = point.y * ry - let xp = cosφ * x - sinφ * y - let yp = sinφ * x + cosφ * y - return Point(x: xp + center.x, y: yp + center.y) -} diff --git a/third-party/VectorPlus/Sources/Pigment+VectorPlus.swift b/third-party/VectorPlus/Sources/Pigment+VectorPlus.swift deleted file mode 100644 index ea9b3e7e04..0000000000 --- a/third-party/VectorPlus/Sources/Pigment+VectorPlus.swift +++ /dev/null @@ -1,7 +0,0 @@ -import SwiftColor - -public extension Pigment { - var coreGraphicsDescription: String { - "CGColor(srgbRed: \(red), green: \(green), blue: \(blue), alpha: \(alpha))" - } -} diff --git a/third-party/VectorPlus/Sources/Point+VectorPlus.swift b/third-party/VectorPlus/Sources/Point+VectorPlus.swift deleted file mode 100644 index 716a66f023..0000000000 --- a/third-party/VectorPlus/Sources/Point+VectorPlus.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Swift2D - -public extension Point { - var coreGraphicsDescription: String { - "CGPoint(x: \(x), y: \(y))" - } -} diff --git a/third-party/VectorPlus/Sources/Rect+VectorPlus.swift b/third-party/VectorPlus/Sources/Rect+VectorPlus.swift deleted file mode 100644 index d66f66f6d6..0000000000 --- a/third-party/VectorPlus/Sources/Rect+VectorPlus.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Swift2D - -public extension Rect { - var coreGraphicsDescription: String { - "CGRect(origin: \(origin.coreGraphicsDescription), size: \(size.coreGraphicsDescription))" - } -} diff --git a/third-party/VectorPlus/Sources/SVG+AppleSymbols.swift b/third-party/VectorPlus/Sources/SVG+AppleSymbols.swift deleted file mode 100644 index 8eb5759507..0000000000 --- a/third-party/VectorPlus/Sources/SVG+AppleSymbols.swift +++ /dev/null @@ -1,324 +0,0 @@ -import Foundation -import Swift2D -import SwiftSVG -import XMLCoder - -public extension SVG { - - static func encodeDocument(_ document: SVG, encoder: XMLEncoder = XMLEncoder()) throws -> Data { - let rootAttributes: [String: String] = [ - "version": "1.1", - "xmlns": "http://www.w3.org/2000/svg", - "xmlns:xlink": "http://www.w3.org/1999/xlink", - ] - let header = XMLHeader(version: 1.0, encoding: "UTF-8", standalone: nil) - return try encoder.encode(document, withRootKey: "svg", rootAttributes: rootAttributes, header: header) - } - - static func appleSymbols(path: Path, in rect: Rect) throws -> SVG { - var document = SVG(width: 3300, height: 2200) - document.groups = try [.appleSymbolsNotes, .appleSymbolsGuides, .appleSymbols(path: path, in: rect)] - return document - } -} - -public extension Group { - static var appleSymbolsNotes: Group { - var group = Group() - - group.id = "Notes" - group.rectangles = [] - group.lines = [] - group.texts = [] - group.groups = [] - - var artboard = Rectangle(x: 0, y: 0, width: 3300, height: 2200) - artboard.id = "artboard" - artboard.style = "fill:white;opacity:1" - group.rectangles?.append(artboard) - - var topLine = Line(x1: 263, y1: 292, x2: 3036, y2: 292) - topLine.style = "fill:none;stroke:black;opacity:1;stroke-width:0.5;" - group.lines?.append(topLine) - - var bottomLine = Line(x1: 263, y1: 1903, x2: 3036, y2: 1903) - bottomLine.style = "fill:none;stroke:black;opacity:1;stroke-width:0.5;" - group.lines?.append(bottomLine) - - var text = Text() - text.style = "stroke:none;fill:black;font-family:-apple-system,\"SF Pro Display\",\"SF Pro Text\",Helvetica,sans-serif;font-weight:bold;" - text.transform = "matrix(1 0 0 1 263 322)" - text.value = "Weight/Scale Variations" - group.texts?.append(text) - - text.style = "stroke:none;fill:black;font-family:-apple-system,\"SF Pro Display\",\"SF Pro Text\",Helvetica,sans-serif;text-anchor:middle" - text.transform = "matrix(1 0 0 1 559.711 322)" - text.value = "Ultralight" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 856.422 322)" - text.value = "Thin" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 1153.13 322)" - text.value = "Light" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 1449.84 322)" - text.value = "Regular" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 1746.56 322)" - text.value = "Medium" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 2043.27 322)" - text.value = "Semibold" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 2339.98 322)" - text.value = "Bold" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 2636.69 322)" - text.value = "Heavy" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 2933.4 322)" - text.value = "Black" - group.texts?.append(text) - - var path = Path(data: "M 9.24805 0.830078 C 13.5547 0.830078 17.1387 -2.74414 17.1387 -7.05078 C 17.1387 -11.3574 13.5449 -14.9316 9.23828 -14.9316 C 4.94141 -14.9316 1.36719 -11.3574 1.36719 -7.05078 C 1.36719 -2.74414 4.95117 0.830078 9.24805 0.830078 Z M 9.24805 -0.654297 C 5.70312 -0.654297 2.87109 -3.49609 2.87109 -7.05078 C 2.87109 -10.6055 5.69336 -13.4473 9.23828 -13.4473 C 12.793 -13.4473 15.6348 -10.6055 15.6445 -7.05078 C 15.6543 -3.49609 12.8027 -0.654297 9.24805 -0.654297 Z M 9.22852 -3.42773 C 9.69727 -3.42773 9.9707 -3.74023 9.9707 -4.25781 L 9.9707 -6.31836 L 12.1973 -6.31836 C 12.6953 -6.31836 13.0371 -6.57227 13.0371 -7.04102 C 13.0371 -7.51953 12.7148 -7.7832 12.1973 -7.7832 L 9.9707 -7.7832 L 9.9707 -10.0098 C 9.9707 -10.5273 9.69727 -10.8496 9.22852 -10.8496 C 8.75977 -10.8496 8.50586 -10.5078 8.50586 -10.0098 L 8.50586 -7.7832 L 6.29883 -7.7832 C 5.78125 -7.7832 5.44922 -7.51953 5.44922 -7.04102 C 5.44922 -6.57227 5.80078 -6.31836 6.29883 -6.31836 L 8.50586 -6.31836 L 8.50586 -4.25781 C 8.50586 -3.75977 8.75977 -3.42773 9.22852 -3.42773 Z") - var subGroup = Group("", path: path, transform: "matrix(1 0 0 1 263 1933)") - group.groups?.append(subGroup) - - path.data = "M 11.709 2.91016 C 17.1582 2.91016 21.6699 -1.60156 21.6699 -7.05078 C 21.6699 -12.4902 17.1484 -17.0117 11.6992 -17.0117 C 6.25977 -17.0117 1.74805 -12.4902 1.74805 -7.05078 C 1.74805 -1.60156 6.26953 2.91016 11.709 2.91016 Z M 11.709 1.25 C 7.09961 1.25 3.41797 -2.44141 3.41797 -7.05078 C 3.41797 -11.6504 7.08984 -15.3516 11.6992 -15.3516 C 16.3086 -15.3516 20 -11.6504 20.0098 -7.05078 C 20.0195 -2.44141 16.3184 1.25 11.709 1.25 Z M 11.6895 -2.41211 C 12.207 -2.41211 12.5195 -2.77344 12.5195 -3.33984 L 12.5195 -6.23047 L 15.5762 -6.23047 C 16.123 -6.23047 16.5039 -6.51367 16.5039 -7.03125 C 16.5039 -7.55859 16.1426 -7.86133 15.5762 -7.86133 L 12.5195 -7.86133 L 12.5195 -10.9277 C 12.5195 -11.5039 12.207 -11.8555 11.6895 -11.8555 C 11.1719 -11.8555 10.8789 -11.4844 10.8789 -10.9277 L 10.8789 -7.86133 L 7.83203 -7.86133 C 7.26562 -7.86133 6.89453 -7.55859 6.89453 -7.03125 C 6.89453 -6.51367 7.28516 -6.23047 7.83203 -6.23047 L 10.8789 -6.23047 L 10.8789 -3.33984 C 10.8789 -2.79297 11.1719 -2.41211 11.6895 -2.41211 Z" - subGroup.paths = [path] - subGroup.transform = "matrix(1 0 0 1 281.506 1933)" - group.groups?.append(subGroup) - - path.data = "M 14.9707 5.67383 C 21.9336 5.67383 27.6953 -0.078125 27.6953 -7.04102 C 27.6953 -14.0039 21.9238 -19.7559 14.9609 -19.7559 C 8.00781 -19.7559 2.25586 -14.0039 2.25586 -7.04102 C 2.25586 -0.078125 8.01758 5.67383 14.9707 5.67383 Z M 14.9707 3.85742 C 8.93555 3.85742 4.08203 -1.00586 4.08203 -7.04102 C 4.08203 -13.0762 8.92578 -17.9395 14.9609 -17.9395 C 21.0059 -17.9395 25.8594 -13.0762 25.8691 -7.04102 C 25.8789 -1.00586 21.0156 3.85742 14.9707 3.85742 Z M 14.9512 -1.06445 C 15.5176 -1.06445 15.8691 -1.45508 15.8691 -2.06055 L 15.8691 -6.13281 L 20.1074 -6.13281 C 20.6934 -6.13281 21.1133 -6.46484 21.1133 -7.02148 C 21.1133 -7.59766 20.7227 -7.93945 20.1074 -7.93945 L 15.8691 -7.93945 L 15.8691 -12.1875 C 15.8691 -12.8027 15.5176 -13.1934 14.9512 -13.1934 C 14.3848 -13.1934 14.0625 -12.7832 14.0625 -12.1875 L 14.0625 -7.93945 L 9.83398 -7.93945 C 9.21875 -7.93945 8.80859 -7.59766 8.80859 -7.02148 C 8.80859 -6.46484 9.23828 -6.13281 9.83398 -6.13281 L 14.0625 -6.13281 L 14.0625 -2.06055 C 14.0625 -1.47461 14.3848 -1.06445 14.9512 -1.06445 Z" - subGroup.paths = [path] - subGroup.transform = "matrix(1 0 0 1 304.924 1933)" - group.groups?.append(subGroup) - - text.style = "stroke:none;fill:black;font-family:-apple-system,\"SF Pro Display\",\"SF Pro Text\",Helvetica,sans-serif;font-weight:bold;" - text.transform = "matrix(1 0 0 1 263 1953)" - text.value = "Design Variations" - group.texts?.append(text) - - text.style = "none;fill:black;font-family:-apple-system,\"SF Pro Display\",\"SF Pro Text\",Helvetica,sans-serif;" - text.transform = "matrix(1 0 0 1 263 1971)" - text.value = "Symbols are supported in up to nine weights and three scales." - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 263 1989)" - text.value = "For optimal layout with text and other symbols, vertically align" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 263 2007)" - text.value = "symbols with the adjacent text." - group.texts?.append(text) - - var rect = Rectangle(x: 776, y: 1919, width: 3, height: 14) - rect.style = "fill:#00AEEF;stroke:none;opacity:0.4;" - group.rectangles?.append(rect) - - path.data = "M 10.5273 0 L 12.373 0 L 7.17773 -14.0918 L 5.43945 -14.0918 L 0.244141 0 L 2.08984 0 L 3.50586 -4.0332 L 9.11133 -4.0332 Z M 6.2793 -11.9531 L 6.33789 -11.9531 L 8.59375 -5.52734 L 4.02344 -5.52734 Z" - subGroup.paths = [path] - subGroup.transform = "matrix(1 0 0 1 779 1933)" - group.groups?.append(subGroup) - - rect.x = 791.617 - group.rectangles?.append(rect) - - text.style = "stroke:none;fill:black;font-family:-apple-system,\"SF Pro Display\",\"SF Pro Text\",Helvetica,sans-serif;font-weight:bold;" - text.transform = "matrix(1 0 0 1 776 1953)" - text.value = "Margins" - group.texts?.append(text) - - text.style = "stroke:none;fill:black;font-family:-apple-system,\"SF Pro Display\",\"SF Pro Text\",Helvetica,sans-serif;" - text.transform = "matrix(1 0 0 1 776 1971)" - text.value = "Leading and trailing margins on the left and right side of each symbol" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 776 1989)" - text.value = "can be adjusted by modifying the width of the blue rectangles." - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 776 2007)" - text.value = "Modifications are automatically applied proportionally to all" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 776 2025)" - text.value = "scales and weights." - group.texts?.append(text) - - path.data = "M 2.83203 3.11523 L 4.375 4.6582 C 5.22461 5.48828 6.19141 5.41992 7.06055 4.46289 L 17.2754 -6.66016 C 17.7051 -6.36719 18.0957 -6.37695 18.5645 -6.47461 L 19.6094 -6.68945 L 20.3027 -5.99609 L 20.2539 -5.47852 C 20.1855 -4.95117 20.3516 -4.53125 20.8496 -4.0332 L 21.6602 -3.22266 C 22.168 -2.71484 22.8223 -2.68555 23.3008 -3.16406 L 26.5527 -6.41602 C 27.0312 -6.89453 27.0117 -7.54883 26.5039 -8.05664 L 25.6836 -8.87695 C 25.1855 -9.375 24.7754 -9.55078 24.2383 -9.47266 L 23.7109 -9.41406 L 23.0566 -10.0781 L 23.3398 -11.2207 C 23.4863 -11.7871 23.3398 -12.2559 22.7148 -12.8613 L 20.3027 -15.2539 C 16.7578 -18.7793 12.2266 -18.6719 9.11133 -15.5371 C 8.69141 -15.1074 8.64258 -14.5215 8.91602 -14.0918 C 9.15039 -13.7207 9.62891 -13.4961 10.2734 -13.6621 C 11.7871 -14.043 13.3008 -13.9258 14.7852 -12.9199 L 14.1602 -11.3379 C 13.9258 -10.752 13.9453 -10.2734 14.1797 -9.83398 L 3.01758 0.439453 C 2.08008 1.30859 1.97266 2.25586 2.83203 3.11523 Z M 10.6738 -15.1465 C 13.3398 -17.1387 16.6504 -16.8262 19.0527 -14.4141 L 21.6797 -11.8066 C 21.9141 -11.5723 21.9434 -11.3867 21.8848 -11.0938 L 21.5039 -9.53125 L 23.0762 -7.95898 L 24.043 -8.04688 C 24.3262 -8.07617 24.4141 -8.05664 24.6387 -7.83203 L 25.2637 -7.20703 L 22.5098 -4.46289 L 21.8848 -5.07812 C 21.6602 -5.30273 21.6406 -5.40039 21.6699 -5.68359 L 21.7578 -6.64062 L 20.1953 -8.20312 L 18.5742 -7.89062 C 18.291 -7.83203 18.1445 -7.83203 17.9102 -8.07617 L 15.7324 -10.2539 C 15.5078 -10.4883 15.4785 -10.625 15.6055 -10.9473 L 16.5527 -13.2227 C 14.9512 -14.7559 12.8418 -15.6055 10.8008 -14.9512 C 10.7129 -14.9219 10.6445 -14.9414 10.6152 -14.9805 C 10.5859 -15.0293 10.5859 -15.0781 10.6738 -15.1465 Z M 4.10156 2.41211 C 3.61328 1.91406 3.78906 1.61133 4.12109 1.30859 L 15.0781 -8.80859 L 16.3086 -7.57812 L 6.15234 3.34961 C 5.84961 3.68164 5.46875 3.7793 5.06836 3.37891 Z" - subGroup.paths = [path] - subGroup.transform = "matrix(1 0 0 1 1289 1933)" - group.groups?.append(subGroup) - - text.style = "stroke:none;fill:black;font-family:-apple-system,\"SF Pro Display\",\"SF Pro Text\",Helvetica,sans-serif;font-weight:bold;" - text.transform = "matrix(1 0 0 1 1289 1953)" - text.value = "Exporting" - group.texts?.append(text) - - text.style = "stroke:none;fill:black;font-family:-apple-system,\"SF Pro Display\",\"SF Pro Text\",Helvetica,sans-serif;" - text.transform = "matrix(1 0 0 1 1289 1971)" - text.value = "Symbols should be outlined when exporting to ensure the" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 1289 1989)" - text.value = "design is preserved when submitting to Xcode." - group.texts?.append(text) - - text.id = "template-version" - text.style = "stroke:none;fill:black;font-family:-apple-system,\"SF Pro Display\",\"SF Pro Text\",Helvetica,sans-serif;text-anchor:end;" - text.transform = "matrix(1 0 0 1 3036 1933)" - text.value = "Template v.2.0" - group.texts?.append(text) - - text.id = nil - text.transform = "matrix(1 0 0 1 3036 1969)" - text.value = "Typeset at 100 points" - group.texts?.append(text) - - text.style = "stroke:none;fill:black;font-family:-apple-system,\"SF Pro Display\",\"SF Pro Text\",Helvetica,sans-serif;" - text.transform = "matrix(1 0 0 1 263 726)" - text.value = "Small" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 263 1156)" - text.value = "Medium" - group.texts?.append(text) - - text.transform = "matrix(1 0 0 1 263 1586)" - text.value = "Large" - group.texts?.append(text) - - return group - } - - static var appleSymbolsGuides: Group { - var group = Group() - - group.id = "Guides" - group.groups = [] - group.lines = [] - - var hRef = Group() - hRef.id = "H-reference" - hRef.style = "fill:#27AAE1;stroke:none;" - hRef.transform = "matrix(1 0 0 1 339 696)" - hRef.paths = [Path(data: "M 54.9316 0 L 57.666 0 L 30.5664 -70.459 L 28.0762 -70.459 L 0.976562 0 L 3.66211 0 L 12.9395 -24.4629 L 45.7031 -24.4629 Z M 29.1992 -67.0898 L 29.4434 -67.0898 L 44.8242 -26.709 L 13.8184 -26.709 Z")] - group.groups?.append(hRef) - - var baseline = Line(x1: 263, y1: 696, x2: 3036, y2: 696) - baseline.id = "Baseline-S" - baseline.style = "fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.577;" - group.lines?.append(baseline) - - var capline = Line(x1: 263, y1: 625.541, x2: 3036, y2: 625.541) - capline.id = "Capline-S" - capline.style = "fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.577;" - group.lines?.append(capline) - - hRef.transform = "matrix(1 0 0 1 339 1126)" - hRef.paths = [Path(data: "M 54.9316 0 L 57.666 0 L 30.5664 -70.459 L 28.0762 -70.459 L 0.976562 0 L 3.66211 0 L 12.9395 -24.4629 L 45.7031 -24.4629 Z M 29.1992 -67.0898 L 29.4434 -67.0898 L 44.8242 -26.709 L 13.8184 -26.709 Z")] - group.groups?.append(hRef) - - baseline.id = "Baseline-M" - baseline.y1 = 1126 - baseline.y2 = 1126 - group.lines?.append(baseline) - - capline.id = "Capline-M" - capline.y1 = 1055.54 - capline.y2 = 1055.54 - group.lines?.append(capline) - - hRef.transform = "matrix(1 0 0 1 339 1556)" - hRef.paths = [Path(data: "M 54.9316 0 L 57.666 0 L 30.5664 -70.459 L 28.0762 -70.459 L 0.976562 0 L 3.66211 0 L 12.9395 -24.4629 L 45.7031 -24.4629 Z M 29.1992 -67.0898 L 29.4434 -67.0898 L 44.8242 -26.709 L 13.8184 -26.709 Z")] - group.groups?.append(hRef) - - baseline.id = "Baseline-L" - baseline.y1 = 1556 - baseline.y2 = 1556 - group.lines?.append(baseline) - - capline.id = "Capline-L" - capline.y1 = 1485.54 - capline.y2 = 1485.54 - group.lines?.append(capline) - - var margin = Line(x1: 1399.72, y1: 1030.79, x2: 1399.72, y2: 1150.12) - margin.id = "left-margin" - margin.style = "fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" - group.lines?.append(margin) - - margin = Line(x1: 1499.97, y1: 1030.79, x2: 1499.97, y2: 1150.12) - margin.id = "right-margin" - margin.style = "fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" - group.lines?.append(margin) - - return group - } - - static func appleSymbols(path: Path, in rect: Rect) throws -> Group { - var group = Group() - - group.id = "Symbols" - - let translations: [(name: String, size: Float, center: Point)] = [ - ("Ultralight-S", 0.75, .init(x: 559.0, y: 661.0)), - ("Thin-S", 0.76, .init(x: 857.0, y: 661.0)), - ("Light-S", 0.78, .init(x: 1153.0, y: 661.0)), - ("Regular-S", 0.79, .init(x: 1449.5, y: 661.0)), - ("Medium-S", 0.80, .init(x: 1747.0, y: 661.0)), - ("Semibold-S", 0.81, .init(x: 2043.0, y: 661.0)), - ("Bold-S", 0.82, .init(x: 2340.0, y: 661.0)), - ("Heavy-S", 0.85, .init(x: 2636.5, y: 661.0)), - ("Black-S", 0.86, .init(x: 2933.0, y: 661.0)), - ("Ultralight-M", 0.95, .init(x: 559.0, y: 1091.0)), - ("Thin-M", 0.96, .init(x: 857.0, y: 1091.0)), - ("Light-M", 0.98, .init(x: 1153.0, y: 1091.0)), - ("Regular-M", 1.00, .init(x: 1449.5, y: 1091.0)), - ("Medium-M", 1.02, .init(x: 1747.0, y: 1091.0)), - ("Semibold-M", 1.03, .init(x: 2043.0, y: 1091.0)), - ("Bold-M", 1.05, .init(x: 2340.0, y: 1091.0)), - ("Heavy-M", 1.07, .init(x: 2636.5, y: 1091.0)), - ("Black-M", 1.10, .init(x: 2933.0, y: 1091.0)), - ("Ultralight-L", 1.22, .init(x: 559.0, y: 1521.0)), - ("Thin-L", 1.24, .init(x: 857.0, y: 1521.0)), - ("Light-L", 1.26, .init(x: 1153.0, y: 1521.0)), - ("Regular-L", 1.28, .init(x: 1449.5, y: 1521.0)), - ("Medium-L", 1.30, .init(x: 1747.0, y: 1521.0)), - ("Semibold-L", 1.31, .init(x: 2043.0, y: 1521.0)), - ("Bold-L", 1.33, .init(x: 2340.0, y: 1521.0)), - ("Heavy-L", 1.36, .init(x: 2636.5, y: 1521.0)), - ("Black-L", 1.39, .init(x: 2933.0, y: 1521.0)), - ] - - group.groups = try translations.map { symbol -> Group in - let size = Size(width: 100.0 * symbol.size, height: 100.0 * symbol.size) - let to = Rect(origin: .zero, size: size) - let commands = try path.commands().map { $0.translate(from: rect, to: to) } - let p = Path(commands: commands) - let matrixOrigin = Point(x: symbol.center.x - size.width / 2.0, y: symbol.center.y - size.height / 2.0) - let matrix: Transformation = .matrix(a: 1, b: 0, c: 0, d: 1, e: matrixOrigin.x, f: matrixOrigin.y) - return Group(symbol.name, path: p, transform: matrix.description) - } - - return group - } -} - -private extension Group { - init(_ id: String, path: Path, transform: String) { - self.init() - self.id = id - self.transform = transform - paths = [path] - } -} diff --git a/third-party/VectorPlus/Sources/SVG+Template.swift b/third-party/VectorPlus/Sources/SVG+Template.swift deleted file mode 100644 index 6dbd962d84..0000000000 --- a/third-party/VectorPlus/Sources/SVG+Template.swift +++ /dev/null @@ -1,56 +0,0 @@ -import Foundation -import Swift2D -import SwiftSVG - -public extension SVG { - func asImageViewSubclass() throws -> String { - let instructions = try asCoreGraphicsDescription() - let renders = try asCGContextDescription() - - return imageViewSubclassTemplate - .replacingOccurrences(of: "{{name}}", with: name) - .replacingOccurrences(of: "{{width}}", with: String(format: "%.1f", originalSize.width)) - .replacingOccurrences(of: "{{height}}", with: String(format: "%.1f", originalSize.height)) - .replacingOccurrences(of: "{{instructions}}", with: instructions) - .replacingOccurrences(of: "{{render}}", with: renders) - } -} - -private extension SVG { - func asCoreGraphicsDescription(variable: String = "path") throws -> String { - try subpaths().map { try $0.asCoreGraphicsDescription(variable: variable, originalSize: originalSize) }.joined(separator: "\n ") - } - - func asCGContextDescription() throws -> String { - var outputs: [String] = [] - - let paths = try subpaths() - try paths.forEach { path in - let instructions = try path.asCoreGraphicsDescription(variable: "path", originalSize: originalSize) - let fillColor = path.fill?.pigment?.coreGraphicsDescription ?? "nil" - let fillOpacity = (path.fillOpacity != nil) ? "\(path.fillOpacity!)" : "nil" - let fillRule = (path.fillRule ?? .nonZero).coreGraphicsDescription - let strokeColor = path.stroke?.pigment?.coreGraphicsDescription ?? "nil" - let strokeOpacity = (path.strokeOpacity != nil) ? "\(path.strokeOpacity!)" : "nil" - let strokeWidth = (path.strokeWidth != nil) ? "\(path.strokeWidth!) * (size.width / width)" : "nil" - let strokeLineCap = (path.strokeLineCap != nil) ? "\(path.strokeLineCap!.coreGraphicsDescription)" : "nil" - let strokeLineJoin = (path.strokeLineJoin != nil) ? "\(path.strokeLineJoin!.coreGraphicsDescription)" : "nil" - let strokeMiterLimit = (path.strokeMiterLimit != nil) ? "\(path.strokeMiterLimit!)" : "nil" - - outputs.append(contextTemplate - .replacingOccurrences(of: "{{instructions}}", with: instructions) - .replacingOccurrences(of: "{{fillColor}}", with: fillColor) - .replacingOccurrences(of: "{{fillOpacity}}", with: fillOpacity) - .replacingOccurrences(of: "{{fillRule}}", with: fillRule) - .replacingOccurrences(of: "{{strokeColor}}", with: strokeColor) - .replacingOccurrences(of: "{{strokeOpacity}}", with: strokeOpacity) - .replacingOccurrences(of: "{{strokeWidth}}", with: strokeWidth) - .replacingOccurrences(of: "{{strokeLineCap}}", with: strokeLineCap) - .replacingOccurrences(of: "{{strokeLineJoin}}", with: strokeLineJoin) - .replacingOccurrences(of: "{{strokeMiterLimit}}", with: strokeMiterLimit) - ) - } - - return outputs.joined(separator: "\n ") - } -} diff --git a/third-party/VectorPlus/Sources/Size+VectorPlus.swift b/third-party/VectorPlus/Sources/Size+VectorPlus.swift deleted file mode 100644 index 3ec4a7bbd4..0000000000 --- a/third-party/VectorPlus/Sources/Size+VectorPlus.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Swift2D - -public extension Size { - var coreGraphicsDescription: String { - "CGSize(width: \(width), height: \(height))" - } -} diff --git a/third-party/VectorPlus/Sources/Stroke+VectorPlus.swift b/third-party/VectorPlus/Sources/Stroke+VectorPlus.swift deleted file mode 100644 index 0d933d2aca..0000000000 --- a/third-party/VectorPlus/Sources/Stroke+VectorPlus.swift +++ /dev/null @@ -1,40 +0,0 @@ -import SwiftColor -import SwiftSVG - -public extension Stroke { - @available(*, deprecated, renamed: "pigment") - var swiftColor: Pigment? { pigment } - - var pigment: Pigment? { - guard let color, !color.isEmpty else { - return nil - } - - let _color = Pigment(color) - guard _color.alpha != 0.0 else { - return nil - } - - return _color - } -} - -public extension Stroke.LineCap { - var coreGraphicsDescription: String { - switch self { - case .butt: ".butt" - case .round: ".round" - case .square: ".square" - } - } -} - -public extension Stroke.LineJoin { - var coreGraphicsDescription: String { - switch self { - case .bevel: ".bevel" - case .arcs, .miter, .miterClip: ".miter" - case .round: ".round" - } - } -} diff --git a/third-party/VectorPlus/Sources/Template+UIImageView.swift b/third-party/VectorPlus/Sources/Template+UIImageView.swift deleted file mode 100644 index a6b03c8f47..0000000000 --- a/third-party/VectorPlus/Sources/Template+UIImageView.swift +++ /dev/null @@ -1,177 +0,0 @@ -let imageViewSubclassTemplate: String = """ -#if canImport(UIKit) -import UIKit - -@IBDesignable -public class {{name}}: UIImageView { - - public static let width: CGFloat = {{width}} - public static let height: CGFloat = {{height}} - public let width: CGFloat = {{width}} - public let height: CGFloat = {{height}} - - public var widthToHeightAspectRatio: CGFloat { - guard width != .nan, width > 0.0 else { - return 0.0 - } - - guard height != .nan, height > 0.0 else { - return 0.0 - } - - return width / height - } - - public var heightToWidthAspectRatio: CGFloat { - guard height != .nan, height > 0.0 else { - return 0.0 - } - - guard width != .nan, width > 0.0 else { - return 0.0 - } - - return height / width - } - - public override init(frame: CGRect) { - super.init(frame: frame) - updateSubviews() - } - - public required init?(coder: NSCoder) { - super.init(coder: coder) - updateSubviews() - } - - public override var intrinsicContentSize: CGSize { - return CGSize(width: width, height: height) - } - - public override var bounds: CGRect { - didSet { - updateSubviews() - } - } - - public override func prepareForInterfaceBuilder() { - super.prepareForInterfaceBuilder() - updateSubviews() - } - - public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - updateSubviews() - } - - public func updateSubviews() { - image = Self.image(size: bounds.size) - } - - public static func path(size: CGSize) -> CGPath { - guard size.height > 0.0 && size.width > 0.0 else { - return CGMutablePath() - } - - let radius = max(size.width / 2.0, size.height / 2.0) - let center = CGPoint(x: size.width / 2.0, y: size.height / 2.0) - - let path = CGMutablePath() - {{instructions}} - return path - } - - public static func image(size: CGSize) -> UIImage? { - guard size.height > 0.0 && size.width > 0.0 else { - return nil - } - - let radius = max(size.width / 2.0, size.height / 2.0) - let center = CGPoint(x: size.width / 2.0, y: size.height / 2.0) - - defer { - UIGraphicsEndImageContext() - } - - UIGraphicsBeginImageContextWithOptions(size, false, 0.0) - - guard let context = UIGraphicsGetCurrentContext() else { - return nil - } - - {{render}} - - return UIGraphicsGetImageFromCurrentImageContext() - } - - private static func radians(_ degree: Float) -> CGFloat { - return CGFloat(degree) * (.pi / CGFloat(180)) - } -} - -private extension CGContext { - func rendering(_ block: (CGContext) -> Void) { - block(self) - } -} - -#endif - -""" - -let contextTemplate: String = """ - context.rendering { (ctx) in - ctx.saveGState() - - let path = CGMutablePath() - {{instructions}} - - let defaultColor: CGColor = CGColor(srgbRed: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) - let pathFillColor: CGColor? = {{fillColor}} - let pathFillOpacity: CGFloat? = {{fillOpacity}} - let pathFillRule: CGPathFillRule = {{fillRule}} - let pathStrokeColor: CGColor? = {{strokeColor}} - let pathStrokeOpacity: CGFloat? = {{strokeOpacity}} - let pathStrokeWidth: CGFloat? = {{strokeWidth}} - let pathStrokeLineCap: CGLineCap? = {{strokeLineCap}} - let pathStrokeLineJoin: CGLineJoin? = {{strokeLineJoin}} - let pathStrokeMiterLimit: CGFloat? = {{strokeMiterLimit}} - - if pathFillColor != nil && pathFillOpacity != nil { - let opacity = pathFillOpacity ?? 1.0 - let color = (pathFillColor ?? defaultColor).copy(alpha: opacity) ?? defaultColor - - ctx.setFillColor(color) - ctx.addPath(path) - ctx.fillPath(using: pathFillRule) - } - - if pathStrokeColor != nil && pathStrokeOpacity != nil { - let opacity = pathStrokeOpacity ?? 1.0 - let color = (pathStrokeColor ?? defaultColor).copy(alpha: opacity) ?? defaultColor - let lineWidth = pathStrokeWidth ?? 1.0 - - ctx.setLineWidth(lineWidth) - ctx.setStrokeColor(color) - if let lineCap = pathStrokeLineCap { - ctx.setLineCap(lineCap) - } - if let lineJoin = pathStrokeLineJoin { - ctx.setLineJoin(lineJoin) - if let miterLimit = pathStrokeMiterLimit, lineJoin == .miter { - ctx.setMiterLimit(miterLimit) - } - } - ctx.addPath(path) - ctx.strokePath() - } - - if (pathFillColor == nil && pathFillOpacity == nil) && (pathStrokeColor == nil && pathStrokeOpacity == nil) { - ctx.setFillColor(defaultColor) - ctx.addPath(path) - ctx.fillPath(using: pathFillRule) - } - - ctx.restoreGState() - } -""" diff --git a/third-party/VectorPlus/Sources/UIKit/SVG+UIImage.swift b/third-party/VectorPlus/Sources/UIKit/SVG+UIImage.swift deleted file mode 100644 index ea336be4f7..0000000000 --- a/third-party/VectorPlus/Sources/UIKit/SVG+UIImage.swift +++ /dev/null @@ -1,43 +0,0 @@ -#if canImport(UIKit) -import Swift2D -import SwiftSVG -import UIKit - -public extension SVG { - func uiImage(size: Size) -> UIImage? { - guard size.height > 0.0, size.width > 0.0 else { - return nil - } - - let from = Rect(origin: .zero, size: originalSize) - let to = Rect(origin: .zero, size: size) - - let paths: [Path] - do { - paths = try subpaths() - } catch { - return nil - } - - defer { - UIGraphicsEndImageContext() - } - - UIGraphicsBeginImageContextWithOptions(CGSize(size), false, 0.0) - - guard let context = UIGraphicsGetCurrentContext() else { - return nil - } - - for path in paths { - try? context.render(path: path, from: from, to: to) - } - - return UIGraphicsGetImageFromCurrentImageContext() - } - - func pngData(size: Size) -> Data? { - uiImage(size: size)?.pngData() - } -} -#endif diff --git a/third-party/VectorPlus/Sources/UIKit/SVGImageView.swift b/third-party/VectorPlus/Sources/UIKit/SVGImageView.swift deleted file mode 100644 index b5131c915a..0000000000 --- a/third-party/VectorPlus/Sources/UIKit/SVGImageView.swift +++ /dev/null @@ -1,81 +0,0 @@ -import Swift2D -import SwiftSVG -#if canImport(UIKit) && !os(watchOS) -import UIKit - -@IBDesignable open class SVGImageView: UIImageView { - - public var width: CGFloat { - CGFloat(svg.originalSize.width) - } - - public var height: CGFloat { - CGFloat(svg.originalSize.height) - } - - open var svg: SVG = SVG() { - didSet { - updateSubviews() - } - } - - public var widthToHeightAspectRatio: CGFloat { - guard !width.isNaN, width > 0.0 else { - return 0.0 - } - - guard !height.isNaN, height > 0.0 else { - return 0.0 - } - - return width / height - } - - public var heightToWidthAspectRatio: CGFloat { - guard !height.isNaN, height > 0.0 else { - return 0.0 - } - - guard !width.isNaN, width > 0.0 else { - return 0.0 - } - - return height / width - } - - override public init(frame: CGRect) { - super.init(frame: frame) - updateSubviews() - } - - public required init?(coder: NSCoder) { - super.init(coder: coder) - updateSubviews() - } - - override public var intrinsicContentSize: CGSize { - CGSize(width: width, height: height) - } - - override public var bounds: CGRect { - didSet { - updateSubviews() - } - } - - override public func prepareForInterfaceBuilder() { - super.prepareForInterfaceBuilder() - updateSubviews() - } - - override public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - updateSubviews() - } - - public func updateSubviews() { - image = svg.uiImage(size: Size(bounds.size)) - } -} - -#endif diff --git a/third-party/VectorPlus/Sources/VectorPoint.swift b/third-party/VectorPlus/Sources/VectorPoint.swift deleted file mode 100644 index 91f81b1d20..0000000000 --- a/third-party/VectorPlus/Sources/VectorPoint.swift +++ /dev/null @@ -1,126 +0,0 @@ -import Swift2D - -/// A cartesian-based struct that describes the relationship of any particular `Point` to the _origin_ of a `Rect`. -public struct VectorPoint { - public enum Sign: String { - case plus = "+" - case minus = "-" - } - - public typealias Offset = (sign: Sign, multiplier: Double) - - public var x: Offset - public var y: Offset - - public init(x: Offset, y: Offset) { - self.x = x - self.y = y - } - - /// Initializes a `VectorPoint` for a given `Point` container in the provided `Rect`. - public init(point: Point, in rect: Rect) { - let radius = rect.size.maxRadius - let cartesianPoint = Self.cartesianPoint(for: point, in: rect) - - if cartesianPoint.x < 0 { - x = (.minus, abs(cartesianPoint.x) / radius) - } else { - x = (.plus, cartesianPoint.x / radius) - } - - if cartesianPoint.y < 0 { - y = (.plus, abs(cartesianPoint.y) / radius) - } else { - y = (.minus, cartesianPoint.y / radius) - } - } -} - -// MARK: - CustomStringConvertible - -extension VectorPoint: CustomStringConvertible { - public var description: String { - "VectorPoint(x: (\(x.sign.rawValue), \(x.multiplier)), y: (\(y.sign.rawValue), \(y.multiplier)))" - } -} - -// MARK: - Equatable - -extension VectorPoint: Equatable { - public static func == (lhs: VectorPoint, rhs: VectorPoint) -> Bool { - guard lhs.x.sign == rhs.x.sign else { - return false - } - guard lhs.x.multiplier == rhs.x.multiplier else { - return false - } - guard lhs.y.sign == rhs.y.sign else { - return false - } - guard lhs.y.multiplier == rhs.y.multiplier else { - return false - } - - return true - } -} - -// MARK: - - -public extension VectorPoint { - /// Translates the provided point within the `Rect` from using the top-left - /// as the _origin_, to using the center as the _origin_. - /// - /// For example: Given `Rect(x: 0, y: 0, width: 100, height: 100)`, the point - /// `Point(x: 25, y: 25)` would translate to `Point(x: -25, y: 25)`. - static func cartesianPoint(for point: Point, in rect: Rect) -> Point { - let origin = Point(x: rect.size.width / 2.0, y: rect.size.height / 2.0) - var cartesianPoint: Point = .zero - - if point.x < origin.x { - cartesianPoint = cartesianPoint.x(-(origin.x - point.x)) - } else if point.x > origin.x { - cartesianPoint = cartesianPoint.x(point.x - origin.x) - } - - if point.y > origin.y { - cartesianPoint = cartesianPoint.y(-(point.y - origin.y)) - } else if point.y < origin.y { - cartesianPoint = cartesianPoint.y(origin.y - point.y) - } - - return cartesianPoint - } -} - -// MARK: - Instance Functionality - -public extension VectorPoint { - /// Calculates the `Point` for this instance in the specified `Rect`. - func translate(to rect: Rect) -> Point { - translate(to: rect.size) - } - - /// Calculates the `Point` in the desired output size - func translate(to outputSize: Size) -> Point { - let center = outputSize.center - let radius = outputSize.minRadius - - switch (x.sign, y.sign) { - case (.plus, .plus): - return Point(x: center.x + (radius * x.multiplier), y: center.y + (radius * y.multiplier)) - case (.plus, .minus): - return Point(x: center.x + (radius * x.multiplier), y: center.y - (radius * y.multiplier)) - case (.minus, .plus): - return Point(x: center.x - (radius * x.multiplier), y: center.y + (radius * y.multiplier)) - case (.minus, .minus): - return Point(x: center.x - (radius * x.multiplier), y: center.y - (radius * y.multiplier)) - } - } -} - -public extension VectorPoint { - var coreGraphicsDescription: String { - "CGPoint(x: center.x \(x.sign.rawValue) (radius * \(x.multiplier)), y: center.y \(y.sign.rawValue) (radius * \(y.multiplier)))" - } -} From f7dcf20f698bd1b20947953d8a5d4b9b54106629 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 16:27:20 +0200 Subject: [PATCH 03/14] Add design spec: context controller portal-view transition Replaces CCEPN's manual visible-area clipping with a portal-based transition mirroring CMTN's primitive. Adds optional sourceTransitionSurface to TakeViewInfo/PutBackInfo; chat is the first adopter. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...5-context-controller-portal-view-design.md | 295 ++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-05-context-controller-portal-view-design.md diff --git a/docs/superpowers/specs/2026-05-05-context-controller-portal-view-design.md b/docs/superpowers/specs/2026-05-05-context-controller-portal-view-design.md new file mode 100644 index 0000000000..2c4292866f --- /dev/null +++ b/docs/superpowers/specs/2026-05-05-context-controller-portal-view-design.md @@ -0,0 +1,295 @@ +# Context controller — portal-view transition (replaces visible-area clipping) + +Date: 2026-05-05 +Status: Design approved; pending implementation plan. + +## Problem + +`ContextControllerExtractedPresentationNode` (CCEPN) animates an extracted bubble in/out of the context menu by reparenting the source's `contentNode`/`contentView` into its own `offsetContainerNode` and then animating a separate `clippingNode` frame to interpolate between the chat's content area and the full screen. The clipping animation is what keeps the bubble from visibly bleeding past chat boundaries (navigation bar above, input panel below) during the transition. + +Two problems with that approach: + +1. **Boundary artifacts.** Bubbles with shadows or rounded corners get visibly cut at the chat content-area edges during the in/out transition — the manual clip rectangle doesn't honor the actual ancestor masking shape. +2. **No live source-side dynamics.** The clip animation is computed once at animation start using `contentAreaInScreenSpace`. If the chat scrolls, the navigation-bar height changes, the input panel's keyboard rises, etc. mid-animation, the manually animated `clippingNode` frame goes stale; the visible clip drifts away from where the chat would actually clip the bubble. + +Both classes of issue go away if the bubble is rendered through a primitive that already exists in the codebase: a `PortalSourceView` whose layer tree is mirrored to a `PortalView` at a different Z position. `ChatMessageTransitionNode` already uses this pattern for message-send animations. CCEPN should use the same primitive for extraction transitions. + +## Solution overview + +During the in/out transition, the source's `contentNode` is reparented into a `sourceTransitionSurface: UIView` that the source provides — a view in its own hierarchy where ancestor clipping (chat content area) applies naturally. CCEPN wraps it with a `PortalSourceView` and adds a `PortalView(matchPosition: true)` clone into `ItemContentNode.offsetContainerNode` (in the overlay tree). The clone tracks the wrapper's screen-space frame automatically. + +CCEPN keeps applying the same spring/position/transform animation values it computes today, but retargets them onto the wrapper's layer instead of `contentNode.layer` / `offsetContainerNode.layer`. Because the wrapper is in the chat tree, its frame changes (and the chat's real-time re-layout) flow through the portal mirror to the visible clone. The manual `clippingNode.layer.animateFrame(...)` calls become unnecessary on this path. + +After the in-animation completes, the `contentNode` is reparented out of the wrapper into `offsetContainerNode` (today's resting state). Portal staging is torn down. On dismiss, the inverse: contentNode is reparented from `offsetContainerNode` into the (fresh) `putBackInfo.sourceTransitionSurface`, the wrapper + clone are reconstructed, the dismiss animation runs against the wrapper's layer, and on completion contentNode is reparented home (its original chat-side parent). + +The new path is opt-in. When `sourceTransitionSurface == nil`, CCEPN falls back to today's `clippingNode.layer.animateFrame(...)` behavior. Existing `ContextExtractedContentSource` adopters that don't pass a surface keep working unchanged. + +## Scope + +**In scope.** The `.extracted` `ContentSource` case in CCEPN. Two struct fields. One file-local helper inside CCEPN. Adoption in two of the four `ContextExtractedContentSource` types in `submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift` — `ChatMessageContextExtractedContentSource` (regular bubble long-press) and `ChatMessageReactionContextExtractedContentSource` (reaction context). + +**Out of scope.** +- `.reference`, `.location`, `.controller` source cases. They never reparent `contentNode` and don't have analogous boundary issues. Their `clippingNode.animateFrame(...)` calls (where present) stay unchanged. +- `ChatViewOnceMessageContextExtractedContentSource`. Has a private `messageNodeCopy` and a custom dust-effect dismiss path that's structurally different. +- `ChatMessageNavigationButtonContextExtractedContentSource`. Stays on the fallback path; not part of this change. +- The `ChatMessageTransitionNode` portal usage itself. We adopt the same primitive; we do not refactor CMTN. +- `maskView` semantics on `TakeViewInfo`/`PutBackInfo`. Unchanged; the portal path doesn't use it. + +## Public-API changes — `submodules/ContextUI/Sources/ContextController.swift` + +```swift +public final class ContextControllerTakeViewInfo { + public enum ContainingItem { case node(...) ; case view(...) } + + public let containingItem: ContainingItem + public let contentAreaInScreenSpace: CGRect + public let maskView: UIView? + public let sourceTransitionSurface: UIView? // NEW + + public init( + containingItem: ContainingItem, + contentAreaInScreenSpace: CGRect, + maskView: UIView? = nil, + sourceTransitionSurface: UIView? = nil // NEW, defaults nil + ) +} + +public final class ContextControllerPutBackViewInfo { + public let contentAreaInScreenSpace: CGRect + public let maskView: UIView? + public let sourceTransitionSurface: UIView? // NEW + + public init( + contentAreaInScreenSpace: CGRect, + maskView: UIView? = nil, + sourceTransitionSurface: UIView? = nil // NEW, defaults nil + ) +} +``` + +**Source-side contract** when `sourceTransitionSurface != nil`: + +- The view MUST be attached to a window-bearing tree at the moment the source returns it. +- Its on-screen frame MUST already reflect current chat layout (the chat's existing layout pass owns this). +- The source MUST NOT remove or move it before the corresponding transition completes (the in-animation for `TakeViewInfo`; the dismiss animation for `PutBackInfo`). CCEPN owns reparenting cleanup. +- A single surface may be reused across `takeView` and `putBack` (and across multiple presentations). The chat owns one shared `transitionContainer: UIView` per `ChatControllerNode`. + +The default `nil` is what makes this a strictly additive change for every existing adopter. + +## `PortalTransitionStaging` — file-local helper inside CCEPN + +A new private class in `submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift`. Single instance per `ItemContentNode`, non-nil only while a transition is in flight. Encapsulates the wrapper + clone lifecycle so CCEPN's animation code never observes a half-staged state. + +```swift +private final class PortalTransitionStaging { + enum OriginalParent { + case node(ASDisplayNode) // contentNode.supernode at staging time + case view(UIView) // contentView.superview at staging time + } + + weak var surface: UIView? + var wrapper: PortalSourceView? + var clone: PortalView? + var originalParentSnapshot: OriginalParent? + + /// Sets up staging and returns the layer the caller should animate. Returns nil + /// (and leaves staging untouched) if `PortalView(matchPosition:)` cannot be + /// instantiated — caller falls back to the clipping path. + /// + /// Side effects on success: + /// - records `originalParentSnapshot` from the containingItem's current parent + /// - constructs `wrapper = PortalSourceView()` and adds it to `surface` + /// - reparents the containingItem's contentNode/contentView into `wrapper` + /// - constructs `clone = PortalView(matchPosition: true)` and adds its view into `overlayHost` + /// - calls `wrapper.addPortal(view: clone)` + /// - sets `wrapper.frame` so the contentNode's screen-space rect equals + /// `targetScreenRect` (via `surface.convert(targetScreenRect, from: nil)`) + func enter( + for containingItem: ContextControllerTakeViewInfo.ContainingItem, + in surface: UIView, + overlayHost: UIView, + targetScreenRect: CGRect + ) -> CALayer? + + enum SettleDestination { + case offsetContainer(ASDisplayNode) // resting parent for animateIn end + case original // restore from originalParentSnapshot + } + + /// Tears down staging. Reparents contentNode into the requested destination, + /// removes the clone from its host, removes the wrapper from `surface`. + /// All reparenting is synchronous; no CATransaction is needed because all + /// animations in this codebase are explicit `animate*` calls — there are no + /// implicit CALayer actions to suppress. + func settle(into: SettleDestination, presentationScale: CGFloat) +} +``` + +**Invariant** (asserted on `enter`): `contentNode.portalStaging != nil` ⇒ contentNode parent is `staging.wrapper`. + +If CCEPN re-enters animateIn or animateOut while staging is non-nil (defensive case — shouldn't happen at runtime), the new branch tears down the existing staging via `settle(into: .offsetContainer, ...)` first, then proceeds with its own `enter(...)`. + +## CCEPN integration + +Three edit points in `ContextControllerExtractedPresentationNode.swift`. The portal-mode branch lives next to the existing clipping branch in each animateIn / animateOut path. + +### `ItemContentNode` — one new property + +```swift +private final class ItemContentNode: ASDisplayNode { + // ...existing fields unchanged... + var portalStaging: PortalTransitionStaging? // NEW +} +``` + +### `case .animateIn:` (currently lines ~1265–1474) + +At the top of `if let contentNode = itemContentNode { ... }`: + +```swift +if let surface = takeInfo.sourceTransitionSurface { + let staging = PortalTransitionStaging() + // `targetScreenRect`: the bubble's resting end-of-animateIn rect in window coords + // (i.e. its menu-extracted position) — derived from today's `currentContentLocalFrame` + // (already in self.view coords) via `self.view.convert(_, to: nil)`. + let targetScreenRect = self.view.convert(currentContentLocalFrame, to: nil) + if let _ = staging.enter( + for: contentNode.containingItem, + in: surface, + overlayHost: contentNode.offsetContainerNode.view, + targetScreenRect: targetScreenRect + ) { + contentNode.portalStaging = staging + } +} + +let animatedLayer: CALayer = contentNode.portalStaging?.wrapper?.layer ?? contentNode.layer +``` + +The existing `if let animateClippingFromContentAreaInScreenSpace = contentNode.animateClippingFromContentAreaInScreenSpace { ... self.clippingNode.layer.animateFrame(...) ... self.clippingNode.layer.animateBoundsOriginYAdditive(...) }` block is wrapped in `if contentNode.portalStaging == nil { ... }` — clip animation only fires on the fallback path. + +The four spring `animateSpring(... keyPath: "position.x" / "position.y" ...)` calls today applied to `contentNode.layer` (and the reactionPreview spring twin) target `animatedLayer` instead. Same delta values (`animationInContentXDistance`, `animationInContentYDistance`), same spring params (`damping: springDamping`, `duration: 0.42`, etc.). + +A completion handler is attached to the longest-lived spring (`position.y` on the contentNode/wrapper): + +```swift +{ [weak self] _ in + guard let strongSelf = self, let contentNode = strongSelf.itemContentNode else { return } + contentNode.portalStaging?.settle( + into: .offsetContainer(contentNode.offsetContainerNode), + presentationScale: contentNode.presentationScale + ) + contentNode.portalStaging = nil +} +``` + +`presentationScale` re-application: while contentNode was inside the wrapper (in chat tree), the chat ancestor's scale was already in effect — the existing `CATransform3DMakeScale(detectedScale, detectedScale, 1.0)` compensation must NOT be applied during staging. After reparenting back into the unscaled `offsetContainerNode`, `settle(...)` reapplies it on `offsetContainerNode.layer.transform`. (Today's code applies it once at construction in lines ~647–649; on the portal path, it shifts to staging-settle time.) + +### `case .animateOut:` (currently lines ~1487–1684) + +Symmetric. After computing `putBackInfo`: + +```swift +if let putBackInfo, let surface = putBackInfo.sourceTransitionSurface { + let staging = PortalTransitionStaging() + // `targetScreenRect`: the bubble's resting end-of-animateOut rect in window coords + // (i.e. its source position back in chat) — derived from `currentContentScreenFrame` + // (in self.view coords, despite the name) via `self.view.convert(_, to: nil)`. + let targetScreenRect = self.view.convert(currentContentScreenFrame, to: nil) + if let _ = staging.enter( + for: contentNode.containingItem, + in: surface, + overlayHost: contentNode.offsetContainerNode.view, + targetScreenRect: targetScreenRect + ) { + contentNode.portalStaging = staging + } +} + +let animatedLayer: CALayer = contentNode.portalStaging?.wrapper?.layer ?? contentNode.offsetContainerNode.layer +``` + +The two `self.clippingNode.layer.animateFrame(...) / animateBoundsOriginYAdditive(...)` blocks (in the `.location`, `.reference`, `.extracted` arms of the source switch) are guarded by `contentNode.portalStaging == nil`. Note: only the `.extracted` arm can have staging; `.location` and `.reference` never set `sourceTransitionSurface`, so this guard simplifies cleanly. + +The dismiss spring on `contentNode.offsetContainerNode.layer` (`position.x` and `position.y`, lines ~1644 and ~1657) targets `animatedLayer` instead. The completion handler at ~1665 currently does: + +```swift +switch contentNode.containingItem { +case let .node(containingNode): containingNode.addSubnode(containingNode.contentNode) +case let .view(containingView): containingView.addSubview(containingView.contentView) +} +``` + +When staging is active, the manual reparenting is replaced by `contentNode.portalStaging?.settle(into: .original, presentationScale: contentNode.presentationScale)` followed by `contentNode.portalStaging = nil`. The flag-clearing (`isExtractedToContextPreview = false` etc.) and `restoreOverlayViews.forEach { $0() }` cleanup stay where they are. + +### Unchanged + +- `willUpdateIsExtractedToContextPreview?(...)` callbacks at lines 1462 and 1623 fire at the same point, with the same arguments. The chat does not need to know we're using a portal. +- The overlay-views snapshot logic at lines 1476–1486 (animateIn) and 1596–1618 (animateOut) references `itemContentNode.supernode` / `itemContentNode.view` — `itemContentNode` itself stays in the scrollNode regardless of staging, so these blocks need no edits. +- All other animations on `actionsContainerNode`, `additionalActionsStackNode`, `reactionContextNode`, etc. are untouched. + +## First adopter — chat message extraction + +Two of the three sources in `submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift`: + +- `ChatMessageContextExtractedContentSource` (regular bubble long-press menu) +- `ChatMessageReactionContextExtractedContentSource` (reaction context) + +Both already return `chatNode.convert(chatNode.frameForVisibleArea(), to: nil)` as their `contentAreaInScreenSpace`. Each gains one new field on the `TakeViewInfo`/`PutBackInfo` constructor: `sourceTransitionSurface: chatNode.ensureContextTransitionContainer()`. + +`ChatMessageNavigationButtonContextExtractedContentSource` and `ChatViewOnceMessageContextExtractedContentSource` are NOT adopted in this change; they continue to pass `sourceTransitionSurface = nil` (i.e. the default). + +### `ChatControllerNode.contextTransitionContainer` + +A single lazy view per chat node, owned by `ChatControllerNode`: + +```swift +// in ChatControllerNode (private): +private var contextTransitionContainer: UIView? + +func ensureContextTransitionContainer() -> UIView { + if let existing = self.contextTransitionContainer { return existing } + let v = UIView() + v.clipsToBounds = true + v.isUserInteractionEnabled = false + self.view.insertSubview(v, aboveSubview: self.historyNode.view) + self.contextTransitionContainer = v + return v +} +``` + +**Frame management.** Sized to `frameForVisibleArea()` and updated whenever the chat's layout changes. The chat's existing layout pass already updates that rect; the container's frame mirrors it. This is what gives us issue B's win: live re-layout flows through the surface, into the wrapped contentNode, into the portal mirror. + +**Z-order check.** Inserting above `historyNode.view` matches the bubble's natural Z. When implementing, verify the input panel and navigation chrome render *over* the surface (so an extracted bubble visually tucks under them just as the in-place bubble does). If a chrome element lands below the surface in the live z-order, adjust `insertSubview(_, belowSubview:)` accordingly. This is a per-implementation check, not an open design question. + +## Edge cases + +- **`PortalView(matchPosition:)` returns nil.** `_UIPortalView` is private API; if it can't be instantiated, `staging.enter(...)` returns nil. CCEPN treats that exactly like `sourceTransitionSurface == nil` and takes the today's-clipping path. No half-staged state. +- **Surface deallocates mid-transition.** `surface` is captured weakly. If it goes away while the spring is running, the portal mirror renders nothing (UIKit handles a missing portal source). The spring completion still fires from the wrapper's layer (still alive in the staging instance) and `settle(...)` walks defensive — if `wrapper.superview == nil` it reparents contentNode into the destination and bails on portal teardown. Visual is degraded for the remainder of the transition; no leaks or crashes. +- **Animation interrupts itself.** If CCEPN is asked to `.animateOut` while `.animateIn` staging is still live (menu dismissed during open), the animateOut branch first calls `settle(into: .offsetContainer, ...)` on the existing staging, clears `portalStaging`, then performs its own `enter(...)`. The "staging non-nil ⇒ contentNode is in wrapper" invariant from above makes this safe. +- **`presentationScale != 1.0`.** Discussed above. The existing scale compensation (lines 642–650) is applied at staging-settle time on the portal path, not at construction time. +- **Chat scrolls during in-animation.** This is the issue-B win: while contentNode is in the wrapper inside `transitionContainer` (whose frame tracks `frameForVisibleArea()`), chat re-layout naturally re-clips the wrapper's content. The portal mirror reflects the live-clipped state. + +## Verification + +No unit tests exist in this project. Verification is manual. + +1. **Build.** Full project build per CLAUDE.md, with `--continueOnError` to surface a multi-file failure set in one pass. +2. **Issue A — boundary clipping.** Long-press a message at the top of the chat (bubble overlapping nav bar) and at the bottom (overlapping input panel). On `master` the bubble visibly cuts at chat content-area edges during the in/out transition. On this branch the cut should follow the chat's actual ancestor mask shape (no straight-line stutter at the manual-clip rect edge). +3. **Issue B — live source dynamics.** Long-press a message and induce a chat layout change mid-animation (e.g. bring up the keyboard, scroll). The visible bubble's clipping should track the chat's live state, not a stale snapshot. +4. **Reaction context.** Open the reaction context on a message; same in/out paths exercised. +5. **Fallback path.** Long-press in a non-bubble extracted source (the search title accessory panel via `ChatSearchTitleAccessoryPanelNode`, the overlay audio player via `OverlayAudioPlayerControllerNode`, and the navigation button via `ChatMessageNavigationButtonContextExtractedContentSource`). All three pass `sourceTransitionSurface = nil` and should behave identically to today. +6. **`ChatViewOnceMessageContextExtractedContentSource`.** Open a play-once voice/video message context. Stays on fallback; dust-effect dismiss path unchanged. + +## Files touched + +- `submodules/ContextUI/Sources/ContextController.swift` — two struct field additions. +- `submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift` — `PortalTransitionStaging` helper, three integration points, one new field on `ItemContentNode`. +- `submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift` — `sourceTransitionSurface` argument added at four call sites (two `takeView`, two `putBack`, across two source classes). +- `submodules/TelegramUI/Sources/ChatControllerNode.swift` — `contextTransitionContainer` storage, `ensureContextTransitionContainer()`, frame updates within the existing layout pass. + +## Risks + +- The `_UIPortalView` private-API path is already in production use via `ChatMessageTransitionNode`, so no net new private-API surface. +- The biggest risk is a regression on the fallback path — i.e. accidentally changing behavior for sources that don't pass a `sourceTransitionSurface`. The design preserves today's clip-animation block verbatim, gated only on `portalStaging == nil`. Reviewers should confirm every existing animation call site still fires unchanged when staging is nil. +- Z-order between `transitionContainer` and the chat's chrome elements (input panel, nav, overlay audio bar) needs a per-element visual check at implementation time. Listed under "First adopter" above. From 797326d6699376db68f489b6ed23b3f0f3edb170 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 16:41:05 +0200 Subject: [PATCH 04/14] Add design spec for ShimmeringMaskView Reusable view that applies a moving alpha-mask shimmer (rest=1.0, dip=peakAlpha) to its contentView. First consumer: the streaming-status text node in ChatMessageTextBubbleContentNode for ChatGPT-style "thinking" effect. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../2026-05-05-shimmering-mask-view-design.md | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-05-shimmering-mask-view-design.md diff --git a/docs/superpowers/specs/2026-05-05-shimmering-mask-view-design.md b/docs/superpowers/specs/2026-05-05-shimmering-mask-view-design.md new file mode 100644 index 0000000000..4ca1ae79d8 --- /dev/null +++ b/docs/superpowers/specs/2026-05-05-shimmering-mask-view-design.md @@ -0,0 +1,152 @@ +# ShimmeringMaskView — design + +## Goal + +Build a reusable `ShimmeringMaskView` that applies a moving alpha-mask shimmer to its `contentView`, producing a "ChatGPT thinking"-style running effect. First consumer: the `streamingStatusTextNode` in `ChatMessageTextBubbleContentNode`. + +## Visual model + +Reveal mask with constant baseline: + +- Outside the wave, mask alpha = `1.0` (content fully visible). +- A horizontal wave travels across the content; at the wave's center, mask alpha dips to `peakAlpha` (a value < 1.0). +- The wave repeats infinitely while in the view hierarchy. + +Conceptually: the wave is a *low-opacity dimming dip* sliding through; rest state is fully visible. + +## Module location and BUILD + +- File: `submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift` +- BUILD: `submodules/TelegramUI/Components/ShimmeringMask/BUILD` + +Final deps: + +```python +deps = [ + "//submodules/ComponentFlow", + "//submodules/Components/HierarchyTrackingLayer", +], +``` + +The currently-listed `AsyncDisplayKit`, `Display`, and `ShimmerEffect` deps are removed — none of their types are used. (Re-add `//submodules/Display` if a Display utility is needed during implementation.) + +## Public API + +```swift +public final class ShimmeringMaskView: UIView { + public let contentView: UIView + + public init(peakAlpha: CGFloat, duration: Double) + + public func update( + size: CGSize, + containerWidth: CGFloat, + offsetX: CGFloat, + gradientWidth: CGFloat, + transition: ComponentTransition + ) +} +``` + +Init params (chosen once): +- `peakAlpha` — alpha at the center of the wave (e.g. `0.3`). +- `duration` — seconds per cycle. + +Update params (per layout): +- `size` — `contentView.frame.size`. +- `containerWidth`, `offsetX` — coordinate space the wave traverses, allowing the wave to extend past `contentView`'s own bounds (matches the `VideoChatVideoLoadingEffectView` API). For an isolated use, pass `containerWidth = size.width, offsetX = 0`. +- `gradientWidth` — width of the dip in container coordinates. + +## Internal architecture + +``` +ShimmeringMaskView (UIView) +├── contentView (UIView, public) +│ └── layer.mask = maskLayer +└── HierarchyTrackingLayer (pause/resume on hierarchy entry) + +maskLayer: CAGradientLayer + startPoint = (0, 0.5), endPoint = (1, 0.5) // horizontal + colors = [white@1.0, white@peakAlpha, white@1.0] + locations = positions placing a gradientWidth-wide dip + centered in maskLayer.bounds + bounds.width = size.width + 2 × travelDistance + where travelDistance = containerWidth + gradientWidth + (guarantees alpha=1.0 edges always cover contentView) + bounds.height = size.height + anchorPoint = (0.5, 0.5) + static position.x = −gradientWidth/2 − offsetX + (dip parked just off-left of the container in contentView coords; + contentView's layer is the mask's reference coord system, so + position.x is in contentView coords directly) + + position.x animation (CABasicAnimation, additive, infinite): + keyPath = "position.x" + from = 0 + to = containerWidth + gradientWidth + duration = duration + timingFunction = .easeOut + repeatCount = .infinity + isRemovedOnCompletion = true (safety net; in practice never completes) +``` + +### Why a single oversized `CAGradientLayer` + +- For an additive overlay (the shape of `AnimatedGradientView` inside `VideoChatVideoLoadingEffectView`), the unit-scale + container-scale + offset-scale hierarchy lets you keep animation params constant while changing `containerWidth/gradientWidth` via static transforms. For a *mask*, the layer must always cover `contentView.bounds` at every animation phase — which forces oversize anyway. So the hierarchy stops paying for itself; we'd carry three intermediate layers and still need to oversize. +- Trade-off: when `containerWidth` or `gradientWidth` change, the animation is re-armed with new `to` values. For the streaming-status use case, layout changes are rare (only when the bubble re-lays out), and the re-arm is cheap. + +### Why animate `position.x` (not `locations`) + +Per direction in the design discussion: `position.x` is GPU-accelerated as a layer translation, matches the proven pattern in `AnimatedGradientView` / `LoadingEffectView`, and produces stable jank-free motion. `additive: true` lets the layer's static `position.x` carry the per-layout offset (offsetX baked in) while the animation contributes the fixed `[0, containerWidth + gradientWidth]` translation delta. + +## Lifecycle + +- `HierarchyTrackingLayer` is added as a sublayer of `self.layer`. Its `didEnterHierarchy` callback calls `updateAnimations()`. +- `updateAnimations()`: if `maskLayer.animation(forKey: "shimmer") == nil`, build the `CABasicAnimation` and add it to `maskLayer`. This restarts the animation when re-entering the hierarchy. +- `update(...)`: + 1. Build `Params(size, containerWidth, offsetX, gradientWidth)`. + 2. If `params == self.params`, return. + 3. Otherwise store new params; apply layout via the supplied `transition` (frame of `contentView`, bounds + position of `maskLayer`). + 4. Re-arm the animation (remove existing key + add a new `CABasicAnimation` reflecting the updated `to` value). +- Re-arm is unconditional when params change. Visible jump is acceptable since layout changes for the streaming-status use case are rare. + +## Integration: `ChatMessageTextBubbleContentNode` + +Location: `submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift` (currently around lines 90 and 961-1006). + +1. Add a field alongside `streamingStatusTextNode`: + ```swift + private var streamingStatusShimmerView: ShimmeringMaskView? + ``` +2. In the `if let streamingTextFrame, let streamingTextLayoutAndApply { ... }` branch (~line 959): + - Lazily create `ShimmeringMaskView(peakAlpha: 0.3, duration: 1.0)`; add to `containerNode.view`. + - Move the streaming text node's view into the shimmer view's `contentView` (instead of adding it directly to `containerNode`). + - Drive shimmer view position/size with `animation.animator` (currently used directly on `streamingStatusTextNode.textNode.layer`): + - `animation.animator.updatePosition(layer: shimmerView.layer, position: streamingTextFrame.center, ...)`. + - `animation.animator.updateBounds(layer: shimmerView.layer, bounds: CGRect(origin: .zero, size: streamingTextFrame.size), ...)`. + - The textNode inside `contentView` is laid out at `(0, 0, streamingTextFrame.size)`. + - Call `shimmerView.update(size: streamingTextFrame.size, containerWidth: streamingTextFrame.width, offsetX: 0, gradientWidth: 200, transition: ComponentTransition(animation))`. +3. In the "tear-down" branch (~line 1001) where `streamingStatusTextNode` is being dropped: + - Animate alpha to 0 on the shimmer view (not the textNode), and remove on completion. The textNode is inside the shimmer view, so removing the shimmer view removes both. +4. The crossfade flow at lines 982-989 continues to work — the textNode's superview is now `shimmerView.contentView` instead of `containerNode`; `sourceView` still gets added to `textNodeContainer` (= `shimmerView.contentView`) and crossfaded in place. + +### Constants used at the call site + +| Constant | Value | Notes | +|----------------|------:|-------| +| `peakAlpha` | `0.3` | Wave dip floor — comfortable contrast against fully visible rest state. | +| `duration` | `1.0` | Matches `LoadingEffectView` / `VideoChatVideoLoadingEffectView` cadence. | +| `gradientWidth`| `200` | Matches the gradient width used elsewhere in the family. | +| `containerWidth` | `streamingTextFrame.width` | Wave scoped to the streaming text strip; broadenable to bubble width if cross-element synchronization is later required. | +| `offsetX` | `0` | Streaming text strip is the container in this scoping. | + +## Out of scope + +- Synchronizing the wave across multiple separate views — the API supports it via `containerWidth + offsetX`, but no consumer needs it today. +- Border-shimmer companion (analogous to `LoadingEffectView.borderGradientView`) — not required for streaming-status text. +- Color tinting the wave — only alpha is modulated; `contentView` keeps its existing colors. + +## Verification + +- Build: `python3 build-system/Make/Make.py --overrideXcodeVersion --cacheDir ~/telegram-bazel-cache build --configurationPath build-system/appstore-configuration.json --gitCodesigningRepository git@gitlab.com:peter-iakovlev/fastlanematch.git --gitCodesigningType development --gitCodesigningUseCurrent --buildNumber=1 --configuration=debug_sim_arm64` (with `source ~/.zshrc 2>/dev/null;` prefix to pick up `TELEGRAM_CODESIGNING_GIT_PASSWORD`). +- Manual: open a chat with a streaming AI message and observe the shimmer effect on the streaming-status line. Confirm the wave runs continuously, the text remains fully readable except when the dip passes, and the effect tears down cleanly when the streaming status disappears. From aafe6d8dab5facbbc15088a8311dea3596d6cb07 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 16:53:13 +0200 Subject: [PATCH 05/14] Add implementation plan for ShimmeringMaskView Three task plan: (1) trim ShimmeringMask BUILD deps, (2) replace stub with full reveal-mask CAGradientLayer implementation, (3) wrap streamingStatusTextNode in ChatMessageTextBubbleContentNode. Plus a manual-verification task since the project has no unit-test harness. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../plans/2026-05-05-shimmering-mask-view.md | 552 ++++++++++++++++++ 1 file changed, 552 insertions(+) create mode 100644 docs/superpowers/plans/2026-05-05-shimmering-mask-view.md diff --git a/docs/superpowers/plans/2026-05-05-shimmering-mask-view.md b/docs/superpowers/plans/2026-05-05-shimmering-mask-view.md new file mode 100644 index 0000000000..7e748a2e0d --- /dev/null +++ b/docs/superpowers/plans/2026-05-05-shimmering-mask-view.md @@ -0,0 +1,552 @@ +# ShimmeringMaskView Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Build a reusable `ShimmeringMaskView` (alpha-mask "running shimmer" effect) and wire it as the host for `streamingStatusTextNode` in `ChatMessageTextBubbleContentNode` to give the streaming-status line a ChatGPT-style "thinking" effect. + +**Architecture:** Single `CAGradientLayer` set as `contentView.layer.mask`. Horizontal three-stop gradient `[white@1.0, white@peakAlpha, white@1.0]` with the dip parked at the layer's bounds center; layer is oversized (`size.width + 2 × travelDistance`) so its `alpha=1.0` edges keep `contentView` covered at every animation phase. A `position.x` `CABasicAnimation` (`additive: true`, `repeatCount: .infinity`, `easeOut`) shifts the dip across the wave path. `HierarchyTrackingLayer` re-arms the animation when the view re-enters the hierarchy. API mirrors `VideoChatVideoLoadingEffectView` (init takes appearance constants; `update` takes layout values + a `ComponentTransition`). + +**Tech Stack:** Swift, UIKit, `CAGradientLayer`, `CABasicAnimation`, `HierarchyTrackingLayer`, `ComponentFlow.ComponentTransition`, Bazel (`swift_library`). + +**Reference reading (no edits needed):** +- Spec: `docs/superpowers/specs/2026-05-05-shimmering-mask-view-design.md` +- Pattern reference: `submodules/TelegramCallsUI/Sources/VideoChatVideoLoadingEffectView.swift` +- Pattern reference: `submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/LoadingEffectView.swift` +- Pattern reference: `submodules/TelegramUI/Components/TextLoadingEffect/Sources/TextLoadingEffect.swift` + +**Important context — no unit tests in this project:** +This codebase has no unit-test harness (see `CLAUDE.md`: *"No tests are used at the moment"*). Verification is done by running the full Bazel build and visually inspecting the result. The "test" steps in this plan therefore replace per-task pytest-style verification with **build steps** that compile the affected modules, plus one explicit manual run-the-app step at the end. + +**Build invocation used throughout this plan:** + +```sh +source ~/.zshrc 2>/dev/null; \ +python3 build-system/Make/Make.py --overrideXcodeVersion \ + --cacheDir ~/telegram-bazel-cache \ + build \ + --configurationPath build-system/appstore-configuration.json \ + --gitCodesigningRepository git@gitlab.com:peter-iakovlev/fastlanematch.git \ + --gitCodesigningType development --gitCodesigningUseCurrent --buildNumber=1 \ + --configuration=debug_sim_arm64 +``` + +The `source ~/.zshrc 2>/dev/null;` prefix is required to pick up `TELEGRAM_CODESIGNING_GIT_PASSWORD`. Bazel is the only supported build path; there is no per-module build target — the full `Telegram/Telegram` app is built. First build of a fresh worktree may take 10+ minutes; incremental builds during this plan are typically 30s–2min. + +--- + +## File Structure + +| Action | Path | Responsibility | +|---|---|---| +| **Modify** | `submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift` | Replace stub with full implementation. | +| **Modify** | `submodules/TelegramUI/Components/ShimmeringMask/BUILD` | Trim deps to `ComponentFlow` + `Components/HierarchyTrackingLayer`. | +| **Modify** | `submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift` | Wrap `streamingStatusTextNode` in a `ShimmeringMaskView`; route position/bounds/alpha animation to the wrapper. | + +The `ShimmeringMask` module is already wired as a dep on the `ChatMessageTextBubbleContentNode` library (we confirmed `submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/BUILD` has `"//submodules/TelegramUI/Components/ShimmeringMask"`), and the consumer file already has `import ShimmeringMask`. No BUILD edits are needed for the consumer side. + +--- + +### Task 1: Trim BUILD deps for ShimmeringMask + +**Files:** +- Modify: `submodules/TelegramUI/Components/ShimmeringMask/BUILD` + +- [ ] **Step 1: Open the BUILD file** + +Read `submodules/TelegramUI/Components/ShimmeringMask/BUILD` to confirm current contents. + +- [ ] **Step 2: Replace deps with the trimmed list** + +Replace the existing `deps` block in `submodules/TelegramUI/Components/ShimmeringMask/BUILD` so the file matches: + +```python +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "ShimmeringMask", + module_name = "ShimmeringMask", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/ComponentFlow", + "//submodules/Components/HierarchyTrackingLayer", + ], + visibility = [ + "//visibility:public", + ], +) +``` + +The removed deps (`AsyncDisplayKit`, `Display`, `ShimmerEffect`) are not used by the new implementation. The added dep (`Components/HierarchyTrackingLayer`) is needed for the pause/resume-on-hierarchy pattern. + +- [ ] **Step 3: Build to confirm BUILD parses** + +The current stub `ShimmeringMaskView.swift` imports `Display`, `ShimmerEffect`, `AsyncDisplayKit`, and `ComponentFlow`. Trimming the BUILD deps without first updating the source would break the build. Skip building until Task 2's source replacement lands. (We'll build after Task 2.) + +- [ ] **Step 4: Stage but don't commit yet** + +```sh +git add submodules/TelegramUI/Components/ShimmeringMask/BUILD +``` + +The commit will happen at the end of Task 2 to keep the BUILD + source change atomic. + +--- + +### Task 2: Replace ShimmeringMaskView stub with full implementation + +**Files:** +- Modify: `submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift` + +- [ ] **Step 1: Verify the stub matches what we expect** + +Read `submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift`. Confirm it contains the stub (a `ShimmeringMaskView` class with `public let contentView: UIView`, `init(frame:)`, and an empty `update(size:transition:)`). If it has diverged, stop and ask for direction; otherwise proceed. + +- [ ] **Step 2: Rewrite the file** + +Replace the entire contents of `submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift` with: + +```swift +import Foundation +import UIKit +import ComponentFlow +import HierarchyTrackingLayer + +public final class ShimmeringMaskView: UIView { + private struct Params: Equatable { + var size: CGSize + var containerWidth: CGFloat + var offsetX: CGFloat + var gradientWidth: CGFloat + } + + public let contentView: UIView + + private let peakAlpha: CGFloat + private let duration: Double + + private let hierarchyTrackingLayer: HierarchyTrackingLayer + private let maskLayer: CAGradientLayer + + private var params: Params? + + public init(peakAlpha: CGFloat, duration: Double) { + self.peakAlpha = peakAlpha + self.duration = duration + + self.contentView = UIView() + + self.hierarchyTrackingLayer = HierarchyTrackingLayer() + + self.maskLayer = CAGradientLayer() + self.maskLayer.startPoint = CGPoint(x: 0.0, y: 0.5) + self.maskLayer.endPoint = CGPoint(x: 1.0, y: 0.5) + self.maskLayer.colors = [ + UIColor(white: 1.0, alpha: 1.0).cgColor, + UIColor(white: 1.0, alpha: peakAlpha).cgColor, + UIColor(white: 1.0, alpha: 1.0).cgColor + ] + self.maskLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5) + + super.init(frame: CGRect()) + + self.addSubview(self.contentView) + self.contentView.layer.mask = self.maskLayer + + self.layer.addSublayer(self.hierarchyTrackingLayer) + self.hierarchyTrackingLayer.didEnterHierarchy = { [weak self] in + guard let self else { + return + } + self.updateAnimations() + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func updateAnimations() { + guard let params = self.params else { + return + } + if self.maskLayer.animation(forKey: "shimmer") != nil { + return + } + let travelDelta = params.containerWidth + params.gradientWidth + let animation = self.maskLayer.makeAnimation( + from: 0.0 as NSNumber, + to: travelDelta as NSNumber, + keyPath: "position.x", + timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, + duration: self.duration, + delay: 0.0, + mediaTimingFunction: nil, + removeOnCompletion: true, + additive: true + ) + animation.repeatCount = Float.infinity + self.maskLayer.add(animation, forKey: "shimmer") + } + + public func update( + size: CGSize, + containerWidth: CGFloat, + offsetX: CGFloat, + gradientWidth: CGFloat, + transition: ComponentTransition + ) { + let params = Params( + size: size, + containerWidth: containerWidth, + offsetX: offsetX, + gradientWidth: gradientWidth + ) + if self.params == params { + return + } + self.params = params + + transition.setFrame(view: self.contentView, frame: CGRect(origin: CGPoint(), size: size)) + + let travelDistance = containerWidth + gradientWidth + let maskWidth = size.width + 2.0 * travelDistance + + let dipHalfFraction: CGFloat + if maskWidth > 0.0 { + dipHalfFraction = (gradientWidth * 0.5) / maskWidth + } else { + dipHalfFraction = 0.0 + } + self.maskLayer.locations = [ + (0.5 - dipHalfFraction) as NSNumber, + 0.5 as NSNumber, + (0.5 + dipHalfFraction) as NSNumber + ] + + let maskBounds = CGRect(origin: CGPoint(), size: CGSize(width: maskWidth, height: size.height)) + let staticPositionX = -gradientWidth * 0.5 - offsetX + let maskPosition = CGPoint(x: staticPositionX, y: size.height * 0.5) + + transition.setBounds(layer: self.maskLayer, bounds: maskBounds) + transition.setPosition(layer: self.maskLayer, position: maskPosition) + + self.maskLayer.removeAnimation(forKey: "shimmer") + self.updateAnimations() + } +} +``` + +Notes on the code (do not alter): +- `super.init(frame: CGRect())` is intentional — callers always size via `update(...)`; init takes appearance constants only. +- `maskLayer.anchorPoint = (0.5, 0.5)` and the mask is parented in `contentView.layer`'s coord system (because `contentView.layer.mask = maskLayer`). So `maskLayer.position.x = -gradientWidth/2 - offsetX` puts the dip just off-left of the container in `contentView` coords. +- `dipHalfFraction` is `(gradientWidth/2) / maskWidth` because `CAGradientLayer.locations` are normalized to the *layer's* bounds. With locations `[0.5 − Δ, 0.5, 0.5 + Δ]` the dip occupies `gradientWidth` pixels centered in `maskWidth`. +- The `if maskWidth > 0.0` guard avoids divide-by-zero on a zero-sized first call. +- Animation re-arm is unconditional whenever params change (intentionally — tradeoff documented in the spec). +- `makeAnimation(...)` is a `CALayer` extension provided by `Display`/`ComponentFlow` (it's used identically in the reference files). It *is* available without importing `Display` because the helper is on `ComponentFlow`'s import surface that we already pull in. If the build complains that `makeAnimation` is unresolved, add `import Display` and `"//submodules/Display"` to the BUILD deps — but check first. + +- [ ] **Step 3: Verify the `makeAnimation` symbol resolves** + +Before a full build, run a quick grep to be sure of the source of `makeAnimation`: + +```sh +grep -rn "func makeAnimation" submodules/Display/ submodules/ComponentFlow/ submodules/Components/HierarchyTrackingLayer/ 2>/dev/null +``` + +Expected: at least one hit. If the only hit is in `submodules/Display/`, then `import Display` and the `Display` BUILD dep ARE required. Update Task 2's source file (add `import Display` after `import UIKit`) and Task 1's BUILD (add `"//submodules/Display",` to deps) before building. If hits exist in `ComponentFlow` or `HierarchyTrackingLayer` we're fine without `Display`. + +- [ ] **Step 4: Build the affected target** + +Run the full Bazel build (see "Build invocation" above). Bazel will compile the `ShimmeringMask` library as part of building `Telegram/Telegram`. + +Expected: build succeeds. Watch for `-warnings-as-errors` failures in `ShimmeringMaskView.swift` (e.g. unused-let, always-false casts) — fix them inline before re-running. + +- [ ] **Step 5: Commit Task 1 + Task 2 together** + +```sh +git add submodules/TelegramUI/Components/ShimmeringMask/BUILD \ + submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift +git commit -m "$(cat <<'EOF' +ShimmeringMask: implement ShimmeringMaskView reveal-mask shimmer + +CAGradientLayer mask with horizontal [white@1.0, white@peakAlpha, +white@1.0] gradient; oversized so alpha=1.0 edges always cover +contentView. Animates position.x (additive, infinite, easeOut) so the +dip travels across containerWidth. HierarchyTrackingLayer pauses / +resumes the animation on hierarchy entry. API mirrors +VideoChatVideoLoadingEffectView. + +Co-Authored-By: Claude Opus 4.7 (1M context) +EOF +)" +``` + +--- + +### Task 3: Wrap streamingStatusTextNode in ShimmeringMaskView + +**Files:** +- Modify: `submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift` + +This task touches three regions of the file. The line numbers below are accurate as of the time the spec was written; if the file has shifted by a handful of lines, locate by surrounding text (the code excerpts shown are the unique anchors). + +- [ ] **Step 1: Add a sibling field for the shimmer view** + +Find the existing field declaration: + +```swift + private var streamingStatusTextNode: InteractiveTextNodeWithEntities? +``` + +(approximately line 90). Insert a new line directly after it: + +```swift + private var streamingStatusTextNode: InteractiveTextNodeWithEntities? + private var streamingStatusShimmerView: ShimmeringMaskView? +``` + +- [ ] **Step 2: Wrap the streaming-text branch — locate** + +Find this block (approximately lines 959-1000): + +```swift + if let streamingTextFrame, let streamingTextLayoutAndApply { + var animation = animation + if strongSelf.streamingStatusTextNode == nil { + animation = .None + } + let streamingStatusTextNode = streamingTextLayoutAndApply.apply(InteractiveTextNodeWithEntities.Arguments( + context: item.context, + cache: item.controllerInteraction.presentationContext.animationCache, + renderer: item.controllerInteraction.presentationContext.animationRenderer, + placeholderColor: messageTheme.mediaPlaceholderColor, + attemptSynchronous: synchronousLoads, + textColor: messageTheme.primaryTextColor, + spoilerEffectColor: messageTheme.secondaryTextColor, + applyArguments: InteractiveTextNode.ApplyArguments( + animation: animation, + spoilerTextColor: messageTheme.primaryTextColor, + spoilerEffectColor: messageTheme.secondaryTextColor, + areContentAnimationsEnabled: item.context.sharedContext.energyUsageSettings.loopEmoji, + spoilerExpandRect: nil, + crossfadeContents: { [weak strongSelf] sourceView in + guard let strongSelf, let streamingStatusTextNode = strongSelf.streamingStatusTextNode else { + return + } + if let textNodeContainer = streamingStatusTextNode.textNode.view.superview { + sourceView.frame = CGRect(origin: streamingStatusTextNode.textNode.frame.origin, size: sourceView.bounds.size) + textNodeContainer.addSubview(sourceView) + + sourceView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false, completion: { [weak sourceView] _ in + sourceView?.removeFromSuperview() + }) + streamingStatusTextNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + } + } + ) + )) + if streamingStatusTextNode !== strongSelf.streamingStatusTextNode { + strongSelf.streamingStatusTextNode?.textNode.removeFromSupernode() + strongSelf.streamingStatusTextNode = streamingStatusTextNode + strongSelf.containerNode.addSubnode(streamingStatusTextNode.textNode) + } + animation.animator.updatePosition(layer: streamingStatusTextNode.textNode.layer, position: streamingTextFrame.center, completion: nil) + animation.animator.updateBounds(layer: streamingStatusTextNode.textNode.layer, bounds: CGRect(origin: CGPoint(), size: streamingTextFrame.size), completion: nil) + } else if let streamingStatusTextNode = strongSelf.streamingStatusTextNode { + strongSelf.streamingStatusTextNode = nil + let streamingStatusTextNodeNode = streamingStatusTextNode.textNode + animation.animator.updateAlpha(layer: streamingStatusTextNodeNode.layer, alpha: 0.0, completion: { [weak streamingStatusTextNodeNode] _ in + streamingStatusTextNodeNode?.removeFromSupernode() + }) + } +``` + +This is the region we will replace. + +- [ ] **Step 3: Wrap the streaming-text branch — replace** + +Replace the entire block from Step 2 with: + +```swift + if let streamingTextFrame, let streamingTextLayoutAndApply { + var animation = animation + if strongSelf.streamingStatusTextNode == nil { + animation = .None + } + let streamingStatusTextNode = streamingTextLayoutAndApply.apply(InteractiveTextNodeWithEntities.Arguments( + context: item.context, + cache: item.controllerInteraction.presentationContext.animationCache, + renderer: item.controllerInteraction.presentationContext.animationRenderer, + placeholderColor: messageTheme.mediaPlaceholderColor, + attemptSynchronous: synchronousLoads, + textColor: messageTheme.primaryTextColor, + spoilerEffectColor: messageTheme.secondaryTextColor, + applyArguments: InteractiveTextNode.ApplyArguments( + animation: animation, + spoilerTextColor: messageTheme.primaryTextColor, + spoilerEffectColor: messageTheme.secondaryTextColor, + areContentAnimationsEnabled: item.context.sharedContext.energyUsageSettings.loopEmoji, + spoilerExpandRect: nil, + crossfadeContents: { [weak strongSelf] sourceView in + guard let strongSelf, let streamingStatusTextNode = strongSelf.streamingStatusTextNode else { + return + } + if let textNodeContainer = streamingStatusTextNode.textNode.view.superview { + sourceView.frame = CGRect(origin: streamingStatusTextNode.textNode.frame.origin, size: sourceView.bounds.size) + textNodeContainer.addSubview(sourceView) + + sourceView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false, completion: { [weak sourceView] _ in + sourceView?.removeFromSuperview() + }) + streamingStatusTextNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + } + } + ) + )) + + let streamingStatusShimmerView: ShimmeringMaskView + if let current = strongSelf.streamingStatusShimmerView { + streamingStatusShimmerView = current + } else { + streamingStatusShimmerView = ShimmeringMaskView(peakAlpha: 0.3, duration: 1.0) + strongSelf.streamingStatusShimmerView = streamingStatusShimmerView + strongSelf.containerNode.view.addSubview(streamingStatusShimmerView) + } + + if streamingStatusTextNode !== strongSelf.streamingStatusTextNode { + strongSelf.streamingStatusTextNode?.textNode.view.removeFromSuperview() + strongSelf.streamingStatusTextNode = streamingStatusTextNode + streamingStatusShimmerView.contentView.addSubview(streamingStatusTextNode.textNode.view) + } + animation.animator.updatePosition(layer: streamingStatusShimmerView.layer, position: streamingTextFrame.center, completion: nil) + animation.animator.updateBounds(layer: streamingStatusShimmerView.layer, bounds: CGRect(origin: CGPoint(), size: streamingTextFrame.size), completion: nil) + animation.animator.updatePosition(layer: streamingStatusTextNode.textNode.layer, position: CGPoint(x: streamingTextFrame.size.width * 0.5, y: streamingTextFrame.size.height * 0.5), completion: nil) + animation.animator.updateBounds(layer: streamingStatusTextNode.textNode.layer, bounds: CGRect(origin: CGPoint(), size: streamingTextFrame.size), completion: nil) + streamingStatusShimmerView.update( + size: streamingTextFrame.size, + containerWidth: streamingTextFrame.size.width, + offsetX: 0.0, + gradientWidth: 200.0, + transition: ComponentTransition(animation.transition) + ) + } else if let streamingStatusTextNode = strongSelf.streamingStatusTextNode { + strongSelf.streamingStatusTextNode = nil + let streamingStatusShimmerView = strongSelf.streamingStatusShimmerView + strongSelf.streamingStatusShimmerView = nil + let streamingStatusTextNodeNode = streamingStatusTextNode.textNode + if let streamingStatusShimmerView { + animation.animator.updateAlpha(layer: streamingStatusShimmerView.layer, alpha: 0.0, completion: { [weak streamingStatusShimmerView] _ in + streamingStatusShimmerView?.removeFromSuperview() + }) + } else { + animation.animator.updateAlpha(layer: streamingStatusTextNodeNode.layer, alpha: 0.0, completion: { [weak streamingStatusTextNodeNode] _ in + streamingStatusTextNodeNode?.removeFromSupernode() + }) + } + } +``` + +What changed: +- Lazy-create `ShimmeringMaskView(peakAlpha: 0.3, duration: 1.0)` and add it to `containerNode.view`. +- When the streaming text node is created/replaced, add `streamingStatusTextNode.textNode.view` to `streamingStatusShimmerView.contentView` (UIView hierarchy) **instead of** `containerNode.addSubnode(streamingStatusTextNode.textNode)`. Mixing `view`/`Subview` and `Subnode`/`Supernode` is fine here: ASDisplayNode's `view` is a real UIView, and adding it via `addSubview` from another UIView reparents it. +- Animate the **shimmer view's** layer to `streamingTextFrame.center`/size — this is the position where the streaming-text strip lives in the bubble's container. +- Animate the inner textNode's layer to the shimmer view's local bounds (`origin = .zero`, same size). Without this, after we reparent the textNode under contentView, the textNode keeps its old `containerNode`-relative frame and ends up offset by `streamingTextFrame.origin`. We're explicitly placing it at `(0, 0, streamingTextFrame.size)` inside `contentView`. +- Call `streamingStatusShimmerView.update(...)` with `containerWidth = streamingTextFrame.size.width` and `offsetX = 0.0` (wave scoped to the streaming-text strip itself; broadenable later). +- The teardown branch animates alpha on the shimmer view (with the textNode inside it). When the shimmer view exists, we use it as the alpha-animation target and do `removeFromSuperview` in the completion; the textNode rides along because it's a subview of `contentView`. We keep a fallback `else` branch animating the textNode directly in case some path produces a streamingStatusTextNode without a shimmer view (defensive — should be unreachable today, but it's a one-line cost and matches the previous behavior exactly). +- The replacement step uses `view.removeFromSuperview()` (not `removeFromSupernode()`) because the inner textNode is now hosted inside `streamingStatusShimmerView.contentView` (a plain UIView) via `addSubview`. ASDisplayKit's `addSubview`/`removeFromSupernode` paths don't sync; using the UIView pair ensures replacements actually unhook the previous textNode's view from the shimmer view. + +Notes on the `transition: ComponentTransition(animation.transition)` — the existing call sites in this file use `animation.animator.update*` (where `animator` is a `Display`-flavored animator) but our `ShimmeringMaskView.update` takes a `ComponentFlow.ComponentTransition`. The `animation` value flowing through is a `ListViewItemUpdateAnimation`; it exposes `.transition` as a `ContainedViewLayoutTransition`. `ComponentTransition` has a public initializer accepting `ContainedViewLayoutTransition`. **Verify this initializer exists** before building (see Step 4); if not, fall back to `ComponentTransition.immediate` (the only consequence is that the mask layer's bounds/position aren't animated to their new values, which is rare and benign). + +- [ ] **Step 4: Verify the ComponentTransition initializer exists** + +```sh +grep -rn "init.*ContainedViewLayoutTransition" submodules/ComponentFlow/Source/ 2>/dev/null +grep -rn "extension ComponentTransition" submodules/ComponentFlow/Source/ 2>/dev/null +``` + +Expected: at least one hit indicating an initializer or static helper that converts a `ContainedViewLayoutTransition` to a `ComponentTransition`. If you find one named differently (e.g. `ComponentTransition(transition:)` or `ComponentTransition.init(legacyAnimation:)`), use that exact name in the call from Step 3. + +If neither exists, replace the `transition:` argument in Step 3's call with `.immediate`: + +```swift + streamingStatusShimmerView.update( + size: streamingTextFrame.size, + containerWidth: streamingTextFrame.size.width, + offsetX: 0.0, + gradientWidth: 200.0, + transition: .immediate + ) +``` + +- [ ] **Step 5: Build** + +Run the full Bazel build (see "Build invocation" above). Expected: build succeeds. + +If you get `-warnings-as-errors` failures specifically about an unused `streamingStatusShimmerView` variable in the teardown branch, that means a compiler-flagged path: re-check the diff against the Step 3 source. + +- [ ] **Step 6: Commit** + +```sh +git add submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift +git commit -m "$(cat <<'EOF' +ChatMessageTextBubbleContentNode: wrap streaming-status text in ShimmeringMaskView + +Hosts streamingStatusTextNode inside a ShimmeringMaskView so the +streaming line gets a "thinking"-style running shimmer (alpha-mask wave +with peakAlpha=0.3, duration=1.0, gradientWidth=200). Layout/teardown +animations target the shimmer view's layer; the text node lives inside +contentView at the wrapper's local bounds. + +Co-Authored-By: Claude Opus 4.7 (1M context) +EOF +)" +``` + +--- + +### Task 4: Manual verification + +**Files:** none (build + run only) + +- [ ] **Step 1: Confirm clean build state** + +```sh +git status --short +``` + +Expected: empty (or only the unrelated `m`/`M` entries that were present before this work began — see `gitStatus` in the conversation context). + +- [ ] **Step 2: Build for the simulator** + +Run the full Bazel build (see "Build invocation" above). Expected: build succeeds with no warnings-as-errors. + +- [ ] **Step 3: Manual run** + +Launch the built app in the simulator. Open a chat with an in-progress AI streaming message (or trigger a streaming-status placeholder if one exists in the test environment). Confirm: + +- The streaming-status line shows a smooth horizontal wave that runs continuously while streaming. +- Outside the wave, the text is fully readable (alpha=1.0). +- At the wave's center, the text dims to ~30% (the `peakAlpha = 0.3` value). +- When the streaming status disappears (message finishes streaming), the shimmer view fades out cleanly with the text inside it. +- Scrolling the streaming message off-screen pauses the animation; scrolling it back on resumes (`HierarchyTrackingLayer` doing its job). + +If the wave is too fast / too slow / too subtle, adjust the constants `peakAlpha`, `duration`, `gradientWidth` at the call site in `ChatMessageTextBubbleContentNode.swift` (Task 3, Step 3, where `ShimmeringMaskView(peakAlpha: 0.3, duration: 1.0)` and `gradientWidth: 200.0` appear) and rebuild. Don't commit tuning changes as part of this plan — leave them for a follow-up. + +- [ ] **Step 4: No commit (verification only)** + +This task produces no code changes. + +--- + +## Notes for the implementer + +- **`-warnings-as-errors`** is enabled on both modules. Common gotchas: unused locals, always-false `is` checks, always-failing `as?` casts. If a build fails with these, fix them inline rather than adding `// swiftlint:disable` or `_ = unused`. +- **No unit tests, no UI snapshot tests** in this project. The full Bazel build is the only automated gate. Be diligent about the manual verification step. +- **Bazel cache:** the plan assumes `~/telegram-bazel-cache` is reusable across builds. If you're working in a fresh worktree (no shared cache), the first build will take meaningfully longer. +- **`HierarchyTrackingLayer` BUILD path** is `//submodules/Components/HierarchyTrackingLayer` (note the `Components/` prefix — there's no top-level `submodules/HierarchyTrackingLayer/`). +- If `streamingTextLayoutAndApply` ends up being non-nil in fast succession (streaming status flickers), the same `ShimmeringMaskView` instance is reused — `update(...)`'s `params != self.params` short-circuit avoids re-arming the animation when nothing changed. +- The wave's containerWidth is currently scoped to the streaming-text strip itself, not the bubble. If a future change wants the wave to traverse the full bubble width (or sync across multiple bubbles), pass a larger `containerWidth` and a non-zero `offsetX` (the streaming-text strip's `minX` within the chosen container) to `update(...)`. From 4de5eeccd25a924b6562a14bb3d8c7b2bbd93367 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 16:53:47 +0200 Subject: [PATCH 06/14] Various improvements --- .../ChatPresentationInterfaceState.swift | 193 +++++++++--------- .../ChatMessageTextBubbleContentNode/BUILD | 1 + .../ChatMessageTextBubbleContentNode.swift | 91 ++++++++- .../ChatTextInputActionButtonsNode.swift | 32 ++- .../Sources/ChatTextInputPanelNode.swift | 25 ++- .../Components/ShimmeringMask/BUILD | 21 ++ .../Sources/ShimmeringMaskView.swift | 26 +++ .../Chat/ChatControllerLoadDisplayNode.swift | 4 + .../Sources/ChatControllerContentData.swift | 45 +++- 9 files changed, 338 insertions(+), 100 deletions(-) create mode 100644 submodules/TelegramUI/Components/ShimmeringMask/BUILD create mode 100644 submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift index c705171903..d43b03e3c9 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift @@ -588,6 +588,7 @@ public final class ChatPresentationInterfaceState: Equatable { public let removePaidMessageFeeData: RemovePaidMessageFeeData? public let viewForumAsMessages: Bool public let hasTopics: Bool + public let canStopIncomingStreamingMessage: Bool public init(chatWallpaper: TelegramWallpaper, theme: PresentationTheme, preferredGlassType: GlassType, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, accountPeerId: PeerId, mode: ChatControllerPresentationMode, chatLocation: ChatLocation, subject: ChatControllerSubject?, greetingData: ChatGreetingData?, pendingUnpinnedAllMessages: Bool, activeGroupCallInfo: ChatActiveGroupCallInfo?, hasActiveGroupCall: Bool, threadData: ThreadData?, isGeneralThreadClosed: Bool?, replyMessage: Message?, accountPeerColor: AccountPeerColor?, businessIntro: TelegramBusinessIntro?) { self.interfaceState = ChatInterfaceState() @@ -687,6 +688,7 @@ public final class ChatPresentationInterfaceState: Equatable { self.removePaidMessageFeeData = nil self.viewForumAsMessages = false self.hasTopics = false + self.canStopIncomingStreamingMessage = false } public init( @@ -784,7 +786,8 @@ public final class ChatPresentationInterfaceState: Equatable { persistentData: PersistentPeerData, removePaidMessageFeeData: RemovePaidMessageFeeData?, viewForumAsMessages: Bool, - hasTopics: Bool + hasTopics: Bool, + canStopIncomingStreamingMessage: Bool ) { self.interfaceState = interfaceState self.chatLocation = chatLocation @@ -881,6 +884,7 @@ public final class ChatPresentationInterfaceState: Equatable { self.removePaidMessageFeeData = removePaidMessageFeeData self.viewForumAsMessages = viewForumAsMessages self.hasTopics = hasTopics + self.canStopIncomingStreamingMessage = canStopIncomingStreamingMessage } public static func ==(lhs: ChatPresentationInterfaceState, rhs: ChatPresentationInterfaceState) -> Bool { @@ -1178,47 +1182,50 @@ public final class ChatPresentationInterfaceState: Equatable { if lhs.hasTopics != rhs.hasTopics { return false } + if lhs.canStopIncomingStreamingMessage != rhs.canStopIncomingStreamingMessage { + return false + } return true } public func updatedInterfaceState(_ f: (ChatInterfaceState) -> ChatInterfaceState) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: f(self.interfaceState), chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: f(self.interfaceState), chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedFocusedPollAddOptionMessageId(_ focusedPollAddOptionMessageId: MessageId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedChatLocation(_ chatLocation: ChatLocation) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPeer(_ f: (RenderedPeer?) -> RenderedPeer?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: f(self.renderedPeer), isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: f(self.renderedPeer), isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedIsNotAccessible(_ isNotAccessible: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedExplicitelyCanPinMessages(_ explicitelyCanPinMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedContactStatus(_ contactStatus: ChatContactStatus?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedIsManagedBot(_ isManagedBot: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHasBots(_ hasBots: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedIsArchived(_ isArchived: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedInputQueryResult(queryKind: ChatPresentationInputQueryKind, _ f: (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?) -> ChatPresentationInterfaceState { @@ -1235,323 +1242,327 @@ public final class ChatPresentationInterfaceState: Equatable { inputQueryResults.removeValue(forKey: queryKind) } - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedInputTextPanelState(_ f: (ChatTextInputPanelState) -> ChatTextInputPanelState) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: f(self.inputTextPanelState), editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: f(self.inputTextPanelState), editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedEditMessageState(_ editMessageState: ChatEditInterfaceMessageState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedInputMode(_ f: (ChatInputMode) -> ChatInputMode) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: f(self.inputMode), titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: f(self.inputMode), titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedTitlePanelContext(_ f: ([ChatTitlePanelContext]) -> [ChatTitlePanelContext]) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: f(self.titlePanelContexts), keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: f(self.titlePanelContexts), keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedKeyboardButtonsMessage(_ message: Message?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: message, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: message, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPinnedMessage(_ pinnedMessage: ChatPinnedMessage?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPeerIsBlocked(_ peerIsBlocked: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPeerIsMuted(_ peerIsMuted: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPeerDiscussionId(_ peerDiscussionId: PeerId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPeerGeoLocation(_ peerGeoLocation: PeerGeoLocation?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedCallsAvailable(_ callsAvailable: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedCallsPrivate(_ callsPrivate: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedSlowmodeState(_ slowmodeState: ChatSlowmodeState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedBotStartPayload(_ botStartPayload: String?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedChatHistoryState(_ chatHistoryState: ChatHistoryNodeHistoryState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedUrlPreview(_ urlPreview: UrlPreview?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedEditingUrlPreview(_ editingUrlPreview: UrlPreview?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedSearch(_ search: ChatSearchData?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedSearchQuerySuggestionResult(_ f: (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: f(self.searchQuerySuggestionResult), historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: f(self.searchQuerySuggestionResult), historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHistoryFilter(_ historyFilter: HistoryFilter?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedDisplayHistoryFilterAsList(_ displayHistoryFilterAsList: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedMode(_ mode: ChatControllerPresentationMode) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPresentationReady(_ presentationReady: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedTheme(_ theme: PresentationTheme) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPreferredGlassType(_ glassType: GlassType) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: glassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: glassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedStrings(_ strings: PresentationStrings) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedDateTimeFormat(_ dateTimeFormat: PresentationDateTimeFormat) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedChatWallpaper(_ chatWallpaper: TelegramWallpaper) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedBubbleCorners(_ bubbleCorners: PresentationChatBubbleCorners) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedSubject(_ subject: ChatControllerSubject?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedAutoremoveTimeout(_ autoremoveTimeout: Int32?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPendingUnpinnedAllMessages(_ pendingUnpinnedAllMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedActiveGroupCallInfo(_ activeGroupCallInfo: ChatActiveGroupCallInfo?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHasActiveGroupCall(_ hasActiveGroupCall: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedReportReason(_ reportReason: ReportReasonData?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedShowCommands(_ showCommands: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHasBotCommands(_ hasBotCommands: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedShowSendAsPeers(_ showSendAsPeers: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedSendAsPeers(_ sendAsPeers: [SendAsPeer]?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedCurrentSendAsPeerId(_ currentSendAsPeerId: PeerId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedBotMenuButton(_ botMenuButton: BotMenuButton) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedShowWebView(_ showWebView: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedCopyProtectionEnabled(_ copyProtectionEnabled: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedMyCopyProtectionEnabled(_ myCopyProtectionEnabled: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHasAtLeast3Messages(_ hasAtLeast3Messages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHasPlentyOfMessages(_ hasPlentyOfMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedIsPremium(_ isPremium: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPremiumGiftOptions(_ premiumGiftOptions: [CachedPremiumGiftOption]) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedSuggestPremiumGift(_ suggestPremiumGift: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedForceInputCommandsHidden(_ forceInputCommandsHidden: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedVoiceMessagesAvailable(_ voiceMessagesAvailable: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedCustomEmojiAvailable(_ customEmojiAvailable: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedThreadData(_ threadData: ThreadData?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedForumTopicData(_ forumTopicData: ThreadData?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedIsGeneralThreadClosed(_ isGeneralThreadClosed: Bool?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedTranslationState(_ translationState: ChatPresentationTranslationState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedReplyMessage(_ replyMessage: Message?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedAccountPeerColor(_ accountPeerColor: AccountPeerColor?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedSavedMessagesTopicPeer(_ savedMessagesTopicPeer: EnginePeer?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHasSearchTags(_ hasSearchTags: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedIsPremiumRequiredForMessaging(_ isPremiumRequiredForMessaging: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedSendPaidMessageStars(_ sendPaidMessageStars: StarsAmount?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedAcknowledgedPaidMessage(_ acknowledgedPaidMessage: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHasSavedChats(_ hasSavedChats: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedAppliedBoosts(_ appliedBoosts: Int32?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedBoostsToUnrestrict(_ boostsToUnrestrict: Int32?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedBusinessIntro(_ businessIntro: TelegramBusinessIntro?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHasBirthdayToday(_ hasBirthdayToday: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedAdMessage(_ adMessage: Message?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPeerVerification(_ peerVerification: PeerVerification?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedStarGiftsAvailable(_ starGiftsAvailable: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedAlwaysShowGiftButton(_ alwaysShowGiftButton: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedDisallowedGifts(_ disallowedGifts: TelegramDisallowedGifts?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedPersistentData(_ persistentData: PersistentPeerData) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedRemovePaidMessageFeeData(_ removePaidMessageFeeData: RemovePaidMessageFeeData?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedViewForumAsMessages(_ viewForumAsMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: viewForumAsMessages, hasTopics: self.hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) } public func updatedHasTopics(_ hasTopics: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: hasTopics) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: hasTopics, canStopIncomingStreamingMessage: self.canStopIncomingStreamingMessage) + } + + public func updatedCanStopIncomingStreamingMessage(_ canStopIncomingStreamingMessage: Bool) -> ChatPresentationInterfaceState { + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, isManagedBot: self.isManagedBot, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, focusedPollAddOptionMessageId: self.focusedPollAddOptionMessageId, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, historyFilter: self.historyFilter, displayHistoryFilterAsList: self.displayHistoryFilterAsList, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, preferredGlassType: self.preferredGlassType, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, myCopyProtectionEnabled: self.myCopyProtectionEnabled, hasAtLeast3Messages: self.hasAtLeast3Messages, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging, sendPaidMessageStars: self.sendPaidMessageStars, acknowledgedPaidMessage: self.acknowledgedPaidMessage, hasSavedChats: self.hasSavedChats, appliedBoosts: self.appliedBoosts, boostsToUnrestrict: self.boostsToUnrestrict, businessIntro: self.businessIntro, hasBirthdayToday: self.hasBirthdayToday, adMessage: self.adMessage, peerVerification: self.peerVerification, starGiftsAvailable: self.starGiftsAvailable, alwaysShowGiftButton: self.alwaysShowGiftButton, disallowedGifts: self.disallowedGifts, persistentData: self.persistentData, removePaidMessageFeeData: self.removePaidMessageFeeData, viewForumAsMessages: self.viewForumAsMessages, hasTopics: self.hasTopics, canStopIncomingStreamingMessage: canStopIncomingStreamingMessage) } } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/BUILD index 2c419d5b7b..f283b07c37 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/BUILD @@ -37,6 +37,7 @@ swift_library( "//submodules/TelegramUI/Components/TextLoadingEffect", "//submodules/TelegramUI/Components/ChatControllerInteraction", "//submodules/TelegramUI/Components/InteractiveTextComponent", + "//submodules/TelegramUI/Components/ShimmeringMask", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift index 54aff3aa0d..d6bada6e9b 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift @@ -25,6 +25,7 @@ import ChatMessageItemCommon import TextLoadingEffect import ChatControllerInteraction import InteractiveTextComponent +import ShimmeringMask private final class CachedChatMessageText { let text: String @@ -86,6 +87,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { private let containerNode: ContainerNode private let textNode: InteractiveTextNodeWithEntities + private var streamingStatusTextNode: InteractiveTextNodeWithEntities? private let textAccessibilityOverlayNode: TextAccessibilityOverlayNode public var statusNode: ChatMessageDateAndStatusNode? @@ -240,6 +242,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { let previousItem = self.item let textLayout = InteractiveTextNodeWithEntities.asyncLayout(self.textNode) + let streamingStatusTextLayout = InteractiveTextNodeWithEntities.asyncLayout(self.streamingStatusTextNode) let statusLayout = ChatMessageDateAndStatusNode.asyncLayout(self.statusNode) let currentCachedChatMessageText = self.cachedChatMessageText @@ -720,10 +723,27 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { displayContentsUnderSpoilers: displayContentsUnderSpoilers.value, customTruncationToken: customTruncationToken, expandedBlocks: expandedBlockIds, - computeCharacterRects: true, - minWidth: (attributedText.string.isEmpty && hasDraft) ? 40.0 : nil + computeCharacterRects: true )) + var streamingTextLayoutAndApply: (layout: InteractiveTextNodeLayout, apply: (InteractiveTextNodeWithEntities.Arguments) -> InteractiveTextNodeWithEntities)? + if hasDraft || hadDraft { + //TODO:localize + streamingTextLayoutAndApply = streamingStatusTextLayout(InteractiveTextNodeLayoutArguments( + attributedString: NSAttributedString(string: "Thinking...", font: textFont, textColor: messageTheme.fileDescriptionColor), + backgroundColor: nil, + maximumNumberOfLines: 1, + truncationType: .end, + constrainedSize: textConstrainedSize, + alignment: .natural, + cutout: nil, + insets: textInsets, + lineColor: messageTheme.accentControlColor, + customTruncationToken: customTruncationToken, + computeCharacterRects: true + )) + } + var maxGlyphCount = currentMaxGlyphCount if maxGlyphCount == nil && (hasDraft || hadDraft) { maxGlyphCount = previousGlyphCount @@ -785,6 +805,15 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { var textFrame = CGRect(origin: CGPoint(x: -textInsets.left, y: -textInsets.top), size: textLayout.size) + let streamingTextSpacing: CGFloat = 1.0 + + var streamingTextFrame: CGRect? + if let streamingTextLayoutAndApply { + let streamingTextFrameValue = CGRect(origin: CGPoint(x: layoutConstants.text.bubbleInsets.left - textInsets.left, y: topInset - textInsets.top), size: streamingTextLayoutAndApply.layout.size) + streamingTextFrame = streamingTextFrameValue + textFrame.origin.y += streamingTextFrameValue.height + streamingTextSpacing - textInsets.top - textInsets.bottom + } + var textFrameWithoutInsets = CGRect(origin: CGPoint(x: textFrame.origin.x + textInsets.left, y: textFrame.origin.y + textInsets.top), size: CGSize(width: textFrame.width - textInsets.left - textInsets.right, height: textFrame.height - textInsets.top - textInsets.bottom)) textFrame = textFrame.offsetBy(dx: layoutConstants.text.bubbleInsets.left, dy: topInset) @@ -798,6 +827,9 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { textFrameWithoutInsets = textFrameWithoutInsets.offsetBy(dx: layoutConstants.text.bubbleInsets.left, dy: topInset) var suggestedBoundingWidth: CGFloat = textFrameWithoutInsets.width + if let streamingTextFrame { + suggestedBoundingWidth = max(suggestedBoundingWidth, streamingTextFrame.width - textInsets.left - textInsets.right) + } if let statusSuggestedWidthAndContinue = statusSuggestedWidthAndContinue, !hasDraft { suggestedBoundingWidth = max(suggestedBoundingWidth, statusSuggestedWidthAndContinue.0) } @@ -814,6 +846,11 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { boundingSize.height += statusSizeAndApply.0.height } + if let streamingTextFrame { + boundingSize.width = max(boundingSize.width, streamingTextFrame.width - textInsets.left - textInsets.right) + boundingSize.height += streamingTextFrame.height - textInsets.top - textInsets.bottom + streamingTextSpacing + } + boundingSize.width += layoutConstants.text.bubbleInsets.left + layoutConstants.text.bubbleInsets.right boundingSize.height += topInset + bottomInset @@ -919,6 +956,56 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { animation.animator.updatePosition(layer: strongSelf.textNode.textNode.layer, position: realTextFrame.center, completion: nil) animation.animator.updateBounds(layer: strongSelf.textNode.textNode.layer, bounds: CGRect(origin: CGPoint(), size: realTextFrame.size), completion: nil) + if let streamingTextFrame, let streamingTextLayoutAndApply { + var animation = animation + if strongSelf.streamingStatusTextNode == nil { + animation = .None + } + let streamingStatusTextNode = streamingTextLayoutAndApply.apply(InteractiveTextNodeWithEntities.Arguments( + context: item.context, + cache: item.controllerInteraction.presentationContext.animationCache, + renderer: item.controllerInteraction.presentationContext.animationRenderer, + placeholderColor: messageTheme.mediaPlaceholderColor, + attemptSynchronous: synchronousLoads, + textColor: messageTheme.primaryTextColor, + spoilerEffectColor: messageTheme.secondaryTextColor, + applyArguments: InteractiveTextNode.ApplyArguments( + animation: animation, + spoilerTextColor: messageTheme.primaryTextColor, + spoilerEffectColor: messageTheme.secondaryTextColor, + areContentAnimationsEnabled: item.context.sharedContext.energyUsageSettings.loopEmoji, + spoilerExpandRect: nil, + crossfadeContents: { [weak strongSelf] sourceView in + guard let strongSelf, let streamingStatusTextNode = strongSelf.streamingStatusTextNode else { + return + } + if let textNodeContainer = streamingStatusTextNode.textNode.view.superview { + sourceView.frame = CGRect(origin: streamingStatusTextNode.textNode.frame.origin, size: sourceView.bounds.size) + textNodeContainer.addSubview(sourceView) + + sourceView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false, completion: { [weak sourceView] _ in + sourceView?.removeFromSuperview() + }) + streamingStatusTextNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + } + } + ) + )) + if streamingStatusTextNode !== strongSelf.streamingStatusTextNode { + strongSelf.streamingStatusTextNode?.textNode.removeFromSupernode() + strongSelf.streamingStatusTextNode = streamingStatusTextNode + strongSelf.containerNode.addSubnode(streamingStatusTextNode.textNode) + } + animation.animator.updatePosition(layer: streamingStatusTextNode.textNode.layer, position: streamingTextFrame.center, completion: nil) + animation.animator.updateBounds(layer: streamingStatusTextNode.textNode.layer, bounds: CGRect(origin: CGPoint(), size: streamingTextFrame.size), completion: nil) + } else if let streamingStatusTextNode = strongSelf.streamingStatusTextNode { + strongSelf.streamingStatusTextNode = nil + let streamingStatusTextNodeNode = streamingStatusTextNode.textNode + animation.animator.updateAlpha(layer: streamingStatusTextNodeNode.layer, alpha: 0.0, completion: { [weak streamingStatusTextNodeNode] _ in + streamingStatusTextNodeNode?.removeFromSupernode() + }) + } + switch strongSelf.visibility { case .none: strongSelf.textNode.visibilityRect = nil diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputActionButtonsNode/Sources/ChatTextInputActionButtonsNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputActionButtonsNode/Sources/ChatTextInputActionButtonsNode.swift index 1569743128..123c96a69f 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputActionButtonsNode/Sources/ChatTextInputActionButtonsNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputActionButtonsNode/Sources/ChatTextInputActionButtonsNode.swift @@ -137,6 +137,7 @@ public final class ChatTextInputActionButtonsNode: ASDisplayNode, ChatSendMessag public let micButtonBackgroundView: GlassBackgroundView public let micButtonTintMaskView: UIImageView public let micButton: ChatTextInputMediaRecordingButton + public let stopButtonIcon: GlassBackgroundView.ContentImageView public let sendContainerNode: ASDisplayNode public let sendButtonBackgroundView: UIImageView @@ -193,6 +194,10 @@ public final class ChatTextInputActionButtonsNode: ASDisplayNode, ChatSendMessag self.micButton.animationOutput = self.micButtonTintMaskView self.micButtonBackgroundView.maskContentView.addSubview(self.micButtonTintMaskView) + self.stopButtonIcon = GlassBackgroundView.ContentImageView() + self.micButtonBackgroundView.contentView.addSubview(self.stopButtonIcon) + self.stopButtonIcon.alpha = 0.0 + self.sendContainerNode = ASDisplayNode() self.sendContainerNode.layer.allowsGroupOpacity = true @@ -362,9 +367,28 @@ public final class ChatTextInputActionButtonsNode: ASDisplayNode, ChatSendMessag transition.updateFrame(view: self.micButtonBackgroundView, frame: CGRect(origin: CGPoint(), size: size)) self.micButtonBackgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, transition: ComponentTransition(transition)) - transition.updateFrame(layer: self.micButton.layer, frame: CGRect(origin: CGPoint(), size: size)) + transition.updatePosition(layer: self.micButton.layer, position: CGRect(origin: CGPoint(), size: size).center) + transition.updateBounds(layer: self.micButton.layer, bounds: CGRect(origin: CGPoint(), size: size)) self.micButton.layoutItems() + if self.stopButtonIcon.image == nil { + self.stopButtonIcon.image = generateImage(CGSize(width: 14.0, height: 14.0), rotatedContext: { size, context in + UIGraphicsPushContext(context) + defer { + UIGraphicsPopContext() + } + + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(UIColor.white.cgColor) + + UIBezierPath(roundedRect: CGRect(origin: CGPoint(), size: size), cornerRadius: 3.0).fill() + })?.withRenderingMode(.alwaysTemplate) + } + if let image = self.stopButtonIcon.image { + self.stopButtonIcon.tintColor = interfaceState.theme.chat.inputPanel.panelControlColor + transition.updateFrame(view: self.stopButtonIcon, frame: image.size.centered(in: CGRect(origin: CGPoint(), size: size))) + } + var sendSlowmodeTimerTimestamp: (duration: Int32, timestamp: Int32)? if let slowmodeState = interfaceState.slowmodeState { switch slowmodeState.variant { @@ -527,7 +551,11 @@ public final class ChatTextInputActionButtonsNode: ASDisplayNode, ChatSendMessag public func updateAccessibility() { self.accessibilityTraits = .button - if !self.micButton.alpha.isZero { + if !self.stopButtonIcon.alpha.isZero { + //TODO:localize + self.accessibilityLabel = "Stop" + self.accessibilityHint = nil + } else if !self.micButton.alpha.isZero { switch self.micButton.mode { case .audio: self.accessibilityLabel = self.strings.VoiceOver_Chat_RecordModeVoiceMessage diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index cc0344eaed..3265d2f969 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -712,6 +712,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg self.sendActionButtons.micButton.alpha = 0.0 self.sendActionButtons.micButtonTintMaskView.alpha = 0.0 self.sendActionButtons.expandMediaInputButtonBackgroundView.alpha = 0.0 + self.sendActionButtons.stopButtonIcon.alpha = 0.0 self.mediaActionButtons = ChatTextInputActionButtonsNode(context: context, presentationInterfaceState: presentationInterfaceState, presentationContext: presentationContext, presentController: presentController) self.mediaActionButtons.sendContainerNode.alpha = 0.0 @@ -4612,7 +4613,9 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg hideMicButton = true } + var displayStop = false if let interfaceState = self.presentationInterfaceState { + displayStop = interfaceState.canStopIncomingStreamingMessage if case let .customChatContents(customChatContents) = interfaceState.subject { switch customChatContents.kind { case .hashTagSearch: @@ -4625,13 +4628,33 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } } - if hideMicButton || (mediaInputIsActive && !hideExpandMediaInput) { + if displayStop { + let alphaTransition = ComponentTransition(alphaTransition) + alphaTransition.setAlpha(view: self.mediaActionButtons.micButton, alpha: 0.0) + alphaTransition.setAlpha(view: self.mediaActionButtons.micButtonBackgroundView, alpha: 1.0) + alphaTransition.setAlpha(view: self.mediaActionButtons.micButtonTintMaskView, alpha: 0.0) + alphaTransition.setAlpha(view: self.mediaActionButtons.stopButtonIcon, alpha: 1.0) + + ComponentTransition(transition).setScale(view: self.mediaActionButtons.stopButtonIcon, scale: 1.0) + ComponentTransition(transition).setScale(view: self.mediaActionButtons.micButton, scale: 0.001) + ComponentTransition(transition).setScale(view: self.mediaActionButtons.micButtonTintMaskView, scale: 0.001) + } else if hideMicButton || (mediaInputIsActive && !hideExpandMediaInput) { + ComponentTransition(alphaTransition).setAlpha(view: self.mediaActionButtons.stopButtonIcon, alpha: 0.0) + ComponentTransition(transition).setScale(view: self.mediaActionButtons.stopButtonIcon, scale: 0.001) + ComponentTransition(transition).setScale(view: self.mediaActionButtons.micButton, scale: 1.0) + ComponentTransition(transition).setScale(view: self.mediaActionButtons.micButtonTintMaskView, scale: 1.0) + if !self.mediaActionButtons.micButton.alpha.isZero { alphaTransition.updateAlpha(layer: self.mediaActionButtons.micButton.layer, alpha: 0.0) alphaTransition.updateAlpha(layer: self.mediaActionButtons.micButtonBackgroundView.layer, alpha: 0.0) alphaTransition.updateAlpha(layer: self.mediaActionButtons.micButtonTintMaskView.layer, alpha: 0.0) } } else { + ComponentTransition(alphaTransition).setAlpha(view: self.mediaActionButtons.stopButtonIcon, alpha: 0.0) + ComponentTransition(transition).setScale(view: self.mediaActionButtons.stopButtonIcon, scale: 0.001) + ComponentTransition(transition).setScale(view: self.mediaActionButtons.micButton, scale: 1.0) + ComponentTransition(transition).setScale(view: self.mediaActionButtons.micButtonTintMaskView, scale: 1.0) + let micAlpha: CGFloat = self.mediaActionButtons.micButton.fadeDisabled ? 0.5 : 1.0 if !self.mediaActionButtons.micButton.alpha.isEqual(to: micAlpha) { alphaTransition.updateAlpha(layer: self.mediaActionButtons.micButton.layer, alpha: micAlpha) diff --git a/submodules/TelegramUI/Components/ShimmeringMask/BUILD b/submodules/TelegramUI/Components/ShimmeringMask/BUILD new file mode 100644 index 0000000000..5e0e9cd015 --- /dev/null +++ b/submodules/TelegramUI/Components/ShimmeringMask/BUILD @@ -0,0 +1,21 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "ShimmeringMask", + module_name = "ShimmeringMask", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/AsyncDisplayKit", + "//submodules/Display", + "//submodules/ShimmerEffect", + "//submodules/ComponentFlow", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift b/submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift new file mode 100644 index 0000000000..65ccc99e76 --- /dev/null +++ b/submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift @@ -0,0 +1,26 @@ +import Foundation +import UIKit +import AsyncDisplayKit +import Display +import ShimmerEffect +import ComponentFlow + +public final class ShimmeringMaskView: UIView { + public let contentView: UIView + + override public init(frame: CGRect) { + self.contentView = UIView() + + super.init(frame: frame) + + self.addSubview(self.contentView) + } + + required public init(coder: NSCoder) { + preconditionFailure() + } + + public func update(size: CGSize, transition: ComponentTransition) { + + } +} diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift index f0efbdfb2d..19bf329003 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift @@ -381,6 +381,9 @@ extension ChatControllerImpl { if previousState.slowmodeState != contentData.state.slowmodeState || previousState.boostsToUnrestrict != contentData.state.boostsToUnrestrict { animated = true } + if previousState.canStopIncomingStreamingMessage != contentData.state.canStopIncomingStreamingMessage { + animated = true + } var transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.4, curve: .spring) : .immediate if let forceAnimationTransition { @@ -445,6 +448,7 @@ extension ChatControllerImpl { presentationInterfaceState = presentationInterfaceState.updatedRemovePaidMessageFeeData(contentData.state.removePaidMessageFeeData) presentationInterfaceState = presentationInterfaceState.updatedViewForumAsMessages(contentData.state.viewForumAsMessages) presentationInterfaceState = presentationInterfaceState.updatedHasTopics(contentData.state.hasTopics) + presentationInterfaceState = presentationInterfaceState.updatedCanStopIncomingStreamingMessage(contentData.state.canStopIncomingStreamingMessage) presentationInterfaceState = presentationInterfaceState.updatedTitlePanelContext({ context in if contentData.state.pinnedMessageId != nil { diff --git a/submodules/TelegramUI/Sources/ChatControllerContentData.swift b/submodules/TelegramUI/Sources/ChatControllerContentData.swift index 77366bb6f7..8e30ccc23b 100644 --- a/submodules/TelegramUI/Sources/ChatControllerContentData.swift +++ b/submodules/TelegramUI/Sources/ChatControllerContentData.swift @@ -147,6 +147,7 @@ extension ChatControllerImpl { var removePaidMessageFeeData: ChatPresentationInterfaceState.RemovePaidMessageFeeData? var viewForumAsMessages: Bool = false var hasTopics: Bool = false + var canStopIncomingStreamingMessage: Bool = false var preloadNextChatPeerId: EnginePeer.Id? } @@ -711,6 +712,21 @@ extension ChatControllerImpl { } let globalPrivacySettings = context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.GlobalPrivacy()) + + let canStopIncomingStreamingMessage: Signal + if let peerId = chatLocation.peerId { + let key = PeerAndThreadId(peerId: peerId, threadId: chatLocation.threadId) + canStopIncomingStreamingMessage = context.account.postbox.combinedView(keys: [PostboxViewKey.typingDrafts(key)]) + |> map { views -> Bool in + guard let view = views.views[PostboxViewKey.typingDrafts(key)] as? TypingDraftsView else { + return false + } + return view.typingDraft != nil + } + |> distinctUntilChanged + } else { + canStopIncomingStreamingMessage = .single(false) + } self.peerDisposable = combineLatest( queue: Queue.mainQueue(), @@ -727,8 +743,9 @@ extension ChatControllerImpl { managingBot, adMessage, displayedPeerVerification, - globalPrivacySettings - ).startStrict(next: { [weak self] peerView, globalNotificationSettings, onlineMemberCount, hasScheduledMessages, hasTopics, pinnedCount, threadInfo, hasSearchTags, hasSavedChats, isPremiumRequiredForMessaging, managingBot, adMessage, displayedPeerVerification, globalPrivacySettings in + globalPrivacySettings, + canStopIncomingStreamingMessage + ).startStrict(next: { [weak self] peerView, globalNotificationSettings, onlineMemberCount, hasScheduledMessages, hasTopics, pinnedCount, threadInfo, hasSearchTags, hasSavedChats, isPremiumRequiredForMessaging, managingBot, adMessage, displayedPeerVerification, globalPrivacySettings, canStopIncomingStreamingMessage in guard let strongSelf = self else { return } @@ -738,6 +755,7 @@ extension ChatControllerImpl { if strongSelf.state.peerView === peerView && strongSelf.state.hasScheduledMessages == hasScheduledMessages && strongSelf.state.hasTopics == hasTopics + && strongSelf.state.canStopIncomingStreamingMessage == canStopIncomingStreamingMessage && strongSelf.state.threadInfo == threadInfo && strongSelf.state.hasSearchTags == hasSearchTags && strongSelf.state.hasSavedChats == hasSavedChats @@ -749,6 +767,7 @@ extension ChatControllerImpl { strongSelf.state.hasScheduledMessages = hasScheduledMessages strongSelf.state.hasTopics = hasTopics + strongSelf.state.canStopIncomingStreamingMessage = canStopIncomingStreamingMessage var upgradedToPeerId: PeerId? var movedToForumTopics = false @@ -1057,6 +1076,7 @@ extension ChatControllerImpl { strongSelf.state.explicitelyCanPinMessages = explicitelyCanPinMessages strongSelf.state.hasScheduledMessages = hasScheduledMessages strongSelf.state.hasTopics = hasTopics + strongSelf.state.canStopIncomingStreamingMessage = canStopIncomingStreamingMessage strongSelf.state.autoremoveTimeout = autoremoveTimeout strongSelf.state.currentSendAsPeerId = currentSendAsPeerId strongSelf.state.copyProtectionEnabled = copyProtectionEnabled @@ -1402,6 +1422,21 @@ extension ChatControllerImpl { let globalPrivacySettings = context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.GlobalPrivacy()) + let canStopIncomingStreamingMessage: Signal + if let peerId = chatLocation.peerId { + let key = PeerAndThreadId(peerId: peerId, threadId: chatLocation.threadId) + canStopIncomingStreamingMessage = context.account.postbox.combinedView(keys: [PostboxViewKey.typingDrafts(key)]) + |> map { views -> Bool in + guard let view = views.views[PostboxViewKey.typingDrafts(key)] as? TypingDraftsView else { + return false + } + return view.typingDraft != nil + } + |> distinctUntilChanged + } else { + canStopIncomingStreamingMessage = .single(false) + } + self.peerDisposable = (combineLatest(queue: Queue.mainQueue(), peerView, messageAndTopic, @@ -1412,9 +1447,10 @@ extension ChatControllerImpl { hasSavedChats, isPremiumRequiredForMessaging, managingBot, - globalPrivacySettings + globalPrivacySettings, + canStopIncomingStreamingMessage ) - |> deliverOnMainQueue).startStrict(next: { [weak self] peerView, messageAndTopic, savedMessagesPeer, onlineMemberCount, hasScheduledMessages, hasSearchTags, hasSavedChats, isPremiumRequiredForMessaging, managingBot, globalPrivacySettings in + |> deliverOnMainQueue).startStrict(next: { [weak self] peerView, messageAndTopic, savedMessagesPeer, onlineMemberCount, hasScheduledMessages, hasSearchTags, hasSavedChats, isPremiumRequiredForMessaging, managingBot, globalPrivacySettings, canStopIncomingStreamingMessage in guard let strongSelf = self else { return } @@ -1490,6 +1526,7 @@ extension ChatControllerImpl { } strongSelf.state.hasTopics = true + strongSelf.state.canStopIncomingStreamingMessage = canStopIncomingStreamingMessage if let savedMessagesPeerId { var peerPresences: [PeerId: PeerPresence] = [:] From 3051b1f3e4a965091b49ac567362b936d41ed874 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 17:04:16 +0200 Subject: [PATCH 07/14] Add implementation plan: context controller portal-view transition Eight-task plan covering ContextUI struct field additions, PortalTransitionStaging helper, CCEPN animateIn/animateOut wiring, ChatControllerNode contextTransitionContainer, two adopter sources, and manual visual verification. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...26-05-05-context-controller-portal-view.md | 999 ++++++++++++++++++ 1 file changed, 999 insertions(+) create mode 100644 docs/superpowers/plans/2026-05-05-context-controller-portal-view.md diff --git a/docs/superpowers/plans/2026-05-05-context-controller-portal-view.md b/docs/superpowers/plans/2026-05-05-context-controller-portal-view.md new file mode 100644 index 0000000000..85f1517e8e --- /dev/null +++ b/docs/superpowers/plans/2026-05-05-context-controller-portal-view.md @@ -0,0 +1,999 @@ +# Context Controller Portal-View Transition Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Replace `ContextControllerExtractedPresentationNode`'s manual visible-area clipping animation with a portal-based transition so the chat's natural ancestor clipping (and live re-layout) drives the bubble's in/out edges, fixing two issues: shadow/rounded-corner cutoff at chat-content-area edges, and stale clipping when chat re-layouts mid-animation. + +**Architecture:** Optional `sourceTransitionSurface: UIView?` on `ContextControllerTakeViewInfo` / `ContextControllerPutBackViewInfo`. When non-nil, CCEPN parks the source's `contentNode` inside that surface (via a `PortalSourceView` wrapper) for the duration of the in/out animation, mirrors it through a `PortalView(matchPosition: true)` clone in `ItemContentNode.offsetContainerNode`, and retargets the existing spring/position deltas onto the wrapper's layer instead of the overlay-side layer. The manual `clippingNode.layer.animateFrame(...)` calls are bypassed on this path. Resting state is unchanged from today (contentNode lives in `offsetContainerNode` while the menu is up). When the surface is nil, today's clipping path is preserved verbatim. First adopter: chat message bubbles (regular long-press + reaction context). + +**Tech Stack:** Swift, AsyncDisplayKit, UIKit. `PortalSourceView` / `PortalView` from `submodules/Display/Source/`. Build via Bazel (`Make.py` wrapper). + +**Reference spec:** `docs/superpowers/specs/2026-05-05-context-controller-portal-view-design.md`. + +**Build verification command** (used at the end of each task): + +```sh +source ~/.zshrc 2>/dev/null; python3 build-system/Make/Make.py --overrideXcodeVersion \ + --cacheDir ~/telegram-bazel-cache build \ + --configurationPath build-system/appstore-configuration.json \ + --gitCodesigningRepository git@gitlab.com:peter-iakovlev/fastlanematch.git \ + --gitCodesigningType development --gitCodesigningUseCurrent \ + --buildNumber=1 --configuration=debug_sim_arm64 --continueOnError +``` + +Expected: build succeeds (no compile errors). The project has no unit tests; verification is the build plus manual checks in Task 8. + +--- + +## Task 1: Add `sourceTransitionSurface` field to `ContextUI` structs + +**Files:** +- Modify: `submodules/ContextUI/Sources/ContextController.swift:347-372` + +The change is purely additive. Default values are `nil`, so every existing producer of `ContextControllerTakeViewInfo` / `ContextControllerPutBackViewInfo` keeps compiling unchanged and falls back to today's clipping path. + +- [ ] **Step 1: Replace the two struct definitions** + +Open `submodules/ContextUI/Sources/ContextController.swift`. Find lines 347–372 (the existing `ContextControllerTakeViewInfo` and `ContextControllerPutBackViewInfo` declarations). Replace exactly: + +Find: +```swift +public final class ContextControllerTakeViewInfo { + public enum ContainingItem { + case node(ContextExtractedContentContainingNode) + case view(ContextExtractedContentContainingView) + } + + public let containingItem: ContainingItem + public let contentAreaInScreenSpace: CGRect + public let maskView: UIView? + + public init(containingItem: ContainingItem, contentAreaInScreenSpace: CGRect, maskView: UIView? = nil) { + self.containingItem = containingItem + self.contentAreaInScreenSpace = contentAreaInScreenSpace + self.maskView = maskView + } +} + +public final class ContextControllerPutBackViewInfo { + public let contentAreaInScreenSpace: CGRect + public let maskView: UIView? + + public init(contentAreaInScreenSpace: CGRect, maskView: UIView? = nil) { + self.contentAreaInScreenSpace = contentAreaInScreenSpace + self.maskView = maskView + } +} +``` + +Replace with: +```swift +public final class ContextControllerTakeViewInfo { + public enum ContainingItem { + case node(ContextExtractedContentContainingNode) + case view(ContextExtractedContentContainingView) + } + + public let containingItem: ContainingItem + public let contentAreaInScreenSpace: CGRect + public let maskView: UIView? + public let sourceTransitionSurface: UIView? + + public init(containingItem: ContainingItem, contentAreaInScreenSpace: CGRect, maskView: UIView? = nil, sourceTransitionSurface: UIView? = nil) { + self.containingItem = containingItem + self.contentAreaInScreenSpace = contentAreaInScreenSpace + self.maskView = maskView + self.sourceTransitionSurface = sourceTransitionSurface + } +} + +public final class ContextControllerPutBackViewInfo { + public let contentAreaInScreenSpace: CGRect + public let maskView: UIView? + public let sourceTransitionSurface: UIView? + + public init(contentAreaInScreenSpace: CGRect, maskView: UIView? = nil, sourceTransitionSurface: UIView? = nil) { + self.contentAreaInScreenSpace = contentAreaInScreenSpace + self.maskView = maskView + self.sourceTransitionSurface = sourceTransitionSurface + } +} +``` + +- [ ] **Step 2: Build to confirm no caller broke** + +Run the full build verification command from the plan header. Expected: succeeds (existing init calls keep working because the new parameter is defaulted). + +- [ ] **Step 3: Commit** + +```bash +git add submodules/ContextUI/Sources/ContextController.swift +git commit -m "$(cat <<'EOF' +ContextUI: add sourceTransitionSurface to TakeViewInfo / PutBackInfo + +Optional UIView field provided by extracted-content sources to opt +into the upcoming portal-based transition path in CCEPN. Defaults to +nil, so existing callers are unchanged. + +Co-Authored-By: Claude Opus 4.7 (1M context) +EOF +)" +``` + +--- + +## Task 2: Add `PortalTransitionStaging` helper + `portalStaging` field on `ItemContentNode` + +**Files:** +- Modify: `submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift` (top of file, near other private types; and inside `ItemContentNode`) + +The class is unused at this point — Task 3 / Task 4 wire it in. Splitting this out is intentional: a buildable commit that adds the new abstraction with no behavior change makes review easier. + +- [ ] **Step 1: Insert the helper class definition** + +Open `submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift`. Imports already include `Display`, `AsyncDisplayKit`, and `UIKit` (line 1–14), which are sufficient for `PortalSourceView` / `PortalView`. + +After the closing `}` of the `private extension ContextControllerTakeViewInfo.ContainingItem { ... }` block (it ends at line 124, just before the start of `final class ContextControllerExtractedPresentationNode` at line 126), insert this new file-local helper: + +```swift +private final class PortalTransitionStaging { + enum SettleDestination { + case offsetContainer(ASDisplayNode) + case original + } + + enum OriginalParent { + case node(ASDisplayNode) + case view(UIView) + } + + weak var surface: UIView? + var wrapper: PortalSourceView? + var clone: PortalView? + var originalParent: OriginalParent? + var containingItem: ContextControllerTakeViewInfo.ContainingItem? + + /// Reparents the source's contentNode/contentView into a freshly-created + /// `PortalSourceView` inside `surface`, attaches a `PortalView(matchPosition: true)` + /// clone to `overlayHost`, sizes the wrapper so contentNode appears at + /// `targetScreenRect` in window coords, and returns the wrapper's layer. + /// + /// Returns nil if `PortalView(matchPosition:)` cannot be instantiated. In that + /// case staging is left empty and the caller takes the clipping fallback path. + func enter( + for containingItem: ContextControllerTakeViewInfo.ContainingItem, + in surface: UIView, + overlayHost: UIView, + targetScreenRect: CGRect + ) -> CALayer? { + guard let clone = PortalView(matchPosition: true) else { + return nil + } + + let wrapper = PortalSourceView() + + let originalParent: OriginalParent + switch containingItem { + case let .node(containingNode): + if let supernode = containingNode.contentNode.supernode { + originalParent = .node(supernode) + } else { + originalParent = .node(containingNode) + } + case let .view(containingView): + if let superview = containingView.contentView.superview { + originalParent = .view(superview) + } else { + originalParent = .view(containingView) + } + } + + // Place wrapper so that the bubble (= containingItem.contentRect, in + // containingItem.view coords) lands at `targetScreenRect` on screen. + // + // After reparenting contentNode/contentView into wrapper (preserving its + // frame value), the bubble's rect in wrapper-local coords numerically + // equals containingItem.contentRect (since the bubble was at + // contentNode.frame.origin + bubbleOffsetInContentNode == contentRect.origin + // in the original parent). So: + // bubble.screen.origin = wrapper.screen.origin + contentRect.origin + // and we want bubble.screen.origin == targetScreenRect.origin, hence: + // wrapper.screen.origin = targetScreenRect.origin - contentRect.origin + let bubbleOffsetInContainer = containingItem.contentRect.origin + let wrapperOriginInWindow = CGPoint( + x: targetScreenRect.origin.x - bubbleOffsetInContainer.x, + y: targetScreenRect.origin.y - bubbleOffsetInContainer.y + ) + let wrapperFrameInWindow = CGRect(origin: wrapperOriginInWindow, size: containingItem.view.bounds.size) + wrapper.frame = surface.convert(wrapperFrameInWindow, from: nil) + surface.addSubview(wrapper) + + switch containingItem { + case let .node(containingNode): + wrapper.addSubview(containingNode.contentNode.view) + case let .view(containingView): + wrapper.addSubview(containingView.contentView) + } + + wrapper.addPortal(view: clone) + overlayHost.addSubview(clone.view) + + self.surface = surface + self.wrapper = wrapper + self.clone = clone + self.originalParent = originalParent + self.containingItem = containingItem + + return wrapper.layer + } + + /// Tears down staging. Reparents contentNode into the requested destination, + /// removes clone from its overlay host, removes wrapper from surface. + /// All operations are explicit; we rely on Telegram's manual-animation policy + /// (no implicit CALayer actions) — no CATransaction wrapping needed. + func settle(into destination: SettleDestination) { + guard let wrapper = self.wrapper, let containingItem = self.containingItem else { + return + } + + switch destination { + case let .offsetContainer(offsetContainerNode): + switch containingItem { + case let .node(containingNode): + offsetContainerNode.addSubnode(containingNode.contentNode) + case let .view(containingView): + offsetContainerNode.view.addSubview(containingView.contentView) + } + case .original: + switch (containingItem, self.originalParent) { + case let (.node(containingNode), .some(.node(parent))): + parent.addSubnode(containingNode.contentNode) + case let (.view(containingView), .some(.view(parent))): + parent.addSubview(containingView.contentView) + case let (.node(containingNode), _): + // Surface lost; restore to the source's containing node as a fallback. + containingNode.addSubnode(containingNode.contentNode) + case let (.view(containingView), _): + containingView.addSubview(containingView.contentView) + } + } + + if let clone = self.clone { + wrapper.removePortal(view: clone) + clone.view.removeFromSuperview() + } + wrapper.removeFromSuperview() + + self.surface = nil + self.wrapper = nil + self.clone = nil + self.originalParent = nil + self.containingItem = nil + } +} +``` + +- [ ] **Step 2: Add `portalStaging` field on `ItemContentNode`** + +Find the `ItemContentNode` class declaration starting at line 134. The existing fields are: + +```swift +private final class ItemContentNode: ASDisplayNode { + let offsetContainerNode: ASDisplayNode + var containingItem: ContextControllerTakeViewInfo.ContainingItem + + var animateClippingFromContentAreaInScreenSpace: CGRect? + var storedGlobalFrame: CGRect? + var storedGlobalBoundsFrame: CGRect? + var presentationScale: CGFloat = 1.0 +``` + +Insert after the `presentationScale` line: + +```swift + var portalStaging: PortalTransitionStaging? +``` + +- [ ] **Step 3: Build to confirm helper compiles** + +Run the build verification command from the plan header. Expected: succeeds. The new class and field are unreferenced; the build only validates syntax/types. + +- [ ] **Step 4: Commit** + +```bash +git add submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift +git commit -m "$(cat <<'EOF' +CCEPN: add PortalTransitionStaging helper + +File-local class that owns the transient PortalSourceView wrapper ++ PortalView clone lifecycle for the upcoming portal-based transition +path. Adds an unused portalStaging field on ItemContentNode. Wired +up in subsequent commits. + +Co-Authored-By: Claude Opus 4.7 (1M context) +EOF +)" +``` + +--- + +## Task 3: Wire portal path into `case .animateIn:` + +**Files:** +- Modify: `submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift:1265-1474` (the `.animateIn` arm of the `stateTransition` switch). + +The portal path is opt-in: only fires when `takeInfo.sourceTransitionSurface != nil` AND `presentationScale == 1.0` AND `staging.enter(...)` succeeds. Otherwise the today's-clipping path runs unchanged. + +CCEPN's `update(state:transition:)` does not have direct access to the takeInfo at `case .animateIn` time — `takeInfo` is consumed earlier at the `case let .extracted(source):` block (line ~631) where `ItemContentNode` is constructed. We thread `sourceTransitionSurface` through the `ItemContentNode` so `.animateIn` can see it. + +- [ ] **Step 1: Stash `sourceTransitionSurface` on `ItemContentNode` at construction time** + +Find the construction site at line 631–656 (`case let .extracted(source):` block). Inside the `if-let` for `takeInfo` (around line 632–655), after the existing line `contentNodeValue.animateClippingFromContentAreaInScreenSpace = takeInfo.contentAreaInScreenSpace` (line 636), add: + +```swift +contentNodeValue.sourceTransitionSurface = takeInfo.sourceTransitionSurface +``` + +Then add a matching field on `ItemContentNode` (next to `animateClippingFromContentAreaInScreenSpace`, line 138): + +```swift +weak var sourceTransitionSurface: UIView? +``` + +The field is `weak` because the surface's lifetime is owned by the source side, not by CCEPN. + +- [ ] **Step 2: Bypass `takeContainingNode()` when staging is active** + +Find line 1269–1271: + +```swift +if let contentNode = itemContentNode { + contentNode.takeContainingNode() +} +``` + +The portal path needs contentNode to NOT be reparented into `offsetContainerNode` here — it'll go into the wrapper instead (next step). Replace with: + +```swift +if let contentNode = itemContentNode { + if let surface = contentNode.sourceTransitionSurface, contentNode.presentationScale == 1.0 { + // Defer reparenting to staging.enter (Step 3 below). + let _ = surface + } else { + contentNode.takeContainingNode() + } +} +``` + +- [ ] **Step 3: Add the staging-enter / animation-target retargeting block** + +Find line 1280: `if let contentNode = itemContentNode { ... }`. The block currently begins with the clipping animation guard (lines 1281–1284). Insert this BEFORE that guard, as the new very-first thing inside the block: + +```swift +let portalAnimationLayer: CALayer? +if let surface = contentNode.sourceTransitionSurface, contentNode.presentationScale == 1.0 { + let staging = PortalTransitionStaging() + let currentContentLocalFrameInWindow = self.view.convert( + convertFrame(contentRect, from: self.scrollNode.view, to: self.view), + to: nil + ) + if let layer = staging.enter( + for: contentNode.containingItem, + in: surface, + overlayHost: contentNode.offsetContainerNode.view, + targetScreenRect: currentContentLocalFrameInWindow + ) { + contentNode.portalStaging = staging + portalAnimationLayer = layer + } else { + // Staging refused (PortalView nil); fall back to clipping by reparenting now. + contentNode.takeContainingNode() + portalAnimationLayer = nil + } +} else { + portalAnimationLayer = nil +} +``` + +- [ ] **Step 4: Gate the existing clipping animation on no-staging** + +Find lines 1281–1284: + +```swift +if let animateClippingFromContentAreaInScreenSpace = contentNode.animateClippingFromContentAreaInScreenSpace { + self.clippingNode.layer.animateFrame(from: CGRect(origin: CGPoint(x: 0.0, y: animateClippingFromContentAreaInScreenSpace.minY), size: CGSize(width: layout.size.width, height: animateClippingFromContentAreaInScreenSpace.height)), to: CGRect(origin: CGPoint(), size: layout.size), duration: 0.2) + self.clippingNode.layer.animateBoundsOriginYAdditive(from: animateClippingFromContentAreaInScreenSpace.minY, to: 0.0, duration: 0.2) +} +``` + +Replace with: + +```swift +if portalAnimationLayer == nil, let animateClippingFromContentAreaInScreenSpace = contentNode.animateClippingFromContentAreaInScreenSpace { + self.clippingNode.layer.animateFrame(from: CGRect(origin: CGPoint(x: 0.0, y: animateClippingFromContentAreaInScreenSpace.minY), size: CGSize(width: layout.size.width, height: animateClippingFromContentAreaInScreenSpace.height)), to: CGRect(origin: CGPoint(), size: layout.size), duration: 0.2) + self.clippingNode.layer.animateBoundsOriginYAdditive(from: animateClippingFromContentAreaInScreenSpace.minY, to: 0.0, duration: 0.2) +} +``` + +- [ ] **Step 5: Retarget the position springs onto `portalAnimationLayer` when present** + +Find the two `contentNode.layer.animateSpring(...)` calls at lines 1313–1322 and 1324–1332. They animate `contentNode.layer` (= the `ItemContentNode`'s layer). When `portalAnimationLayer` is non-nil, the springs need to target the wrapper's layer instead. + +Replace lines 1312–1332 (the X-distance spring guard + X spring + Y spring) with: + +```swift +let animateLayer: CALayer = portalAnimationLayer ?? contentNode.layer + +if animationInContentXDistance != 0.0 { + animateLayer.animateSpring( + from: -animationInContentXDistance as NSNumber, to: 0.0 as NSNumber, + keyPath: "position.x", + duration: duration, + delay: 0.0, + initialVelocity: 0.0, + damping: springDamping, + additive: true + ) +} + +animateLayer.animateSpring( + from: -animationInContentYDistance as NSNumber, to: 0.0 as NSNumber, + keyPath: "position.y", + duration: duration, + delay: 0.0, + initialVelocity: 0.0, + damping: springDamping, + additive: true +) +``` + +(Net change: replace each `contentNode.layer.animateSpring(...)` with `animateLayer.animateSpring(...)`, keeping every other parameter identical.) + +The `reactionPreviewView` springs at lines 1334–1355 stay unchanged — `reactionPreviewView` lives in CCEPN's own tree, never inside the source-side surface. + +- [ ] **Step 6: Attach a settle completion to the Y-spring** + +The Y-distance spring is the longest-lived in the animateIn animation set. Add a completion handler that calls `staging.settle(into: .offsetContainer(...))` when staging is active. Replace the just-edited Y-spring (the one at the bottom of the block from Step 5): + +```swift +animateLayer.animateSpring( + from: -animationInContentYDistance as NSNumber, to: 0.0 as NSNumber, + keyPath: "position.y", + duration: duration, + delay: 0.0, + initialVelocity: 0.0, + damping: springDamping, + additive: true +) +``` + +with: + +```swift +animateLayer.animateSpring( + from: -animationInContentYDistance as NSNumber, to: 0.0 as NSNumber, + keyPath: "position.y", + duration: duration, + delay: 0.0, + initialVelocity: 0.0, + damping: springDamping, + additive: true, + completion: { [weak contentNode] _ in + guard let contentNode else { return } + if let staging = contentNode.portalStaging { + staging.settle(into: .offsetContainer(contentNode.offsetContainerNode)) + contentNode.portalStaging = nil + } + } +) +``` + +(The `Display` module's `animateSpring` already accepts a `completion:` parameter — the dismiss path uses it at line 1665.) + +- [ ] **Step 7: Build to confirm everything compiles** + +Run the build verification command from the plan header. Expected: succeeds. Existing source-callers don't pass `sourceTransitionSurface`, so portal path is dormant; visual behavior is unchanged. + +- [ ] **Step 8: Commit** + +```bash +git add submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift +git commit -m "$(cat <<'EOF' +CCEPN: portal-mode animateIn (gated on sourceTransitionSurface) + +When a source provides sourceTransitionSurface (and presentationScale +is 1.0), reparent the source's contentNode into a PortalSourceView +inside the surface, mirror it via PortalView(matchPosition: true) into +ItemContentNode.offsetContainerNode, and retarget the position springs +onto the wrapper's layer. The clipping animation is bypassed in this +mode. On animation completion, contentNode is reparented home into +offsetContainerNode (today's resting state). Fallback path unchanged. + +Co-Authored-By: Claude Opus 4.7 (1M context) +EOF +)" +``` + +--- + +## Task 4: Wire portal path into `case .animateOut:` + +**Files:** +- Modify: `submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift:1487-1684` (the `.animateOut` arm of the `stateTransition` switch). + +Mirror of Task 3 but in reverse direction: contentNode goes from `offsetContainerNode` back into the source-side surface, animation runs in chat tree, and on completion contentNode is reparented to its original parent (chat-side). + +- [ ] **Step 1: Declare `portalAnimationLayer` at the top of the animateOut block** + +Find line 1507 (`let currentContentScreenFrame: CGRect`), inside `case .animateOut(...)`. Insert immediately before that line: + +```swift + var portalAnimationLayer: CALayer? = nil +``` + +The local is `var` because the `.extracted` arm of the source switch (next step) populates it. It must be declared up here — outside the source switch — because the dismiss-spring code further down (the `if let contentNode = itemContentNode { ... }` block around line 1622) needs to read it. + +- [ ] **Step 2: Replace the `.extracted` arm of the source switch** + +Find lines 1528–1543 (the `.extracted` arm of the source switch inside `.animateOut`). The current code: + +```swift +case let .extracted(source): + let putBackInfo = source.putBack() + + if let putBackInfo = putBackInfo { + self.clippingNode.layer.animateFrame(from: CGRect(origin: CGPoint(), size: layout.size), to: CGRect(origin: CGPoint(x: 0.0, y: putBackInfo.contentAreaInScreenSpace.minY), size: CGSize(width: layout.size.width, height: putBackInfo.contentAreaInScreenSpace.height)), duration: duration, timingFunction: timingFunction, removeOnCompletion: false) + self.clippingNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: putBackInfo.contentAreaInScreenSpace.minY, duration: duration, timingFunction: timingFunction, removeOnCompletion: false) + } + + if let contentNode = itemContentNode { + currentContentScreenFrame = convertFrame(contentNode.containingItem.contentRect, from: contentNode.containingItem.view, to: self.view) + if currentContentScreenFrame.origin.x < 0.0 { + contentParentGlobalFrameOffsetX = layout.size.width + } + } else { + return + } +``` + +Replace with (note: assigns into the `portalAnimationLayer` declared in Step 1, no re-declaration here): + +```swift +case let .extracted(source): + let putBackInfo = source.putBack() + + if let putBackInfo = putBackInfo, + let surface = putBackInfo.sourceTransitionSurface, + let contentNode = itemContentNode, + contentNode.presentationScale == 1.0 + { + let preStagingScreenFrame = convertFrame(contentNode.containingItem.contentRect, from: contentNode.containingItem.view, to: self.view) + let preStagingScreenFrameInWindow = self.view.convert(preStagingScreenFrame, to: nil) + let staging = PortalTransitionStaging() + if let layer = staging.enter( + for: contentNode.containingItem, + in: surface, + overlayHost: contentNode.offsetContainerNode.view, + targetScreenRect: preStagingScreenFrameInWindow + ) { + contentNode.portalStaging = staging + portalAnimationLayer = layer + } + } + + if portalAnimationLayer == nil, let putBackInfo = putBackInfo { + self.clippingNode.layer.animateFrame(from: CGRect(origin: CGPoint(), size: layout.size), to: CGRect(origin: CGPoint(x: 0.0, y: putBackInfo.contentAreaInScreenSpace.minY), size: CGSize(width: layout.size.width, height: putBackInfo.contentAreaInScreenSpace.height)), duration: duration, timingFunction: timingFunction, removeOnCompletion: false) + self.clippingNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: putBackInfo.contentAreaInScreenSpace.minY, duration: duration, timingFunction: timingFunction, removeOnCompletion: false) + } + + if let contentNode = itemContentNode { + currentContentScreenFrame = convertFrame(contentNode.containingItem.contentRect, from: contentNode.containingItem.view, to: self.view) + if currentContentScreenFrame.origin.x < 0.0 { + contentParentGlobalFrameOffsetX = layout.size.width + } + } else { + return + } +``` + +- [ ] **Step 3: Retarget the dismiss springs onto `portalAnimationLayer` when present** + +Find lines 1643–1684 (the X spring at 1644, the position adjustment at 1655, and the Y spring at 1657). Currently: + +```swift +if animationInContentXDistance != 0.0 { + contentNode.offsetContainerNode.layer.animate( + from: -animationInContentXDistance as NSNumber, + to: 0.0 as NSNumber, + keyPath: "position.x", + timingFunction: timingFunction, + duration: duration, + delay: 0.0, + additive: true + ) +} + +contentNode.offsetContainerNode.position = contentNode.offsetContainerNode.position.offsetBy(dx: animationInContentXDistance, dy: -animationInContentYDistance) +let reactionContextNodeIsAnimatingOut = self.reactionContextNodeIsAnimatingOut +contentNode.offsetContainerNode.layer.animate( + from: animationInContentYDistance as NSNumber, + to: 0.0 as NSNumber, + keyPath: "position.y", + timingFunction: timingFunction, + duration: duration, + delay: 0.0, + additive: true, + completion: { [weak self] _ in + Queue.mainQueue().after(reactionContextNodeIsAnimatingOut ? 0.2 * UIView.animationDurationFactor() : 0.0, { + if let strongSelf = self, let contentNode = strongSelf.itemContentNode { + switch contentNode.containingItem { + case let .node(containingNode): + containingNode.addSubnode(containingNode.contentNode) + case let .view(containingView): + containingView.addSubview(containingView.contentView) + } + } + + contentNode.containingItem.isExtractedToContextPreview = false + contentNode.containingItem.isExtractedToContextPreviewUpdated?(false) + contentNode.containingItem.onDismiss?() + + restoreOverlayViews.forEach({ $0() }) + completion() + }) + } +) +``` + +Replace with the staging-aware variant: + +```swift +let animateLayer: CALayer = portalAnimationLayer ?? contentNode.offsetContainerNode.layer + +if animationInContentXDistance != 0.0 { + animateLayer.animate( + from: -animationInContentXDistance as NSNumber, + to: 0.0 as NSNumber, + keyPath: "position.x", + timingFunction: timingFunction, + duration: duration, + delay: 0.0, + additive: true + ) +} + +if portalAnimationLayer == nil { + contentNode.offsetContainerNode.position = contentNode.offsetContainerNode.position.offsetBy(dx: animationInContentXDistance, dy: -animationInContentYDistance) +} + +let reactionContextNodeIsAnimatingOut = self.reactionContextNodeIsAnimatingOut +animateLayer.animate( + from: animationInContentYDistance as NSNumber, + to: 0.0 as NSNumber, + keyPath: "position.y", + timingFunction: timingFunction, + duration: duration, + delay: 0.0, + additive: true, + completion: { [weak self] _ in + Queue.mainQueue().after(reactionContextNodeIsAnimatingOut ? 0.2 * UIView.animationDurationFactor() : 0.0, { + if let strongSelf = self, let contentNode = strongSelf.itemContentNode { + if let staging = contentNode.portalStaging { + staging.settle(into: .original) + contentNode.portalStaging = nil + } else { + switch contentNode.containingItem { + case let .node(containingNode): + containingNode.addSubnode(containingNode.contentNode) + case let .view(containingView): + containingView.addSubview(containingView.contentView) + } + } + } + + if let strongSelf = self, let contentNode = strongSelf.itemContentNode { + contentNode.containingItem.isExtractedToContextPreview = false + contentNode.containingItem.isExtractedToContextPreviewUpdated?(false) + contentNode.containingItem.onDismiss?() + } + + restoreOverlayViews.forEach({ $0() }) + completion() + }) + } +) +``` + +Three substantive changes: +- The X / Y spring `animate(...)` calls target `animateLayer` instead of `contentNode.offsetContainerNode.layer`. +- The `offsetContainerNode.position = ...` mutation is skipped on the portal path (offsetContainerNode is not the visible animation layer in that case; mutating it would be a no-op visually but is unnecessary). +- The completion's reparent step branches on `contentNode.portalStaging` — staging owns the reparent on the portal path. + +- [ ] **Step 4: Build** + +Run the build verification command. Expected: succeeds. + +- [ ] **Step 5: Commit** + +```bash +git add submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift +git commit -m "$(cat <<'EOF' +CCEPN: portal-mode animateOut (gated on sourceTransitionSurface) + +Symmetric to portal-mode animateIn: when putBackInfo provides a +surface (and presentationScale is 1.0), reparent contentNode out of +offsetContainerNode into a PortalSourceView in the surface, mirror +via PortalView clone in offsetContainerNode, retarget dismiss springs +onto the wrapper's layer, skip the manual clip animation. On +completion, staging reparents contentNode to its original chat-side +parent. Fallback path unchanged. + +Co-Authored-By: Claude Opus 4.7 (1M context) +EOF +)" +``` + +--- + +## Task 5: Add `contextTransitionContainer` to `ChatControllerNode` + +**Files:** +- Modify: `submodules/TelegramUI/Sources/ChatControllerNode.swift` (private storage near other view fields; `ensureContextTransitionContainer()` accessor; frame update inside `containerLayoutUpdated`). + +`ChatControllerNode` is a 4400+ line file. The exact line numbers below are anchors — search for the surrounding code to locate the precise insertion point if your local copy has drifted. + +- [ ] **Step 1: Add private storage** + +Open `submodules/TelegramUI/Sources/ChatControllerNode.swift`. Find a section of private view fields near the top of the class (after `class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {` at line 171). A natural location is just after other private optional view fields. Search for `private var` near the start of the class body and insert this declaration alongside them — for example, immediately before `weak var node: ChatControllerNode?` is *not* applicable (that's on a different type at line 80); look in the body of `ChatControllerNode` itself. + +Concretely: after the existing private property block (anywhere in the first 250 lines after class start), add: + +```swift + private var contextTransitionContainer: UIView? +``` + +If you cannot find an obvious spot, place it directly above the `historyNode` property — `grep -n "self.historyNode = historyNode"` (line 166) is one anchor; the property declaration itself is nearby. + +- [ ] **Step 2: Add the accessor** + +Find the `frameForVisibleArea()` function at line 4038. Immediately before its `func frameForVisibleArea() -> CGRect {` line, insert: + +```swift + func ensureContextTransitionContainer() -> UIView { + if let existing = self.contextTransitionContainer { + existing.frame = self.frameForVisibleArea() + return existing + } + let v = UIView() + v.clipsToBounds = true + v.isUserInteractionEnabled = false + v.frame = self.frameForVisibleArea() + self.view.insertSubview(v, aboveSubview: self.historyNodeContainer.view) + self.contextTransitionContainer = v + return v + } +``` + +The choice `aboveSubview: self.historyNodeContainer.view` puts the container at the same Z position as the chat history. If a future visual check shows the input panel or navigation chrome rendering UNDER the staged bubble (when it should render OVER), change to `belowSubview:` against the appropriate subview. The first visual smoke test in Task 8 will surface this. + +- [ ] **Step 3: Wire frame update into the layout pass** + +Find the end of `containerLayoutUpdated(...)` at line 3530–3533: + +```swift + self.derivedLayoutState = ChatControllerNodeDerivedLayoutState(inputContextPanelsFrame: inputContextPanelsFrame, inputContextPanelsOverMainPanelFrame: inputContextPanelsOverMainPanelFrame, inputNodeHeight: inputNodeHeightAndOverflow?.0, inputNodeAdditionalHeight: inputNodeHeightAndOverflow?.1, upperInputPositionBound: inputNodeHeightAndOverflow?.0 != nil ? self.upperInputPositionBound : nil) + + //self.notifyTransitionCompletionListeners(transition: transition) + } +``` + +Just before the closing `}` of `containerLayoutUpdated`, insert: + +```swift + if let contextTransitionContainer = self.contextTransitionContainer { + contextTransitionContainer.frame = self.frameForVisibleArea() + } +``` + +This makes the surface track the chat's visible-area rect on every layout pass, which is what gives Issue B (live source-side dynamics) its win. + +- [ ] **Step 4: Build** + +Run the build verification command. Expected: succeeds. Nothing references `ensureContextTransitionContainer()` yet, so this is a no-op behaviorally. + +- [ ] **Step 5: Commit** + +```bash +git add submodules/TelegramUI/Sources/ChatControllerNode.swift +git commit -m "$(cat <<'EOF' +ChatControllerNode: add contextTransitionContainer + +Lazy UIView sized to frameForVisibleArea(), updated in +containerLayoutUpdated, used as the sourceTransitionSurface for +extracted-content context menus in subsequent commits. + +Co-Authored-By: Claude Opus 4.7 (1M context) +EOF +)" +``` + +--- + +## Task 6: Adopt `sourceTransitionSurface` in `ChatMessageContextExtractedContentSource` + +**Files:** +- Modify: `submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift:76-120` (the `takeView` and `putBack` of `ChatMessageContextExtractedContentSource`). + +This is the regular bubble long-press path. After this task, that path uses the portal transition. + +- [ ] **Step 1: Update `takeView()`** + +Find lines 76–99 (the `func takeView()` body of `ChatMessageContextExtractedContentSource`). The relevant single line is line 90: + +```swift + result = ContextControllerTakeViewInfo(containingItem: .node(contentNode), contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) +``` + +Replace with: + +```swift + result = ContextControllerTakeViewInfo(containingItem: .node(contentNode), contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil), sourceTransitionSurface: chatNode.ensureContextTransitionContainer()) +``` + +- [ ] **Step 2: Update `putBack()`** + +Find lines 101–120 (`func putBack()`). The relevant single line is line 115: + +```swift + result = ContextControllerPutBackViewInfo(contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) +``` + +Replace with: + +```swift + result = ContextControllerPutBackViewInfo(contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil), sourceTransitionSurface: chatNode.ensureContextTransitionContainer()) +``` + +- [ ] **Step 3: Build** + +Run the build verification command. Expected: succeeds. + +- [ ] **Step 4: Commit** + +```bash +git add submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift +git commit -m "$(cat <<'EOF' +Adopt sourceTransitionSurface in ChatMessage extraction source + +ChatMessageContextExtractedContentSource (regular long-press menu) +now passes the chat's contextTransitionContainer as the surface for +take/putBack, enabling CCEPN's portal transition path. + +Co-Authored-By: Claude Opus 4.7 (1M context) +EOF +)" +``` + +--- + +## Task 7: Adopt `sourceTransitionSurface` in `ChatMessageReactionContextExtractedContentSource` + +**Files:** +- Modify: `submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift:452-490` (the reaction-context source's `takeView` and `putBack`). + +This is the reaction context menu path on a bubble. After this task, that path also uses the portal transition. + +- [ ] **Step 1: Update `takeView()`** + +Find lines 452–470 (the `func takeView()` body of `ChatMessageReactionContextExtractedContentSource`). Line 466: + +```swift + result = ContextControllerTakeViewInfo(containingItem: .view(self.contentView), contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) +``` + +Replace with: + +```swift + result = ContextControllerTakeViewInfo(containingItem: .view(self.contentView), contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil), sourceTransitionSurface: chatNode.ensureContextTransitionContainer()) +``` + +- [ ] **Step 2: Update `putBack()`** + +Find lines 472–490. Line 486: + +```swift + result = ContextControllerPutBackViewInfo(contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) +``` + +Replace with: + +```swift + result = ContextControllerPutBackViewInfo(contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil), sourceTransitionSurface: chatNode.ensureContextTransitionContainer()) +``` + +- [ ] **Step 3: Build** + +Run the build verification command. Expected: succeeds. + +- [ ] **Step 4: Commit** + +```bash +git add submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift +git commit -m "$(cat <<'EOF' +Adopt sourceTransitionSurface in ChatMessage reaction source + +ChatMessageReactionContextExtractedContentSource (reaction context +menu on a bubble) now passes the chat's contextTransitionContainer +as the surface for take/putBack, enabling CCEPN's portal transition +path. + +Co-Authored-By: Claude Opus 4.7 (1M context) +EOF +)" +``` + +--- + +## Task 8: Manual visual verification + +**Files:** None modified. This task is hands-on testing. + +The project has no unit tests; the design's claims (Issue A, Issue B fixes, fallback unchanged) need to be verified by exercising the app in a simulator. The four checks below correspond to the four spec verification items. + +- [ ] **Step 1: Final build (no `--continueOnError`)** + +```sh +source ~/.zshrc 2>/dev/null; python3 build-system/Make/Make.py --overrideXcodeVersion \ + --cacheDir ~/telegram-bazel-cache build \ + --configurationPath build-system/appstore-configuration.json \ + --gitCodesigningRepository git@gitlab.com:peter-iakovlev/fastlanematch.git \ + --gitCodesigningType development --gitCodesigningUseCurrent \ + --buildNumber=1 --configuration=debug_sim_arm64 +``` + +Expected: clean build (zero errors). + +- [ ] **Step 2: Issue A — boundary clipping check** + +Run the app on the iOS simulator. Open a chat with messages. Long-press a message that is positioned near the top of the chat (so its bubble overlaps the navigation bar) and another that is positioned near the bottom (overlapping the input panel). Compare the in/out animation against `master`: + +- On `master`: the bubble visibly cuts at the chat content-area edge during the in/out transition (a straight horizontal line where shadow/rounded corner is sliced). +- On this branch: the cut should follow the chat's actual ancestor mask shape — no straight-line stutter at the manual-clip rect edge. The shadow / rounded corner should clip exactly as the in-place bubble does at rest. + +If the bubble appears NOT to be clipped at all (i.e., it visibly extends OVER the navigation bar / input panel during the animation), check Z-order — see Task 5 Step 2 note about `aboveSubview` vs `belowSubview`. + +- [ ] **Step 3: Issue B — live source dynamics check** + +Long-press a message. Mid-animation (during the spring's ~0.42s duration), induce a chat layout change — easiest method: tap the input field to bring up the keyboard right at the moment of long-press. Visually watch the bubble. The clipping should track the chat's live state, not a frozen snapshot taken at animation start. + +- [ ] **Step 4: Reaction context check** + +On a message in the same chat, open the reaction context menu (long-press to bring up the menu, then tap an empty area or whatever invokes the reactions). Confirm the in/out animation looks correct (same as Step 2's criteria). + +- [ ] **Step 5: Fallback path regression check** + +Exercise three sources that pass `sourceTransitionSurface = nil` (i.e., still on the today's-clipping path): + +- A play-once voice or video message context (`ChatViewOnceMessageContextExtractedContentSource`). +- A chat-message-navigation-button context (`ChatMessageNavigationButtonContextExtractedContentSource`). +- The overlay audio player context (`OverlayAudioPlayerControllerNode`). +- The chat search title accessory context (`ChatSearchTitleAccessoryPanelNode`). + +Confirm each looks identical to `master` — no visible regressions. + +- [ ] **Step 6: Take notes on any visible regressions** + +If any regression is observed in steps 2–5, capture (a) the source it occurred in, (b) the exact visual symptom, (c) whether it reproduces on `master`. File these against this plan; do not silently land regressions. + +--- + +## Limitation noted in the design + +The portal path is gated on `presentationScale == 1.0`. When CCEPN detects ancestor scale on the source view (e.g., a chat shown inside a sheet with a container transform), it falls back to the clipping path. Lifting this restriction is future work — the animation deltas would need to be divided by `presentationScale` before being applied to the wrapper's layer (since the wrapper sits in scaled chat-tree-local coords, while deltas are computed in screen coords). None of the first adopters in this plan trigger that case. + +## Files touched (summary) + +- `submodules/ContextUI/Sources/ContextController.swift` — Task 1. +- `submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift` — Tasks 2, 3, 4. +- `submodules/TelegramUI/Sources/ChatControllerNode.swift` — Task 5. +- `submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift` — Tasks 6, 7. From 05f1f19ab0a9a2272836ddfe8af9b1a18f99e2ba Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 20:26:25 +0200 Subject: [PATCH 08/14] Context controller portal-view transition --- .../plans/2026-05-05-shimmering-mask-view.md | 552 ------------------ .../2026-05-05-shimmering-mask-view-design.md | 152 ----- .../ContextUI/Sources/ContextController.swift | 14 +- .../ChatMessageTextBubbleContentNode.swift | 46 +- ...tControllerExtractedPresentationNode.swift | 322 +++++++++- .../Components/ShimmeringMask/BUILD | 5 +- .../Sources/ShimmeringMaskView.swift | 123 +++- .../Sources/ChatControllerNode.swift | 38 +- ...essageContextControllerContentSource.swift | 14 +- 9 files changed, 495 insertions(+), 771 deletions(-) delete mode 100644 docs/superpowers/plans/2026-05-05-shimmering-mask-view.md delete mode 100644 docs/superpowers/specs/2026-05-05-shimmering-mask-view-design.md diff --git a/docs/superpowers/plans/2026-05-05-shimmering-mask-view.md b/docs/superpowers/plans/2026-05-05-shimmering-mask-view.md deleted file mode 100644 index 7e748a2e0d..0000000000 --- a/docs/superpowers/plans/2026-05-05-shimmering-mask-view.md +++ /dev/null @@ -1,552 +0,0 @@ -# ShimmeringMaskView Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Build a reusable `ShimmeringMaskView` (alpha-mask "running shimmer" effect) and wire it as the host for `streamingStatusTextNode` in `ChatMessageTextBubbleContentNode` to give the streaming-status line a ChatGPT-style "thinking" effect. - -**Architecture:** Single `CAGradientLayer` set as `contentView.layer.mask`. Horizontal three-stop gradient `[white@1.0, white@peakAlpha, white@1.0]` with the dip parked at the layer's bounds center; layer is oversized (`size.width + 2 × travelDistance`) so its `alpha=1.0` edges keep `contentView` covered at every animation phase. A `position.x` `CABasicAnimation` (`additive: true`, `repeatCount: .infinity`, `easeOut`) shifts the dip across the wave path. `HierarchyTrackingLayer` re-arms the animation when the view re-enters the hierarchy. API mirrors `VideoChatVideoLoadingEffectView` (init takes appearance constants; `update` takes layout values + a `ComponentTransition`). - -**Tech Stack:** Swift, UIKit, `CAGradientLayer`, `CABasicAnimation`, `HierarchyTrackingLayer`, `ComponentFlow.ComponentTransition`, Bazel (`swift_library`). - -**Reference reading (no edits needed):** -- Spec: `docs/superpowers/specs/2026-05-05-shimmering-mask-view-design.md` -- Pattern reference: `submodules/TelegramCallsUI/Sources/VideoChatVideoLoadingEffectView.swift` -- Pattern reference: `submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/LoadingEffectView.swift` -- Pattern reference: `submodules/TelegramUI/Components/TextLoadingEffect/Sources/TextLoadingEffect.swift` - -**Important context — no unit tests in this project:** -This codebase has no unit-test harness (see `CLAUDE.md`: *"No tests are used at the moment"*). Verification is done by running the full Bazel build and visually inspecting the result. The "test" steps in this plan therefore replace per-task pytest-style verification with **build steps** that compile the affected modules, plus one explicit manual run-the-app step at the end. - -**Build invocation used throughout this plan:** - -```sh -source ~/.zshrc 2>/dev/null; \ -python3 build-system/Make/Make.py --overrideXcodeVersion \ - --cacheDir ~/telegram-bazel-cache \ - build \ - --configurationPath build-system/appstore-configuration.json \ - --gitCodesigningRepository git@gitlab.com:peter-iakovlev/fastlanematch.git \ - --gitCodesigningType development --gitCodesigningUseCurrent --buildNumber=1 \ - --configuration=debug_sim_arm64 -``` - -The `source ~/.zshrc 2>/dev/null;` prefix is required to pick up `TELEGRAM_CODESIGNING_GIT_PASSWORD`. Bazel is the only supported build path; there is no per-module build target — the full `Telegram/Telegram` app is built. First build of a fresh worktree may take 10+ minutes; incremental builds during this plan are typically 30s–2min. - ---- - -## File Structure - -| Action | Path | Responsibility | -|---|---|---| -| **Modify** | `submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift` | Replace stub with full implementation. | -| **Modify** | `submodules/TelegramUI/Components/ShimmeringMask/BUILD` | Trim deps to `ComponentFlow` + `Components/HierarchyTrackingLayer`. | -| **Modify** | `submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift` | Wrap `streamingStatusTextNode` in a `ShimmeringMaskView`; route position/bounds/alpha animation to the wrapper. | - -The `ShimmeringMask` module is already wired as a dep on the `ChatMessageTextBubbleContentNode` library (we confirmed `submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/BUILD` has `"//submodules/TelegramUI/Components/ShimmeringMask"`), and the consumer file already has `import ShimmeringMask`. No BUILD edits are needed for the consumer side. - ---- - -### Task 1: Trim BUILD deps for ShimmeringMask - -**Files:** -- Modify: `submodules/TelegramUI/Components/ShimmeringMask/BUILD` - -- [ ] **Step 1: Open the BUILD file** - -Read `submodules/TelegramUI/Components/ShimmeringMask/BUILD` to confirm current contents. - -- [ ] **Step 2: Replace deps with the trimmed list** - -Replace the existing `deps` block in `submodules/TelegramUI/Components/ShimmeringMask/BUILD` so the file matches: - -```python -load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") - -swift_library( - name = "ShimmeringMask", - module_name = "ShimmeringMask", - srcs = glob([ - "Sources/**/*.swift", - ]), - copts = [ - "-warnings-as-errors", - ], - deps = [ - "//submodules/ComponentFlow", - "//submodules/Components/HierarchyTrackingLayer", - ], - visibility = [ - "//visibility:public", - ], -) -``` - -The removed deps (`AsyncDisplayKit`, `Display`, `ShimmerEffect`) are not used by the new implementation. The added dep (`Components/HierarchyTrackingLayer`) is needed for the pause/resume-on-hierarchy pattern. - -- [ ] **Step 3: Build to confirm BUILD parses** - -The current stub `ShimmeringMaskView.swift` imports `Display`, `ShimmerEffect`, `AsyncDisplayKit`, and `ComponentFlow`. Trimming the BUILD deps without first updating the source would break the build. Skip building until Task 2's source replacement lands. (We'll build after Task 2.) - -- [ ] **Step 4: Stage but don't commit yet** - -```sh -git add submodules/TelegramUI/Components/ShimmeringMask/BUILD -``` - -The commit will happen at the end of Task 2 to keep the BUILD + source change atomic. - ---- - -### Task 2: Replace ShimmeringMaskView stub with full implementation - -**Files:** -- Modify: `submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift` - -- [ ] **Step 1: Verify the stub matches what we expect** - -Read `submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift`. Confirm it contains the stub (a `ShimmeringMaskView` class with `public let contentView: UIView`, `init(frame:)`, and an empty `update(size:transition:)`). If it has diverged, stop and ask for direction; otherwise proceed. - -- [ ] **Step 2: Rewrite the file** - -Replace the entire contents of `submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift` with: - -```swift -import Foundation -import UIKit -import ComponentFlow -import HierarchyTrackingLayer - -public final class ShimmeringMaskView: UIView { - private struct Params: Equatable { - var size: CGSize - var containerWidth: CGFloat - var offsetX: CGFloat - var gradientWidth: CGFloat - } - - public let contentView: UIView - - private let peakAlpha: CGFloat - private let duration: Double - - private let hierarchyTrackingLayer: HierarchyTrackingLayer - private let maskLayer: CAGradientLayer - - private var params: Params? - - public init(peakAlpha: CGFloat, duration: Double) { - self.peakAlpha = peakAlpha - self.duration = duration - - self.contentView = UIView() - - self.hierarchyTrackingLayer = HierarchyTrackingLayer() - - self.maskLayer = CAGradientLayer() - self.maskLayer.startPoint = CGPoint(x: 0.0, y: 0.5) - self.maskLayer.endPoint = CGPoint(x: 1.0, y: 0.5) - self.maskLayer.colors = [ - UIColor(white: 1.0, alpha: 1.0).cgColor, - UIColor(white: 1.0, alpha: peakAlpha).cgColor, - UIColor(white: 1.0, alpha: 1.0).cgColor - ] - self.maskLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5) - - super.init(frame: CGRect()) - - self.addSubview(self.contentView) - self.contentView.layer.mask = self.maskLayer - - self.layer.addSublayer(self.hierarchyTrackingLayer) - self.hierarchyTrackingLayer.didEnterHierarchy = { [weak self] in - guard let self else { - return - } - self.updateAnimations() - } - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func updateAnimations() { - guard let params = self.params else { - return - } - if self.maskLayer.animation(forKey: "shimmer") != nil { - return - } - let travelDelta = params.containerWidth + params.gradientWidth - let animation = self.maskLayer.makeAnimation( - from: 0.0 as NSNumber, - to: travelDelta as NSNumber, - keyPath: "position.x", - timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, - duration: self.duration, - delay: 0.0, - mediaTimingFunction: nil, - removeOnCompletion: true, - additive: true - ) - animation.repeatCount = Float.infinity - self.maskLayer.add(animation, forKey: "shimmer") - } - - public func update( - size: CGSize, - containerWidth: CGFloat, - offsetX: CGFloat, - gradientWidth: CGFloat, - transition: ComponentTransition - ) { - let params = Params( - size: size, - containerWidth: containerWidth, - offsetX: offsetX, - gradientWidth: gradientWidth - ) - if self.params == params { - return - } - self.params = params - - transition.setFrame(view: self.contentView, frame: CGRect(origin: CGPoint(), size: size)) - - let travelDistance = containerWidth + gradientWidth - let maskWidth = size.width + 2.0 * travelDistance - - let dipHalfFraction: CGFloat - if maskWidth > 0.0 { - dipHalfFraction = (gradientWidth * 0.5) / maskWidth - } else { - dipHalfFraction = 0.0 - } - self.maskLayer.locations = [ - (0.5 - dipHalfFraction) as NSNumber, - 0.5 as NSNumber, - (0.5 + dipHalfFraction) as NSNumber - ] - - let maskBounds = CGRect(origin: CGPoint(), size: CGSize(width: maskWidth, height: size.height)) - let staticPositionX = -gradientWidth * 0.5 - offsetX - let maskPosition = CGPoint(x: staticPositionX, y: size.height * 0.5) - - transition.setBounds(layer: self.maskLayer, bounds: maskBounds) - transition.setPosition(layer: self.maskLayer, position: maskPosition) - - self.maskLayer.removeAnimation(forKey: "shimmer") - self.updateAnimations() - } -} -``` - -Notes on the code (do not alter): -- `super.init(frame: CGRect())` is intentional — callers always size via `update(...)`; init takes appearance constants only. -- `maskLayer.anchorPoint = (0.5, 0.5)` and the mask is parented in `contentView.layer`'s coord system (because `contentView.layer.mask = maskLayer`). So `maskLayer.position.x = -gradientWidth/2 - offsetX` puts the dip just off-left of the container in `contentView` coords. -- `dipHalfFraction` is `(gradientWidth/2) / maskWidth` because `CAGradientLayer.locations` are normalized to the *layer's* bounds. With locations `[0.5 − Δ, 0.5, 0.5 + Δ]` the dip occupies `gradientWidth` pixels centered in `maskWidth`. -- The `if maskWidth > 0.0` guard avoids divide-by-zero on a zero-sized first call. -- Animation re-arm is unconditional whenever params change (intentionally — tradeoff documented in the spec). -- `makeAnimation(...)` is a `CALayer` extension provided by `Display`/`ComponentFlow` (it's used identically in the reference files). It *is* available without importing `Display` because the helper is on `ComponentFlow`'s import surface that we already pull in. If the build complains that `makeAnimation` is unresolved, add `import Display` and `"//submodules/Display"` to the BUILD deps — but check first. - -- [ ] **Step 3: Verify the `makeAnimation` symbol resolves** - -Before a full build, run a quick grep to be sure of the source of `makeAnimation`: - -```sh -grep -rn "func makeAnimation" submodules/Display/ submodules/ComponentFlow/ submodules/Components/HierarchyTrackingLayer/ 2>/dev/null -``` - -Expected: at least one hit. If the only hit is in `submodules/Display/`, then `import Display` and the `Display` BUILD dep ARE required. Update Task 2's source file (add `import Display` after `import UIKit`) and Task 1's BUILD (add `"//submodules/Display",` to deps) before building. If hits exist in `ComponentFlow` or `HierarchyTrackingLayer` we're fine without `Display`. - -- [ ] **Step 4: Build the affected target** - -Run the full Bazel build (see "Build invocation" above). Bazel will compile the `ShimmeringMask` library as part of building `Telegram/Telegram`. - -Expected: build succeeds. Watch for `-warnings-as-errors` failures in `ShimmeringMaskView.swift` (e.g. unused-let, always-false casts) — fix them inline before re-running. - -- [ ] **Step 5: Commit Task 1 + Task 2 together** - -```sh -git add submodules/TelegramUI/Components/ShimmeringMask/BUILD \ - submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift -git commit -m "$(cat <<'EOF' -ShimmeringMask: implement ShimmeringMaskView reveal-mask shimmer - -CAGradientLayer mask with horizontal [white@1.0, white@peakAlpha, -white@1.0] gradient; oversized so alpha=1.0 edges always cover -contentView. Animates position.x (additive, infinite, easeOut) so the -dip travels across containerWidth. HierarchyTrackingLayer pauses / -resumes the animation on hierarchy entry. API mirrors -VideoChatVideoLoadingEffectView. - -Co-Authored-By: Claude Opus 4.7 (1M context) -EOF -)" -``` - ---- - -### Task 3: Wrap streamingStatusTextNode in ShimmeringMaskView - -**Files:** -- Modify: `submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift` - -This task touches three regions of the file. The line numbers below are accurate as of the time the spec was written; if the file has shifted by a handful of lines, locate by surrounding text (the code excerpts shown are the unique anchors). - -- [ ] **Step 1: Add a sibling field for the shimmer view** - -Find the existing field declaration: - -```swift - private var streamingStatusTextNode: InteractiveTextNodeWithEntities? -``` - -(approximately line 90). Insert a new line directly after it: - -```swift - private var streamingStatusTextNode: InteractiveTextNodeWithEntities? - private var streamingStatusShimmerView: ShimmeringMaskView? -``` - -- [ ] **Step 2: Wrap the streaming-text branch — locate** - -Find this block (approximately lines 959-1000): - -```swift - if let streamingTextFrame, let streamingTextLayoutAndApply { - var animation = animation - if strongSelf.streamingStatusTextNode == nil { - animation = .None - } - let streamingStatusTextNode = streamingTextLayoutAndApply.apply(InteractiveTextNodeWithEntities.Arguments( - context: item.context, - cache: item.controllerInteraction.presentationContext.animationCache, - renderer: item.controllerInteraction.presentationContext.animationRenderer, - placeholderColor: messageTheme.mediaPlaceholderColor, - attemptSynchronous: synchronousLoads, - textColor: messageTheme.primaryTextColor, - spoilerEffectColor: messageTheme.secondaryTextColor, - applyArguments: InteractiveTextNode.ApplyArguments( - animation: animation, - spoilerTextColor: messageTheme.primaryTextColor, - spoilerEffectColor: messageTheme.secondaryTextColor, - areContentAnimationsEnabled: item.context.sharedContext.energyUsageSettings.loopEmoji, - spoilerExpandRect: nil, - crossfadeContents: { [weak strongSelf] sourceView in - guard let strongSelf, let streamingStatusTextNode = strongSelf.streamingStatusTextNode else { - return - } - if let textNodeContainer = streamingStatusTextNode.textNode.view.superview { - sourceView.frame = CGRect(origin: streamingStatusTextNode.textNode.frame.origin, size: sourceView.bounds.size) - textNodeContainer.addSubview(sourceView) - - sourceView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false, completion: { [weak sourceView] _ in - sourceView?.removeFromSuperview() - }) - streamingStatusTextNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) - } - } - ) - )) - if streamingStatusTextNode !== strongSelf.streamingStatusTextNode { - strongSelf.streamingStatusTextNode?.textNode.removeFromSupernode() - strongSelf.streamingStatusTextNode = streamingStatusTextNode - strongSelf.containerNode.addSubnode(streamingStatusTextNode.textNode) - } - animation.animator.updatePosition(layer: streamingStatusTextNode.textNode.layer, position: streamingTextFrame.center, completion: nil) - animation.animator.updateBounds(layer: streamingStatusTextNode.textNode.layer, bounds: CGRect(origin: CGPoint(), size: streamingTextFrame.size), completion: nil) - } else if let streamingStatusTextNode = strongSelf.streamingStatusTextNode { - strongSelf.streamingStatusTextNode = nil - let streamingStatusTextNodeNode = streamingStatusTextNode.textNode - animation.animator.updateAlpha(layer: streamingStatusTextNodeNode.layer, alpha: 0.0, completion: { [weak streamingStatusTextNodeNode] _ in - streamingStatusTextNodeNode?.removeFromSupernode() - }) - } -``` - -This is the region we will replace. - -- [ ] **Step 3: Wrap the streaming-text branch — replace** - -Replace the entire block from Step 2 with: - -```swift - if let streamingTextFrame, let streamingTextLayoutAndApply { - var animation = animation - if strongSelf.streamingStatusTextNode == nil { - animation = .None - } - let streamingStatusTextNode = streamingTextLayoutAndApply.apply(InteractiveTextNodeWithEntities.Arguments( - context: item.context, - cache: item.controllerInteraction.presentationContext.animationCache, - renderer: item.controllerInteraction.presentationContext.animationRenderer, - placeholderColor: messageTheme.mediaPlaceholderColor, - attemptSynchronous: synchronousLoads, - textColor: messageTheme.primaryTextColor, - spoilerEffectColor: messageTheme.secondaryTextColor, - applyArguments: InteractiveTextNode.ApplyArguments( - animation: animation, - spoilerTextColor: messageTheme.primaryTextColor, - spoilerEffectColor: messageTheme.secondaryTextColor, - areContentAnimationsEnabled: item.context.sharedContext.energyUsageSettings.loopEmoji, - spoilerExpandRect: nil, - crossfadeContents: { [weak strongSelf] sourceView in - guard let strongSelf, let streamingStatusTextNode = strongSelf.streamingStatusTextNode else { - return - } - if let textNodeContainer = streamingStatusTextNode.textNode.view.superview { - sourceView.frame = CGRect(origin: streamingStatusTextNode.textNode.frame.origin, size: sourceView.bounds.size) - textNodeContainer.addSubview(sourceView) - - sourceView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false, completion: { [weak sourceView] _ in - sourceView?.removeFromSuperview() - }) - streamingStatusTextNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) - } - } - ) - )) - - let streamingStatusShimmerView: ShimmeringMaskView - if let current = strongSelf.streamingStatusShimmerView { - streamingStatusShimmerView = current - } else { - streamingStatusShimmerView = ShimmeringMaskView(peakAlpha: 0.3, duration: 1.0) - strongSelf.streamingStatusShimmerView = streamingStatusShimmerView - strongSelf.containerNode.view.addSubview(streamingStatusShimmerView) - } - - if streamingStatusTextNode !== strongSelf.streamingStatusTextNode { - strongSelf.streamingStatusTextNode?.textNode.view.removeFromSuperview() - strongSelf.streamingStatusTextNode = streamingStatusTextNode - streamingStatusShimmerView.contentView.addSubview(streamingStatusTextNode.textNode.view) - } - animation.animator.updatePosition(layer: streamingStatusShimmerView.layer, position: streamingTextFrame.center, completion: nil) - animation.animator.updateBounds(layer: streamingStatusShimmerView.layer, bounds: CGRect(origin: CGPoint(), size: streamingTextFrame.size), completion: nil) - animation.animator.updatePosition(layer: streamingStatusTextNode.textNode.layer, position: CGPoint(x: streamingTextFrame.size.width * 0.5, y: streamingTextFrame.size.height * 0.5), completion: nil) - animation.animator.updateBounds(layer: streamingStatusTextNode.textNode.layer, bounds: CGRect(origin: CGPoint(), size: streamingTextFrame.size), completion: nil) - streamingStatusShimmerView.update( - size: streamingTextFrame.size, - containerWidth: streamingTextFrame.size.width, - offsetX: 0.0, - gradientWidth: 200.0, - transition: ComponentTransition(animation.transition) - ) - } else if let streamingStatusTextNode = strongSelf.streamingStatusTextNode { - strongSelf.streamingStatusTextNode = nil - let streamingStatusShimmerView = strongSelf.streamingStatusShimmerView - strongSelf.streamingStatusShimmerView = nil - let streamingStatusTextNodeNode = streamingStatusTextNode.textNode - if let streamingStatusShimmerView { - animation.animator.updateAlpha(layer: streamingStatusShimmerView.layer, alpha: 0.0, completion: { [weak streamingStatusShimmerView] _ in - streamingStatusShimmerView?.removeFromSuperview() - }) - } else { - animation.animator.updateAlpha(layer: streamingStatusTextNodeNode.layer, alpha: 0.0, completion: { [weak streamingStatusTextNodeNode] _ in - streamingStatusTextNodeNode?.removeFromSupernode() - }) - } - } -``` - -What changed: -- Lazy-create `ShimmeringMaskView(peakAlpha: 0.3, duration: 1.0)` and add it to `containerNode.view`. -- When the streaming text node is created/replaced, add `streamingStatusTextNode.textNode.view` to `streamingStatusShimmerView.contentView` (UIView hierarchy) **instead of** `containerNode.addSubnode(streamingStatusTextNode.textNode)`. Mixing `view`/`Subview` and `Subnode`/`Supernode` is fine here: ASDisplayNode's `view` is a real UIView, and adding it via `addSubview` from another UIView reparents it. -- Animate the **shimmer view's** layer to `streamingTextFrame.center`/size — this is the position where the streaming-text strip lives in the bubble's container. -- Animate the inner textNode's layer to the shimmer view's local bounds (`origin = .zero`, same size). Without this, after we reparent the textNode under contentView, the textNode keeps its old `containerNode`-relative frame and ends up offset by `streamingTextFrame.origin`. We're explicitly placing it at `(0, 0, streamingTextFrame.size)` inside `contentView`. -- Call `streamingStatusShimmerView.update(...)` with `containerWidth = streamingTextFrame.size.width` and `offsetX = 0.0` (wave scoped to the streaming-text strip itself; broadenable later). -- The teardown branch animates alpha on the shimmer view (with the textNode inside it). When the shimmer view exists, we use it as the alpha-animation target and do `removeFromSuperview` in the completion; the textNode rides along because it's a subview of `contentView`. We keep a fallback `else` branch animating the textNode directly in case some path produces a streamingStatusTextNode without a shimmer view (defensive — should be unreachable today, but it's a one-line cost and matches the previous behavior exactly). -- The replacement step uses `view.removeFromSuperview()` (not `removeFromSupernode()`) because the inner textNode is now hosted inside `streamingStatusShimmerView.contentView` (a plain UIView) via `addSubview`. ASDisplayKit's `addSubview`/`removeFromSupernode` paths don't sync; using the UIView pair ensures replacements actually unhook the previous textNode's view from the shimmer view. - -Notes on the `transition: ComponentTransition(animation.transition)` — the existing call sites in this file use `animation.animator.update*` (where `animator` is a `Display`-flavored animator) but our `ShimmeringMaskView.update` takes a `ComponentFlow.ComponentTransition`. The `animation` value flowing through is a `ListViewItemUpdateAnimation`; it exposes `.transition` as a `ContainedViewLayoutTransition`. `ComponentTransition` has a public initializer accepting `ContainedViewLayoutTransition`. **Verify this initializer exists** before building (see Step 4); if not, fall back to `ComponentTransition.immediate` (the only consequence is that the mask layer's bounds/position aren't animated to their new values, which is rare and benign). - -- [ ] **Step 4: Verify the ComponentTransition initializer exists** - -```sh -grep -rn "init.*ContainedViewLayoutTransition" submodules/ComponentFlow/Source/ 2>/dev/null -grep -rn "extension ComponentTransition" submodules/ComponentFlow/Source/ 2>/dev/null -``` - -Expected: at least one hit indicating an initializer or static helper that converts a `ContainedViewLayoutTransition` to a `ComponentTransition`. If you find one named differently (e.g. `ComponentTransition(transition:)` or `ComponentTransition.init(legacyAnimation:)`), use that exact name in the call from Step 3. - -If neither exists, replace the `transition:` argument in Step 3's call with `.immediate`: - -```swift - streamingStatusShimmerView.update( - size: streamingTextFrame.size, - containerWidth: streamingTextFrame.size.width, - offsetX: 0.0, - gradientWidth: 200.0, - transition: .immediate - ) -``` - -- [ ] **Step 5: Build** - -Run the full Bazel build (see "Build invocation" above). Expected: build succeeds. - -If you get `-warnings-as-errors` failures specifically about an unused `streamingStatusShimmerView` variable in the teardown branch, that means a compiler-flagged path: re-check the diff against the Step 3 source. - -- [ ] **Step 6: Commit** - -```sh -git add submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift -git commit -m "$(cat <<'EOF' -ChatMessageTextBubbleContentNode: wrap streaming-status text in ShimmeringMaskView - -Hosts streamingStatusTextNode inside a ShimmeringMaskView so the -streaming line gets a "thinking"-style running shimmer (alpha-mask wave -with peakAlpha=0.3, duration=1.0, gradientWidth=200). Layout/teardown -animations target the shimmer view's layer; the text node lives inside -contentView at the wrapper's local bounds. - -Co-Authored-By: Claude Opus 4.7 (1M context) -EOF -)" -``` - ---- - -### Task 4: Manual verification - -**Files:** none (build + run only) - -- [ ] **Step 1: Confirm clean build state** - -```sh -git status --short -``` - -Expected: empty (or only the unrelated `m`/`M` entries that were present before this work began — see `gitStatus` in the conversation context). - -- [ ] **Step 2: Build for the simulator** - -Run the full Bazel build (see "Build invocation" above). Expected: build succeeds with no warnings-as-errors. - -- [ ] **Step 3: Manual run** - -Launch the built app in the simulator. Open a chat with an in-progress AI streaming message (or trigger a streaming-status placeholder if one exists in the test environment). Confirm: - -- The streaming-status line shows a smooth horizontal wave that runs continuously while streaming. -- Outside the wave, the text is fully readable (alpha=1.0). -- At the wave's center, the text dims to ~30% (the `peakAlpha = 0.3` value). -- When the streaming status disappears (message finishes streaming), the shimmer view fades out cleanly with the text inside it. -- Scrolling the streaming message off-screen pauses the animation; scrolling it back on resumes (`HierarchyTrackingLayer` doing its job). - -If the wave is too fast / too slow / too subtle, adjust the constants `peakAlpha`, `duration`, `gradientWidth` at the call site in `ChatMessageTextBubbleContentNode.swift` (Task 3, Step 3, where `ShimmeringMaskView(peakAlpha: 0.3, duration: 1.0)` and `gradientWidth: 200.0` appear) and rebuild. Don't commit tuning changes as part of this plan — leave them for a follow-up. - -- [ ] **Step 4: No commit (verification only)** - -This task produces no code changes. - ---- - -## Notes for the implementer - -- **`-warnings-as-errors`** is enabled on both modules. Common gotchas: unused locals, always-false `is` checks, always-failing `as?` casts. If a build fails with these, fix them inline rather than adding `// swiftlint:disable` or `_ = unused`. -- **No unit tests, no UI snapshot tests** in this project. The full Bazel build is the only automated gate. Be diligent about the manual verification step. -- **Bazel cache:** the plan assumes `~/telegram-bazel-cache` is reusable across builds. If you're working in a fresh worktree (no shared cache), the first build will take meaningfully longer. -- **`HierarchyTrackingLayer` BUILD path** is `//submodules/Components/HierarchyTrackingLayer` (note the `Components/` prefix — there's no top-level `submodules/HierarchyTrackingLayer/`). -- If `streamingTextLayoutAndApply` ends up being non-nil in fast succession (streaming status flickers), the same `ShimmeringMaskView` instance is reused — `update(...)`'s `params != self.params` short-circuit avoids re-arming the animation when nothing changed. -- The wave's containerWidth is currently scoped to the streaming-text strip itself, not the bubble. If a future change wants the wave to traverse the full bubble width (or sync across multiple bubbles), pass a larger `containerWidth` and a non-zero `offsetX` (the streaming-text strip's `minX` within the chosen container) to `update(...)`. diff --git a/docs/superpowers/specs/2026-05-05-shimmering-mask-view-design.md b/docs/superpowers/specs/2026-05-05-shimmering-mask-view-design.md deleted file mode 100644 index 4ca1ae79d8..0000000000 --- a/docs/superpowers/specs/2026-05-05-shimmering-mask-view-design.md +++ /dev/null @@ -1,152 +0,0 @@ -# ShimmeringMaskView — design - -## Goal - -Build a reusable `ShimmeringMaskView` that applies a moving alpha-mask shimmer to its `contentView`, producing a "ChatGPT thinking"-style running effect. First consumer: the `streamingStatusTextNode` in `ChatMessageTextBubbleContentNode`. - -## Visual model - -Reveal mask with constant baseline: - -- Outside the wave, mask alpha = `1.0` (content fully visible). -- A horizontal wave travels across the content; at the wave's center, mask alpha dips to `peakAlpha` (a value < 1.0). -- The wave repeats infinitely while in the view hierarchy. - -Conceptually: the wave is a *low-opacity dimming dip* sliding through; rest state is fully visible. - -## Module location and BUILD - -- File: `submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift` -- BUILD: `submodules/TelegramUI/Components/ShimmeringMask/BUILD` - -Final deps: - -```python -deps = [ - "//submodules/ComponentFlow", - "//submodules/Components/HierarchyTrackingLayer", -], -``` - -The currently-listed `AsyncDisplayKit`, `Display`, and `ShimmerEffect` deps are removed — none of their types are used. (Re-add `//submodules/Display` if a Display utility is needed during implementation.) - -## Public API - -```swift -public final class ShimmeringMaskView: UIView { - public let contentView: UIView - - public init(peakAlpha: CGFloat, duration: Double) - - public func update( - size: CGSize, - containerWidth: CGFloat, - offsetX: CGFloat, - gradientWidth: CGFloat, - transition: ComponentTransition - ) -} -``` - -Init params (chosen once): -- `peakAlpha` — alpha at the center of the wave (e.g. `0.3`). -- `duration` — seconds per cycle. - -Update params (per layout): -- `size` — `contentView.frame.size`. -- `containerWidth`, `offsetX` — coordinate space the wave traverses, allowing the wave to extend past `contentView`'s own bounds (matches the `VideoChatVideoLoadingEffectView` API). For an isolated use, pass `containerWidth = size.width, offsetX = 0`. -- `gradientWidth` — width of the dip in container coordinates. - -## Internal architecture - -``` -ShimmeringMaskView (UIView) -├── contentView (UIView, public) -│ └── layer.mask = maskLayer -└── HierarchyTrackingLayer (pause/resume on hierarchy entry) - -maskLayer: CAGradientLayer - startPoint = (0, 0.5), endPoint = (1, 0.5) // horizontal - colors = [white@1.0, white@peakAlpha, white@1.0] - locations = positions placing a gradientWidth-wide dip - centered in maskLayer.bounds - bounds.width = size.width + 2 × travelDistance - where travelDistance = containerWidth + gradientWidth - (guarantees alpha=1.0 edges always cover contentView) - bounds.height = size.height - anchorPoint = (0.5, 0.5) - static position.x = −gradientWidth/2 − offsetX - (dip parked just off-left of the container in contentView coords; - contentView's layer is the mask's reference coord system, so - position.x is in contentView coords directly) - - position.x animation (CABasicAnimation, additive, infinite): - keyPath = "position.x" - from = 0 - to = containerWidth + gradientWidth - duration = duration - timingFunction = .easeOut - repeatCount = .infinity - isRemovedOnCompletion = true (safety net; in practice never completes) -``` - -### Why a single oversized `CAGradientLayer` - -- For an additive overlay (the shape of `AnimatedGradientView` inside `VideoChatVideoLoadingEffectView`), the unit-scale + container-scale + offset-scale hierarchy lets you keep animation params constant while changing `containerWidth/gradientWidth` via static transforms. For a *mask*, the layer must always cover `contentView.bounds` at every animation phase — which forces oversize anyway. So the hierarchy stops paying for itself; we'd carry three intermediate layers and still need to oversize. -- Trade-off: when `containerWidth` or `gradientWidth` change, the animation is re-armed with new `to` values. For the streaming-status use case, layout changes are rare (only when the bubble re-lays out), and the re-arm is cheap. - -### Why animate `position.x` (not `locations`) - -Per direction in the design discussion: `position.x` is GPU-accelerated as a layer translation, matches the proven pattern in `AnimatedGradientView` / `LoadingEffectView`, and produces stable jank-free motion. `additive: true` lets the layer's static `position.x` carry the per-layout offset (offsetX baked in) while the animation contributes the fixed `[0, containerWidth + gradientWidth]` translation delta. - -## Lifecycle - -- `HierarchyTrackingLayer` is added as a sublayer of `self.layer`. Its `didEnterHierarchy` callback calls `updateAnimations()`. -- `updateAnimations()`: if `maskLayer.animation(forKey: "shimmer") == nil`, build the `CABasicAnimation` and add it to `maskLayer`. This restarts the animation when re-entering the hierarchy. -- `update(...)`: - 1. Build `Params(size, containerWidth, offsetX, gradientWidth)`. - 2. If `params == self.params`, return. - 3. Otherwise store new params; apply layout via the supplied `transition` (frame of `contentView`, bounds + position of `maskLayer`). - 4. Re-arm the animation (remove existing key + add a new `CABasicAnimation` reflecting the updated `to` value). -- Re-arm is unconditional when params change. Visible jump is acceptable since layout changes for the streaming-status use case are rare. - -## Integration: `ChatMessageTextBubbleContentNode` - -Location: `submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift` (currently around lines 90 and 961-1006). - -1. Add a field alongside `streamingStatusTextNode`: - ```swift - private var streamingStatusShimmerView: ShimmeringMaskView? - ``` -2. In the `if let streamingTextFrame, let streamingTextLayoutAndApply { ... }` branch (~line 959): - - Lazily create `ShimmeringMaskView(peakAlpha: 0.3, duration: 1.0)`; add to `containerNode.view`. - - Move the streaming text node's view into the shimmer view's `contentView` (instead of adding it directly to `containerNode`). - - Drive shimmer view position/size with `animation.animator` (currently used directly on `streamingStatusTextNode.textNode.layer`): - - `animation.animator.updatePosition(layer: shimmerView.layer, position: streamingTextFrame.center, ...)`. - - `animation.animator.updateBounds(layer: shimmerView.layer, bounds: CGRect(origin: .zero, size: streamingTextFrame.size), ...)`. - - The textNode inside `contentView` is laid out at `(0, 0, streamingTextFrame.size)`. - - Call `shimmerView.update(size: streamingTextFrame.size, containerWidth: streamingTextFrame.width, offsetX: 0, gradientWidth: 200, transition: ComponentTransition(animation))`. -3. In the "tear-down" branch (~line 1001) where `streamingStatusTextNode` is being dropped: - - Animate alpha to 0 on the shimmer view (not the textNode), and remove on completion. The textNode is inside the shimmer view, so removing the shimmer view removes both. -4. The crossfade flow at lines 982-989 continues to work — the textNode's superview is now `shimmerView.contentView` instead of `containerNode`; `sourceView` still gets added to `textNodeContainer` (= `shimmerView.contentView`) and crossfaded in place. - -### Constants used at the call site - -| Constant | Value | Notes | -|----------------|------:|-------| -| `peakAlpha` | `0.3` | Wave dip floor — comfortable contrast against fully visible rest state. | -| `duration` | `1.0` | Matches `LoadingEffectView` / `VideoChatVideoLoadingEffectView` cadence. | -| `gradientWidth`| `200` | Matches the gradient width used elsewhere in the family. | -| `containerWidth` | `streamingTextFrame.width` | Wave scoped to the streaming text strip; broadenable to bubble width if cross-element synchronization is later required. | -| `offsetX` | `0` | Streaming text strip is the container in this scoping. | - -## Out of scope - -- Synchronizing the wave across multiple separate views — the API supports it via `containerWidth + offsetX`, but no consumer needs it today. -- Border-shimmer companion (analogous to `LoadingEffectView.borderGradientView`) — not required for streaming-status text. -- Color tinting the wave — only alpha is modulated; `contentView` keeps its existing colors. - -## Verification - -- Build: `python3 build-system/Make/Make.py --overrideXcodeVersion --cacheDir ~/telegram-bazel-cache build --configurationPath build-system/appstore-configuration.json --gitCodesigningRepository git@gitlab.com:peter-iakovlev/fastlanematch.git --gitCodesigningType development --gitCodesigningUseCurrent --buildNumber=1 --configuration=debug_sim_arm64` (with `source ~/.zshrc 2>/dev/null;` prefix to pick up `TELEGRAM_CODESIGNING_GIT_PASSWORD`). -- Manual: open a chat with a streaming AI message and observe the shimmer effect on the streaming-status line. Confirm the wave runs continuously, the text remains fully readable except when the dip passes, and the effect tears down cleanly when the streaming status disappears. diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index 9c6b20390a..435072a929 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -349,25 +349,29 @@ public final class ContextControllerTakeViewInfo { case node(ContextExtractedContentContainingNode) case view(ContextExtractedContentContainingView) } - + public let containingItem: ContainingItem public let contentAreaInScreenSpace: CGRect public let maskView: UIView? - - public init(containingItem: ContainingItem, contentAreaInScreenSpace: CGRect, maskView: UIView? = nil) { + public let sourceTransitionSurface: UIView? + + public init(containingItem: ContainingItem, contentAreaInScreenSpace: CGRect, maskView: UIView? = nil, sourceTransitionSurface: UIView? = nil) { self.containingItem = containingItem self.contentAreaInScreenSpace = contentAreaInScreenSpace self.maskView = maskView + self.sourceTransitionSurface = sourceTransitionSurface } } public final class ContextControllerPutBackViewInfo { public let contentAreaInScreenSpace: CGRect public let maskView: UIView? - - public init(contentAreaInScreenSpace: CGRect, maskView: UIView? = nil) { + public let sourceTransitionSurface: UIView? + + public init(contentAreaInScreenSpace: CGRect, maskView: UIView? = nil, sourceTransitionSurface: UIView? = nil) { self.contentAreaInScreenSpace = contentAreaInScreenSpace self.maskView = maskView + self.sourceTransitionSurface = sourceTransitionSurface } } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift index d6bada6e9b..f0ff8cfa22 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageTextBubbleContentNode/Sources/ChatMessageTextBubbleContentNode.swift @@ -88,7 +88,8 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { private let containerNode: ContainerNode private let textNode: InteractiveTextNodeWithEntities private var streamingStatusTextNode: InteractiveTextNodeWithEntities? - + private var streamingStatusShimmerView: ShimmeringMaskView? + private let textAccessibilityOverlayNode: TextAccessibilityOverlayNode public var statusNode: ChatMessageDateAndStatusNode? private var linkHighlightingNode: LinkHighlightingNode? @@ -979,10 +980,10 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { guard let strongSelf, let streamingStatusTextNode = strongSelf.streamingStatusTextNode else { return } - if let textNodeContainer = streamingStatusTextNode.textNode.view.superview { + if let shimmerView = strongSelf.streamingStatusShimmerView { sourceView.frame = CGRect(origin: streamingStatusTextNode.textNode.frame.origin, size: sourceView.bounds.size) - textNodeContainer.addSubview(sourceView) - + shimmerView.addSubview(sourceView) + sourceView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false, completion: { [weak sourceView] _ in sourceView?.removeFromSuperview() }) @@ -991,18 +992,37 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } ) )) - if streamingStatusTextNode !== strongSelf.streamingStatusTextNode { - strongSelf.streamingStatusTextNode?.textNode.removeFromSupernode() - strongSelf.streamingStatusTextNode = streamingStatusTextNode - strongSelf.containerNode.addSubnode(streamingStatusTextNode.textNode) + + let streamingStatusShimmerView: ShimmeringMaskView + if let current = strongSelf.streamingStatusShimmerView { + streamingStatusShimmerView = current + } else { + streamingStatusShimmerView = ShimmeringMaskView(peakAlpha: 0.3, duration: 1.0) + strongSelf.streamingStatusShimmerView = streamingStatusShimmerView + strongSelf.containerNode.view.addSubview(streamingStatusShimmerView) } - animation.animator.updatePosition(layer: streamingStatusTextNode.textNode.layer, position: streamingTextFrame.center, completion: nil) + + if streamingStatusTextNode !== strongSelf.streamingStatusTextNode { + strongSelf.streamingStatusTextNode?.textNode.view.removeFromSuperview() + strongSelf.streamingStatusTextNode = streamingStatusTextNode + streamingStatusShimmerView.contentView.addSubview(streamingStatusTextNode.textNode.view) + } + animation.animator.updatePosition(layer: streamingStatusShimmerView.layer, position: streamingTextFrame.center, completion: nil) + animation.animator.updateBounds(layer: streamingStatusShimmerView.layer, bounds: CGRect(origin: CGPoint(), size: streamingTextFrame.size), completion: nil) + animation.animator.updatePosition(layer: streamingStatusTextNode.textNode.layer, position: CGPoint(x: streamingTextFrame.size.width * 0.5, y: streamingTextFrame.size.height * 0.5), completion: nil) animation.animator.updateBounds(layer: streamingStatusTextNode.textNode.layer, bounds: CGRect(origin: CGPoint(), size: streamingTextFrame.size), completion: nil) - } else if let streamingStatusTextNode = strongSelf.streamingStatusTextNode { + streamingStatusShimmerView.update( + size: streamingTextFrame.size, + containerWidth: streamingTextFrame.size.width, + offsetX: 0.0, + gradientWidth: 200.0, + transition: .immediate + ) + } else if let streamingStatusShimmerView = strongSelf.streamingStatusShimmerView { strongSelf.streamingStatusTextNode = nil - let streamingStatusTextNodeNode = streamingStatusTextNode.textNode - animation.animator.updateAlpha(layer: streamingStatusTextNodeNode.layer, alpha: 0.0, completion: { [weak streamingStatusTextNodeNode] _ in - streamingStatusTextNodeNode?.removeFromSupernode() + strongSelf.streamingStatusShimmerView = nil + animation.animator.updateAlpha(layer: streamingStatusShimmerView.layer, alpha: 0.0, completion: { [weak streamingStatusShimmerView] _ in + streamingStatusShimmerView?.removeFromSuperview() }) } diff --git a/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift b/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift index d65a39fad8..0f656f4597 100644 --- a/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift +++ b/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextControllerExtractedPresentationNode.swift @@ -123,6 +123,128 @@ private extension ContextControllerTakeViewInfo.ContainingItem { } } +private final class PortalTransitionStaging { + enum SettleDestination { + case offsetContainer(ASDisplayNode) + case original + } + + weak var surface: UIView? + var wrapper: PortalSourceView? + var clone: PortalView? + var containingItem: ContextControllerTakeViewInfo.ContainingItem? + + /// Reparents the source's contentNode/contentView into a freshly-created + /// `PortalSourceView` inside `surface`, attaches a `PortalView(matchPosition: true)` + /// clone to `overlayHost`, sizes the wrapper so contentNode appears at + /// `targetScreenRect` in window coords, and returns the wrapper's layer. + /// + /// Returns nil if `PortalView(matchPosition:)` cannot be instantiated. In that + /// case staging is left empty and the caller takes the clipping fallback path. + func enter( + for containingItem: ContextControllerTakeViewInfo.ContainingItem, + in surface: UIView, + overlayHost: UIView, + targetScreenRect: CGRect + ) -> CALayer? { + guard let clone = PortalView(matchPosition: true) else { + return nil + } + + let wrapper = PortalSourceView() + + // Place wrapper so that the bubble (= containingItem.contentRect, in + // containingItem.view coords) lands at `targetScreenRect` on screen. + // + // After reparenting contentNode/contentView into wrapper (preserving its + // frame value), the bubble's rect in wrapper-local coords numerically + // equals containingItem.contentRect (since the bubble was at + // contentNode.frame.origin + bubbleOffsetInContentNode == contentRect.origin + // in the original parent). So: + // bubble.screen.origin = wrapper.screen.origin + contentRect.origin + // and we want bubble.screen.origin == targetScreenRect.origin, hence: + // wrapper.screen.origin = targetScreenRect.origin - contentRect.origin + // + // Hidden assumption: contentNode.frame.origin == (0, 0) within containingNode. + // Holds for every current ContextExtractedContentContainingNode adopter; if a + // future adopter offsets contentNode within its containing parent, the bubble + // will be mispositioned in the portal target by that delta. + let bubbleOffsetInContainer = containingItem.contentRect.origin + let wrapperOriginInWindow = CGPoint( + x: targetScreenRect.origin.x - bubbleOffsetInContainer.x, + y: targetScreenRect.origin.y - bubbleOffsetInContainer.y + ) + let wrapperFrameInWindow = CGRect(origin: wrapperOriginInWindow, size: containingItem.view.bounds.size) + wrapper.frame = surface.convert(wrapperFrameInWindow, from: nil) + surface.addSubview(wrapper) + + switch containingItem { + case let .node(containingNode): + wrapper.addSubview(containingNode.contentNode.view) + case let .view(containingView): + wrapper.addSubview(containingView.contentView) + } + + wrapper.addPortal(view: clone) + overlayHost.addSubview(clone.view) + + self.surface = surface + self.wrapper = wrapper + self.clone = clone + self.containingItem = containingItem + + return wrapper.layer + } + + /// Tears down staging. Reparents contentNode into the requested destination, + /// removes clone from its overlay host, removes wrapper from surface. + /// All operations are explicit; we rely on Telegram's manual-animation policy + /// (no implicit CALayer actions) — no CATransaction wrapping needed. + /// + /// `presentationScale` re-application is intentionally not handled here: the + /// portal path is gated on `contentNode.presentationScale == 1.0` in CCEPN's + /// animateIn/animateOut wiring (Tasks 3 and 4), so the scale compensation that + /// the design spec described at settle time is always identity in practice. + func settle(into destination: SettleDestination) { + guard let wrapper = self.wrapper, let containingItem = self.containingItem else { + return + } + + switch destination { + case let .offsetContainer(offsetContainerNode): + switch containingItem { + case let .node(containingNode): + offsetContainerNode.addSubnode(containingNode.contentNode) + case let .view(containingView): + offsetContainerNode.view.addSubview(containingView.contentView) + } + case .original: + // Reparent to the source's containing node/view (where ContextExtracted- + // ContentContainingNode/View added contentNode at init). Capturing + // contentNode.supernode at staging-enter time was overengineered: during + // animateOut staging that's offsetContainerNode (CCEPN's transient host), + // which gets torn down with CCEPN — leaving the bubble parentless. + switch containingItem { + case let .node(containingNode): + containingNode.addSubnode(containingNode.contentNode) + case let .view(containingView): + containingView.addSubview(containingView.contentView) + } + } + + if let clone = self.clone { + wrapper.removePortal(view: clone) + clone.view.removeFromSuperview() + } + wrapper.removeFromSuperview() + + self.surface = nil + self.wrapper = nil + self.clone = nil + self.containingItem = nil + } +} + final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextControllerPresentationNode, ASScrollViewDelegate { enum ContentSource { case location(ContextLocationContentSource) @@ -139,6 +261,8 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo var storedGlobalFrame: CGRect? var storedGlobalBoundsFrame: CGRect? var presentationScale: CGFloat = 1.0 + var portalStaging: PortalTransitionStaging? + weak var sourceTransitionSurface: UIView? init(containingItem: ContextControllerTakeViewInfo.ContainingItem) { self.offsetContainerNode = ASDisplayNode() @@ -634,6 +758,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo } let contentNodeValue = ItemContentNode(containingItem: takeInfo.containingItem) contentNodeValue.animateClippingFromContentAreaInScreenSpace = takeInfo.contentAreaInScreenSpace + contentNodeValue.sourceTransitionSurface = takeInfo.sourceTransitionSurface // Mirror any ancestor scale on the source (e.g. a sheet's container transform) onto the offset // container so the extracted contents render at the same visual size as in-place — without this @@ -1204,6 +1329,18 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo } } contentTransition.updateFrame(node: contentNode, frame: contentFrame, beginWithCurrentState: true) + + // Keep the staging wrapper's frame in sync with ItemContentNode's frame so + // chat-side relayouts that fire mid-animation (e.g. via layoutUpdated → + // requestUpdate after isExtractedToContextPreview = true) shift the portal + // source the same way ItemContentNode shifts. The additive position springs + // on wrapper.layer ("position.x" / "position.y") and this layout-pass + // "position" animation compose: visual = (interpolated layout) + (additive offset). + if let staging = contentNode.portalStaging, let wrapper = staging.wrapper, let surface = staging.surface { + let wrapperFrameInWindow = self.scrollNode.view.convert(contentFrame, to: nil) + let wrapperFrameInSurface = surface.convert(wrapperFrameInWindow, from: nil) + contentTransition.updateFrame(view: wrapper, frame: wrapperFrameInSurface, beginWithCurrentState: true) + } } if let contentNode = controllerContentNode { //TODO: @@ -1267,9 +1404,13 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo let actionsSize = self.actionsContainerNode.bounds.size if let contentNode = itemContentNode { - contentNode.takeContainingNode() + if contentNode.sourceTransitionSurface != nil && contentNode.presentationScale == 1.0 { + // Portal path: defer reparenting to the staging.enter call below. + } else { + contentNode.takeContainingNode() + } } - + let duration: Double = 0.42 let springDamping: CGFloat = 104.0 @@ -1278,11 +1419,70 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo var animationInContentYDistance: CGFloat let currentContentScreenFrame: CGRect if let contentNode = itemContentNode { - if let animateClippingFromContentAreaInScreenSpace = contentNode.animateClippingFromContentAreaInScreenSpace { + let portalAnimationLayer: CALayer? + if let surface = contentNode.sourceTransitionSurface, contentNode.presentationScale == 1.0 { + let staging = PortalTransitionStaging() + // Use ItemContentNode.frame (already includes contentVerticalOffset and + // additionalVisibleOffsetY from the layout pass) plus + // containingItem.contentRect.origin to derive the bubble's actual rest + // window rect. Using bare `contentRect` skips those offsets — when reactions + // are visible (additionalVisibleOffsetY = reactionContextNode.visibleExtensionDistance) + // the wrapper would sit ~10pt above the bubble's true rest, visibly offsetting + // the portal mirror until staging.settle reparents into offsetContainerNode. + // Springs are additive: `from: -distance` at t=0 pulls the wrapper back to + // the chat-side source position; `to: 0` lands at rest. + let bubbleRestRectInScrollNode = CGRect( + x: contentNode.frame.minX + contentNode.containingItem.contentRect.minX, + y: contentNode.frame.minY + contentNode.containingItem.contentRect.minY, + width: contentNode.containingItem.contentRect.width, + height: contentNode.containingItem.contentRect.height + ) + let currentContentLocalFrameInWindow = self.scrollNode.view.convert(bubbleRestRectInScrollNode, to: nil) + if let layer = staging.enter( + for: contentNode.containingItem, + in: surface, + overlayHost: contentNode.offsetContainerNode.view, + targetScreenRect: currentContentLocalFrameInWindow + ) { + contentNode.portalStaging = staging + portalAnimationLayer = layer + + // Mid-animation crossfade: source (chat-tree wrapper, behind chrome) + // is visible at the chat-bubble slot; final (overlay clone, above + // chrome) is visible at the menu position. Final fade-in begins + // `crossfadeOverlap` seconds before source fade-out, so the final + // is already on screen before the source starts dropping out — no + // single-frame seam at the handoff. Each fade runs for a fixed 0.1s. + if let wrapper = staging.wrapper, let clone = staging.clone { + let sourceFadeDelay = 0.12 * duration + let crossfadeOverlap: Double = 0.3 + let crossfadeDuration: Double = 0.1 + let finalFadeDelay = max(0.0, sourceFadeDelay - crossfadeOverlap) + + // Final = clone (visible at end), fades in. + clone.view.alpha = 1.0 + clone.view.layer.allowsGroupOpacity = true + clone.view.layer.animateAlpha(from: 0.01, to: 1.0, duration: crossfadeDuration, delay: finalFadeDelay) + + // Source = wrapper (visible at start), fades out. + wrapper.alpha = 0.0 + wrapper.layer.allowsGroupOpacity = true + wrapper.layer.animateAlpha(from: 1.0, to: 0.0, duration: crossfadeDuration, delay: sourceFadeDelay) + } + } else { + // Staging refused (PortalView nil); fall back to clipping by reparenting now. + contentNode.takeContainingNode() + portalAnimationLayer = nil + } + } else { + portalAnimationLayer = nil + } + + if portalAnimationLayer == nil, let animateClippingFromContentAreaInScreenSpace = contentNode.animateClippingFromContentAreaInScreenSpace { self.clippingNode.layer.animateFrame(from: CGRect(origin: CGPoint(x: 0.0, y: animateClippingFromContentAreaInScreenSpace.minY), size: CGSize(width: layout.size.width, height: animateClippingFromContentAreaInScreenSpace.height)), to: CGRect(origin: CGPoint(), size: layout.size), duration: 0.2) self.clippingNode.layer.animateBoundsOriginYAdditive(from: animateClippingFromContentAreaInScreenSpace.minY, to: 0.0, duration: 0.2) } - + currentContentScreenFrame = convertFrame(contentNode.containingItem.contentRect, from: contentNode.containingItem.view, to: self.view) let currentContentLocalFrame = convertFrame(contentRect, from: self.scrollNode.view, to: self.view) animationInContentYDistance = currentContentLocalFrame.maxY - currentContentScreenFrame.maxY @@ -1298,7 +1498,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo if actionsSize.height.isZero { var initialContentRect = contentRect initialContentRect.origin.y += extracted.initialAppearanceOffset.y - + let fixedContentY = floorToScreenPixels((layout.size.height - contentHeight) / 2.0) animationInContentYDistance = fixedContentY - initialContentRect.minY } else if contentX + contentWidth > layout.size.width / 2.0, actionsSize.height > 0.0 { @@ -1308,9 +1508,11 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo } else { animationInContentXDistance = contentParentGlobalFrameOffsetX } - + + let animateLayer: CALayer = portalAnimationLayer ?? contentNode.layer + if animationInContentXDistance != 0.0 { - contentNode.layer.animateSpring( + animateLayer.animateSpring( from: -animationInContentXDistance as NSNumber, to: 0.0 as NSNumber, keyPath: "position.x", duration: duration, @@ -1320,15 +1522,22 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo additive: true ) } - - contentNode.layer.animateSpring( + + animateLayer.animateSpring( from: -animationInContentYDistance as NSNumber, to: 0.0 as NSNumber, keyPath: "position.y", duration: duration, delay: 0.0, initialVelocity: 0.0, damping: springDamping, - additive: true + additive: true, + completion: { [weak contentNode] _ in + guard let contentNode else { return } + if let staging = contentNode.portalStaging { + staging.settle(into: .offsetContainer(contentNode.offsetContainerNode)) + contentNode.portalStaging = nil + } + } ) if let reactionPreviewView = self.reactionPreviewView { @@ -1504,8 +1713,10 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo } } + var portalAnimationLayer: CALayer? = nil + let currentContentScreenFrame: CGRect - + switch self.source { case let .location(location): if let putBackInfo = location.transitionInfo() { @@ -1527,12 +1738,55 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo } case let .extracted(source): let putBackInfo = source.putBack() - - if let putBackInfo = putBackInfo { + + if let putBackInfo = putBackInfo, + let surface = putBackInfo.sourceTransitionSurface, + let contentNode = itemContentNode, + contentNode.presentationScale == 1.0 + { + let preStagingScreenFrame = convertFrame(contentNode.containingItem.contentRect, from: contentNode.containingItem.view, to: self.view) + let preStagingScreenFrameInWindow = self.view.convert(preStagingScreenFrame, to: nil) + let staging = PortalTransitionStaging() + if let layer = staging.enter( + for: contentNode.containingItem, + in: surface, + overlayHost: contentNode.offsetContainerNode.view, + targetScreenRect: preStagingScreenFrameInWindow + ) { + contentNode.portalStaging = staging + portalAnimationLayer = layer + + // Mid-dismiss crossfade: clone (overlay portal target, above chrome) + // is visible at the menu position; final (chat-tree wrapper, behind + // chrome) is visible once the bubble settles at the chat-bubble + // slot. Late handoff — clone carries the bubble through most of the + // dismiss; final picks up only as the bubble lands. Source fade-out + // is anchored at 80% of the spring duration; final fade-in starts + // `crossfadeOverlap` seconds earlier. Each fade runs for 0.1s. + if let wrapper = staging.wrapper, let clone = staging.clone { + let sourceFadeDelay = 0.5 * duration + let crossfadeOverlap: Double = 0.3 + let crossfadeDuration: Double = 0.12 + let finalFadeDelay = max(0.0, sourceFadeDelay - crossfadeOverlap) + + // Final = wrapper (visible at end), fades in. + wrapper.alpha = 1.0 + wrapper.layer.allowsGroupOpacity = true + wrapper.layer.animateAlpha(from: 0.01, to: 1.0, duration: crossfadeDuration, delay: finalFadeDelay) + + // Source = clone (visible at start), fades out. + clone.view.alpha = 0.0 + clone.view.layer.allowsGroupOpacity = true + clone.view.layer.animateAlpha(from: 1.0, to: 0.0, duration: crossfadeDuration, delay: sourceFadeDelay) + } + } + } + + if portalAnimationLayer == nil, let putBackInfo = putBackInfo { self.clippingNode.layer.animateFrame(from: CGRect(origin: CGPoint(), size: layout.size), to: CGRect(origin: CGPoint(x: 0.0, y: putBackInfo.contentAreaInScreenSpace.minY), size: CGSize(width: layout.size.width, height: putBackInfo.contentAreaInScreenSpace.height)), duration: duration, timingFunction: timingFunction, removeOnCompletion: false) self.clippingNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: putBackInfo.contentAreaInScreenSpace.minY, duration: duration, timingFunction: timingFunction, removeOnCompletion: false) } - + if let contentNode = itemContentNode { currentContentScreenFrame = convertFrame(contentNode.containingItem.contentRect, from: contentNode.containingItem.view, to: self.view) if currentContentScreenFrame.origin.x < 0.0 { @@ -1640,8 +1894,10 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo animationInContentXDistance = -contentParentGlobalFrameOffsetX } + let animateLayer: CALayer = portalAnimationLayer ?? contentNode.offsetContainerNode.layer + if animationInContentXDistance != 0.0 { - contentNode.offsetContainerNode.layer.animate( + animateLayer.animate( from: -animationInContentXDistance as NSNumber, to: 0.0 as NSNumber, keyPath: "position.x", @@ -1651,10 +1907,13 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo additive: true ) } - - contentNode.offsetContainerNode.position = contentNode.offsetContainerNode.position.offsetBy(dx: animationInContentXDistance, dy: -animationInContentYDistance) + + if portalAnimationLayer == nil { + contentNode.offsetContainerNode.position = contentNode.offsetContainerNode.position.offsetBy(dx: animationInContentXDistance, dy: -animationInContentYDistance) + } + let reactionContextNodeIsAnimatingOut = self.reactionContextNodeIsAnimatingOut - contentNode.offsetContainerNode.layer.animate( + animateLayer.animate( from: animationInContentYDistance as NSNumber, to: 0.0 as NSNumber, keyPath: "position.y", @@ -1665,18 +1924,25 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo completion: { [weak self] _ in Queue.mainQueue().after(reactionContextNodeIsAnimatingOut ? 0.2 * UIView.animationDurationFactor() : 0.0, { if let strongSelf = self, let contentNode = strongSelf.itemContentNode { - switch contentNode.containingItem { - case let .node(containingNode): - containingNode.addSubnode(containingNode.contentNode) - case let .view(containingView): - containingView.addSubview(containingView.contentView) + if let staging = contentNode.portalStaging { + staging.settle(into: .original) + contentNode.portalStaging = nil + } else { + switch contentNode.containingItem { + case let .node(containingNode): + containingNode.addSubnode(containingNode.contentNode) + case let .view(containingView): + containingView.addSubview(containingView.contentView) + } } } - - contentNode.containingItem.isExtractedToContextPreview = false - contentNode.containingItem.isExtractedToContextPreviewUpdated?(false) - contentNode.containingItem.onDismiss?() - + + if let strongSelf = self, let contentNode = strongSelf.itemContentNode { + contentNode.containingItem.isExtractedToContextPreview = false + contentNode.containingItem.isExtractedToContextPreviewUpdated?(false) + contentNode.containingItem.onDismiss?() + } + restoreOverlayViews.forEach({ $0() }) completion() }) diff --git a/submodules/TelegramUI/Components/ShimmeringMask/BUILD b/submodules/TelegramUI/Components/ShimmeringMask/BUILD index 5e0e9cd015..8aaeac03c3 100644 --- a/submodules/TelegramUI/Components/ShimmeringMask/BUILD +++ b/submodules/TelegramUI/Components/ShimmeringMask/BUILD @@ -10,10 +10,9 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/AsyncDisplayKit", - "//submodules/Display", - "//submodules/ShimmerEffect", "//submodules/ComponentFlow", + "//submodules/Display", + "//submodules/Components/HierarchyTrackingLayer", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift b/submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift index 65ccc99e76..7da9d6d331 100644 --- a/submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift +++ b/submodules/TelegramUI/Components/ShimmeringMask/Sources/ShimmeringMaskView.swift @@ -1,26 +1,129 @@ import Foundation import UIKit -import AsyncDisplayKit -import Display -import ShimmerEffect import ComponentFlow +import Display +import HierarchyTrackingLayer public final class ShimmeringMaskView: UIView { + private struct Params: Equatable { + var size: CGSize + var containerWidth: CGFloat + var offsetX: CGFloat + var gradientWidth: CGFloat + } + public let contentView: UIView - override public init(frame: CGRect) { + private let peakAlpha: CGFloat + private let duration: Double + + private let hierarchyTrackingLayer: HierarchyTrackingLayer + private let maskLayer: CAGradientLayer + + private var params: Params? + + public init(peakAlpha: CGFloat, duration: Double) { + self.peakAlpha = peakAlpha + self.duration = duration + self.contentView = UIView() - super.init(frame: frame) + self.hierarchyTrackingLayer = HierarchyTrackingLayer() + + self.maskLayer = CAGradientLayer() + self.maskLayer.startPoint = CGPoint(x: 0.0, y: 0.5) + self.maskLayer.endPoint = CGPoint(x: 1.0, y: 0.5) + self.maskLayer.colors = [ + UIColor(white: 1.0, alpha: 1.0).cgColor, + UIColor(white: 1.0, alpha: self.peakAlpha).cgColor, + UIColor(white: 1.0, alpha: 1.0).cgColor + ] + self.maskLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5) + + super.init(frame: CGRect()) self.addSubview(self.contentView) - } - - required public init(coder: NSCoder) { - preconditionFailure() + self.contentView.layer.mask = self.maskLayer + + self.layer.addSublayer(self.hierarchyTrackingLayer) + self.hierarchyTrackingLayer.didEnterHierarchy = { [weak self] in + guard let self else { + return + } + self.updateAnimations() + } } - public func update(size: CGSize, transition: ComponentTransition) { + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + private func updateAnimations() { + guard let params = self.params else { + return + } + if self.maskLayer.animation(forKey: "shimmer") != nil { + return + } + let travelDelta = params.containerWidth + params.gradientWidth + let animation = self.maskLayer.makeAnimation( + from: 0.0 as NSNumber, + to: travelDelta as NSNumber, + keyPath: "position.x", + timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, + duration: self.duration, + delay: 0.0, + mediaTimingFunction: nil, + removeOnCompletion: true, + additive: true + ) + animation.repeatCount = Float.infinity + self.maskLayer.add(animation, forKey: "shimmer") + } + + public func update( + size: CGSize, + containerWidth: CGFloat, + offsetX: CGFloat, + gradientWidth: CGFloat, + transition: ComponentTransition + ) { + let params = Params( + size: size, + containerWidth: containerWidth, + offsetX: offsetX, + gradientWidth: gradientWidth + ) + if self.params == params { + return + } + self.params = params + + transition.setFrame(view: self.contentView, frame: CGRect(origin: CGPoint(), size: size)) + + let travelDistance = containerWidth + gradientWidth + let maskWidth = size.width + 2.0 * travelDistance + + let dipHalfFraction: CGFloat + if maskWidth > 0.0 { + dipHalfFraction = (gradientWidth * 0.5) / maskWidth + } else { + dipHalfFraction = 0.0 + } + self.maskLayer.locations = [ + (0.5 - dipHalfFraction) as NSNumber, + 0.5 as NSNumber, + (0.5 + dipHalfFraction) as NSNumber + ] + + let maskBounds = CGRect(origin: CGPoint(), size: CGSize(width: maskWidth, height: size.height)) + let staticPositionX = -gradientWidth * 0.5 - offsetX + let maskPosition = CGPoint(x: staticPositionX, y: size.height * 0.5) + + transition.setBounds(layer: self.maskLayer, bounds: maskBounds) + transition.setPosition(layer: self.maskLayer, position: maskPosition) + + self.maskLayer.removeAnimation(forKey: "shimmer") + self.updateAnimations() } } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 2ff4273233..d69d16cb1a 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -183,6 +183,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { private var scrollContainerNode: ScrollContainerNode? private var containerNode: ASDisplayNode? private var overlayNavigationBar: ChatOverlayNavigationBar? + private var contextTransitionContainer: UIView? var overlayTitle: String? { didSet { @@ -3528,7 +3529,11 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { } self.derivedLayoutState = ChatControllerNodeDerivedLayoutState(inputContextPanelsFrame: inputContextPanelsFrame, inputContextPanelsOverMainPanelFrame: inputContextPanelsOverMainPanelFrame, inputNodeHeight: inputNodeHeightAndOverflow?.0, inputNodeAdditionalHeight: inputNodeHeightAndOverflow?.1, upperInputPositionBound: inputNodeHeightAndOverflow?.0 != nil ? self.upperInputPositionBound : nil) - + + if let contextTransitionContainer = self.contextTransitionContainer { + contextTransitionContainer.frame = self.view.convert(self.frameForVisibleArea(), to: self.contentContainerNode.contentNode.view) + } + //self.notifyTransitionCompletionListeners(transition: transition) } @@ -4035,6 +4040,37 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { self.textInputPanelNode?.isMediaDeleted = isDeleted } + func ensureContextTransitionContainer() -> UIView? { + // Frames are expressed in self.view coords by frameForVisibleArea(), but the + // container lives inside self.contentContainerNode.contentNode.view (the + // direct parent of historyNodeContainer) so chat-side ancestor clipping + // applies and chrome above contentContainerNode (input panel, nav, etc.) + // renders over it. Convert at the boundary. + // + // In overlay chat mode (self.containerNode != nil) historyNodeContainer is + // reparented out of contentContainerNode (see line ~1299), making the + // `aboveSubview: historyNodeContainer.view` insertion invalid. Return nil + // so callers fall back to CCEPN's clipping path — portal-style transitions + // are not supported in overlay mode. + guard self.containerNode == nil else { return nil } + let parent = self.contentContainerNode.contentNode.view + let frame = self.view.convert(self.frameForVisibleArea(), to: parent) + if let existing = self.contextTransitionContainer { + existing.frame = frame + return existing + } + let container = UIView() + // No clipsToBounds: the source-side wrapper is faded out via alpha during the + // crossfade, so we don't rely on clipping to hide it. Clipping the wrapper + // would also clip the iOS portal mirror (which reflects ancestor clipping), + // producing visibly clipped pixels in the clone at intermediate positions. + container.isUserInteractionEnabled = false + container.frame = frame + parent.insertSubview(container, aboveSubview: self.historyNodeContainer.view) + self.contextTransitionContainer = container + return container + } + func frameForVisibleArea() -> CGRect { var rect = CGRect(origin: CGPoint(x: self.visibleAreaInset.left, y: self.visibleAreaInset.top), size: CGSize(width: self.bounds.size.width - self.visibleAreaInset.left - self.visibleAreaInset.right, height: self.bounds.size.height - self.visibleAreaInset.top - self.visibleAreaInset.bottom)) if let inputContextPanelNode = self.inputContextPanelNode, let topItemFrame = inputContextPanelNode.topItemFrame { diff --git a/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift b/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift index 78d6cb1f9d..560273d070 100644 --- a/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift +++ b/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift @@ -87,7 +87,7 @@ final class ChatMessageContextExtractedContentSource: ContextExtractedContentSou return } if item.content.contains(where: { $0.0.stableId == self.message.stableId }), let contentNode = itemNode.getMessageContextSourceNode(stableId: self.selectAll ? nil : self.message.stableId) { - result = ContextControllerTakeViewInfo(containingItem: .node(contentNode), contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) + result = ContextControllerTakeViewInfo(containingItem: .node(contentNode), contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil), sourceTransitionSurface: chatNode.ensureContextTransitionContainer()) if self.snapshot, let snapshotView = contentNode.contentNode.view.snapshotContentTree(unhide: false, keepPortals: true, keepTransform: true) { contentNode.view.superview?.addSubview(snapshotView) @@ -112,10 +112,10 @@ final class ChatMessageContextExtractedContentSource: ContextExtractedContentSou return } if item.content.contains(where: { $0.0.stableId == self.message.stableId }) { - result = ContextControllerPutBackViewInfo(contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) + result = ContextControllerPutBackViewInfo(contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil), sourceTransitionSurface: chatNode.ensureContextTransitionContainer()) } } - + return result } } @@ -463,17 +463,17 @@ final class ChatMessageReactionContextExtractedContentSource: ContextExtractedCo return } if item.content.contains(where: { $0.0.stableId == self.message.stableId }) { - result = ContextControllerTakeViewInfo(containingItem: .view(self.contentView), contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) + result = ContextControllerTakeViewInfo(containingItem: .view(self.contentView), contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil), sourceTransitionSurface: chatNode.ensureContextTransitionContainer()) } } return result } - + func putBack() -> ContextControllerPutBackViewInfo? { guard let chatNode = self.chatNode else { return nil } - + var result: ContextControllerPutBackViewInfo? chatNode.historyNode.forEachItemNode { itemNode in guard let itemNode = itemNode as? ChatMessageItemView else { @@ -483,7 +483,7 @@ final class ChatMessageReactionContextExtractedContentSource: ContextExtractedCo return } if item.content.contains(where: { $0.0.stableId == self.message.stableId }) { - result = ContextControllerPutBackViewInfo(contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil)) + result = ContextControllerPutBackViewInfo(contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil), sourceTransitionSurface: chatNode.ensureContextTransitionContainer()) } } return result From 3e9b0742d1624ab717ef146f01a163f33c3fba74 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 20:23:06 +0200 Subject: [PATCH 09/14] Fix custom emoji --- .../Sources/InteractiveTextComponent.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/TelegramUI/Components/InteractiveTextComponent/Sources/InteractiveTextComponent.swift b/submodules/TelegramUI/Components/InteractiveTextComponent/Sources/InteractiveTextComponent.swift index af0f34a9a1..75006283d1 100644 --- a/submodules/TelegramUI/Components/InteractiveTextComponent/Sources/InteractiveTextComponent.swift +++ b/submodules/TelegramUI/Components/InteractiveTextComponent/Sources/InteractiveTextComponent.swift @@ -3250,7 +3250,7 @@ final class TextContentItemLayer: SimpleLayer { animation.animator.updateBounds(layer: self.renderNodeContainer, bounds: CGRect(origin: CGPoint(), size: effectiveContentFrame.size), completion: nil) animation.animator.updatePosition(layer: self.renderNode.layer, position: effectiveContentFrame.center, completion: nil) - animation.animator.updateBounds(layer: self.renderNode.layer, bounds: CGRect(origin: CGRect(origin: CGPoint(), size: effectiveContentFrame.size).center, size: effectiveContentFrame.size), completion: nil) + animation.animator.updateBounds(layer: self.renderNode.layer, bounds: CGRect(origin: CGPoint(), size: effectiveContentFrame.size), completion: nil) var staticContentMask = contentMask if let contentMask, self.isAnimating { From 05fe27d0f74356ea6b0e5035f6a078509ad2b144 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 20:28:43 +0200 Subject: [PATCH 10/14] Update tgcalls --- submodules/TgVoipWebrtc/tgcalls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/TgVoipWebrtc/tgcalls b/submodules/TgVoipWebrtc/tgcalls index a6ea40ebf1..2caf643db0 160000 --- a/submodules/TgVoipWebrtc/tgcalls +++ b/submodules/TgVoipWebrtc/tgcalls @@ -1 +1 @@ -Subproject commit a6ea40ebf18233fad5aae29aa3d30561f839a6a8 +Subproject commit 2caf643db02d2a6d862a27a81801271aac94af94 From 71ac72d46317c2d1c4992a39aa6ba826f76006b3 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 20:32:33 +0200 Subject: [PATCH 11/14] Upate webrtc --- third-party/webrtc/webrtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third-party/webrtc/webrtc b/third-party/webrtc/webrtc index d5c77d3588..3817e906cb 160000 --- a/third-party/webrtc/webrtc +++ b/third-party/webrtc/webrtc @@ -1 +1 @@ -Subproject commit d5c77d3588c9353dd48b80430d2ffb41dafef177 +Subproject commit 3817e906cb6c22ec9cc62023b073e1a668d9cb33 From bf01b4c8588fd9217e3817516466b25ad0abdd95 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 5 May 2026 21:01:48 +0200 Subject: [PATCH 12/14] Postbox refactor wave 357: drop orphan //submodules/Postbox BUILD deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sweep 14 BUILD files whose modules no longer have any source file with `import Postbox`. All targets are ChatMessage*BubbleContentNode subclasses plus WallpaperPreviewMedia — modules whose Swift sources stopped importing Postbox in earlier waves but whose BUILD deps were not cleaned up. Pre-flight: for each `BUILD` containing `"//submodules/Postbox"`, verified no source file under `/Sources` matches `^import Postbox$`. 14 modules met the criterion. Build: 15s warm-cache verify, 0 errors. Modules: - ChatMessageActionBubbleContentNode - ChatMessageEventLogPreviousDescriptionContentNode - ChatMessageEventLogPreviousLinkContentNode - ChatMessageEventLogPreviousMessageContentNode - ChatMessageFileBubbleContentNode - ChatMessageGameBubbleContentNode - ChatMessageInvoiceBubbleContentNode - ChatMessageMapBubbleContentNode - ChatMessageMediaBubbleContentNode - ChatMessageProfilePhotoSuggestionContentNode - ChatMessageStoryMentionContentNode - ChatMessageWallpaperBubbleContentNode - ChatMessageWebpageBubbleContentNode - WallpaperPreviewMedia Pre-wave attempt failure note: tried 5 source-side `import Postbox` drops first (StatsMessageItem, StarsAvatarComponent, PeerListItemComponent, WebAppMessagePreviewScreen, OpenChatMessage). All 5 hit hidden bare `Media`/`Message`/`PeerStoryStats`/`areMediaArraysEqual` references that the prior pre-flight regex missed. Reverted source edits; only the risk-free BUILD-dep sweep survives in this commit. Lesson: pre-flight regex MUST include bare Postbox protocols `\bMedia\b`, `\bMessage\b`, `\bPeer\b`, plus the Postbox helper `areMediaArraysEqual` and the `PeerStoryStats` type. The previous identifier-typealias-only regex was insufficient. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Components/Chat/ChatMessageActionBubbleContentNode/BUILD | 1 - .../Chat/ChatMessageEventLogPreviousDescriptionContentNode/BUILD | 1 - .../Chat/ChatMessageEventLogPreviousLinkContentNode/BUILD | 1 - .../Chat/ChatMessageEventLogPreviousMessageContentNode/BUILD | 1 - .../Components/Chat/ChatMessageFileBubbleContentNode/BUILD | 1 - .../Components/Chat/ChatMessageGameBubbleContentNode/BUILD | 1 - .../Components/Chat/ChatMessageInvoiceBubbleContentNode/BUILD | 1 - .../Components/Chat/ChatMessageMapBubbleContentNode/BUILD | 1 - .../Components/Chat/ChatMessageMediaBubbleContentNode/BUILD | 1 - .../Chat/ChatMessageProfilePhotoSuggestionContentNode/BUILD | 1 - .../Components/Chat/ChatMessageStoryMentionContentNode/BUILD | 1 - .../Components/Chat/ChatMessageWallpaperBubbleContentNode/BUILD | 1 - .../Components/Chat/ChatMessageWebpageBubbleContentNode/BUILD | 1 - submodules/TelegramUI/Components/WallpaperPreviewMedia/BUILD | 1 - 14 files changed, 14 deletions(-) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/BUILD index e613fa4d19..c51712b5ac 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageActionBubbleContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/AccountContext", "//submodules/TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousDescriptionContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousDescriptionContentNode/BUILD index 8ac301a11e..8ac49b13e7 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousDescriptionContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousDescriptionContentNode/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/Display", "//submodules/AsyncDisplayKit", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousLinkContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousLinkContentNode/BUILD index db002d4d41..41b7a09aed 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousLinkContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousLinkContentNode/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/Display", "//submodules/AsyncDisplayKit", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousMessageContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousMessageContentNode/BUILD index 0a07f4940e..498ff8a205 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousMessageContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageEventLogPreviousMessageContentNode/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/Display", "//submodules/AsyncDisplayKit", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageFileBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageFileBubbleContentNode/BUILD index a9382eddeb..367ca57c53 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageFileBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageFileBubbleContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/TelegramUIPreferences", "//submodules/ComponentFlow", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageGameBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageGameBubbleContentNode/BUILD index 8f178acb21..cd30ed4ae4 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageGameBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageGameBubbleContentNode/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/Display", "//submodules/AsyncDisplayKit", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInvoiceBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageInvoiceBubbleContentNode/BUILD index 78df073283..2d136e362f 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInvoiceBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInvoiceBubbleContentNode/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/Display", "//submodules/AsyncDisplayKit", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageMapBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageMapBubbleContentNode/BUILD index 319e0fe189..efeef468cf 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageMapBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageMapBubbleContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/LiveLocationTimerNode", "//submodules/PhotoResources", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageMediaBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageMediaBubbleContentNode/BUILD index e5008a8e93..54f5c9efbb 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageMediaBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageMediaBubbleContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/TelegramUIPreferences", "//submodules/TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageProfilePhotoSuggestionContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageProfilePhotoSuggestionContentNode/BUILD index afa1e07539..cdec64f769 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageProfilePhotoSuggestionContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageProfilePhotoSuggestionContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/AccountContext", "//submodules/TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageStoryMentionContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageStoryMentionContentNode/BUILD index 765105167f..75a659705d 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageStoryMentionContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageStoryMentionContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/AccountContext", "//submodules/TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageWallpaperBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageWallpaperBubbleContentNode/BUILD index 98d37bb582..ecd4515127 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageWallpaperBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageWallpaperBubbleContentNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/AsyncDisplayKit", "//submodules/Display", "//submodules/SSignalKit/SwiftSignalKit", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/AccountContext", "//submodules/TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/BUILD index 61ab438674..6770d0c4a0 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/Display", "//submodules/AsyncDisplayKit", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/WallpaperPreviewMedia/BUILD b/submodules/TelegramUI/Components/WallpaperPreviewMedia/BUILD index 2bbdb275af..8d26154271 100644 --- a/submodules/TelegramUI/Components/WallpaperPreviewMedia/BUILD +++ b/submodules/TelegramUI/Components/WallpaperPreviewMedia/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/TelegramCore", ], visibility = [ From 41072637476f3cfc246ea3c894098cf03693a346 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Thu, 7 May 2026 07:36:30 +0200 Subject: [PATCH 13/14] Postbox refactor waves 358-426 Squashed range bf01b4c..a66739c (70 commits) covering 69 waves of the Postbox -> TelegramEngine consumer migration plus a few BUILD-dep followups. Notable additions to TelegramCore in this range: - Engine typealiases: EngineRawPeerPresence, EngineRawValueBoxKey, EngineSimpleDictionary, EngineRawPeerView, EngineRawPostboxViewKey, EngineRawPreferencesView, EngineRawMessageHistoryView (+ entry/attrs/ read-state), EngineMessageIdNamespaces, EngineHistoryViewInputAnchor, EngineRawUnreadMessageCountsItem, EngineRawMessageHistorySavedMessages IndexView, EngineRawChatInterfaceStateView, EngineRawOrderedItemList View, EngineRawMessageHistoryThreadIndexView, EngineRawCombinedRead StateView, EngineRawMessageHistoryThreadInfoView, EngineRawBasicPeer View, EngineRawCachedPeerDataView, EngineMessageHistoryThreadData, EngineViewUpdateType, EngineInitialMessageHistoryData, EnginePeerGroupId, EngineChatLocationInput, EngineHistoryViewInputTag. - Engine data items: Peer.CachedData, ItemCollections.InstalledPackInfos, ItemCollections.InstalledPackIds. - Engine facade: TelegramEngine.ItemCollections.allItems(namespace:). - Free function: engineAreMediaArraysEqual forwarder. Net effect: 65+ consumer modules drop "import Postbox"; 131 files changed (+1386 / -1493). Build green at HEAD. --- .../Sources/AccountContext.swift | 105 ++++++------ .../Sources/ChatController.swift | 25 ++- .../AccountContext/Sources/MediaManager.swift | 27 ++- .../ChatListSearchRecentPeersNode.swift | 11 +- .../ChatListUI/Sources/ChatContextMenus.swift | 33 ++-- .../Sources/ChatListController.swift | 4 +- .../Sources/ChatListSearchMediaNode.swift | 51 +++--- .../TabBarChatListFilterController.swift | 25 ++- .../Sources/ChatMediaInputTrendingPane.swift | 35 ++-- .../ChatItemGalleryFooterContentNode.swift | 23 ++- .../Items/UniversalVideoGalleryItem.swift | 4 +- .../HashtagSearchGlobalChatContents.swift | 29 ++-- .../Sources/LegacyMediaPickers.swift | 85 +++++---- .../Sources/ListMessageFileItemNode.swift | 19 +-- .../Sources/ListMessageSnippetItemNode.swift | 5 +- .../Sources/AvatarEditorPreviewView.swift | 30 ++-- .../Sources/ChannelAdminsController.swift | 5 +- .../ChannelBannedMemberController.swift | 51 +++--- .../Sources/ChannelBlacklistController.swift | 2 +- .../Sources/ChannelMembersController.swift | 7 +- .../ChannelMembersSearchContainerNode.swift | 18 +- .../ChannelMembersSearchControllerNode.swift | 4 +- .../ChannelPermissionsController.swift | 9 +- .../Sources/ChannelVisibilityController.swift | 15 +- .../Sources/PhotoResources.swift | 3 +- .../PremiumUI/Sources/PremiumDemoScreen.swift | 22 +-- .../PremiumUI/Sources/PremiumGiftScreen.swift | 5 +- .../Sources/PremiumLimitsListScreen.swift | 22 +-- .../Sources/ReactionContextNode.swift | 28 ++- .../Sources/SearchPeerMembers.swift | 6 +- .../BubbleSettingsController.swift | 23 ++- .../DataAndStorageSettingsController.swift | 5 +- .../ProxyListSettingsController.swift | 5 +- .../SaveIncomingMediaController.swift | 9 +- .../ForwardPrivacyChatPreviewItem.swift | 15 +- .../ArchivedStickerPacksController.swift | 56 +++--- .../FeaturedStickerPacksController.swift | 63 ++++--- .../InstalledStickerPacksController.swift | 161 ++++++++---------- .../TextSizeSelectionController.swift | 37 ++-- .../Themes/ThemePreviewControllerNode.swift | 45 +++-- .../Themes/ThemeSettingsChatPreviewItem.swift | 15 +- .../Sources/UsernameSetupController.swift | 29 ++-- .../Sources/ShareControllerNode.swift | 4 +- .../Sources/ShareLoadingContainerNode.swift | 6 +- .../Sources/StatsMessageItem.swift | 5 +- .../Sources/CallController.swift | 13 +- .../Sources/CallStatusBarNode.swift | 21 ++- .../Sources/PresentationGroupCall.swift | 6 +- .../Sources/VideoChatScreen.swift | 17 +- .../Data/OrderedListsData.swift | 44 +++++ .../TelegramEngine/Data/PeersData.swift | 24 +++ .../TelegramEngineItemCollections.swift | 20 +++ .../TelegramEngine/TelegramEngine.swift | 6 +- .../Utils/EnginePostboxCoding.swift | 33 ++++ .../Sources/TelegramIntents.swift | 19 +-- .../Sources/AttachmentFileController.swift | 57 +++---- .../Sources/AttachmentFileSearchItem.swift | 57 +++---- .../Components/AvatarEditorScreen/BUILD | 1 - .../Sources/AvatarEditorScreen.swift | 69 +++----- .../Sources/ChatHistoryEntry.swift | 25 ++- ...ChatInlineSearchResultsListComponent.swift | 29 ++-- .../Chat/ChatMessageAttachedContentNode/BUILD | 1 - .../ChatMessageAttachedContentNode.swift | 19 +-- .../ChatMessageInteractiveFileNode.swift | 31 ++-- .../Sources/ChatMessageDateHeader.swift | 8 +- .../Chat/ChatMessageNotificationItem/BUILD | 1 - .../Sources/ChatMessageNotificationItem.swift | 9 +- .../Sources/ChatRecentActionsController.swift | 2 +- .../ChatRecentActionsControllerNode.swift | 43 +++-- .../Chat/ForwardAccessoryPanelNode/BUILD | 1 - .../Sources/ForwardAccessoryPanelNode.swift | 18 +- .../Components/Chat/QuickShareScreen/BUILD | 1 - .../Sources/QuickShareScreen.swift | 17 +- .../Components/Chat/TopMessageReactions/BUILD | 1 - .../Sources/TopMessageReactions.swift | 30 +--- .../StickerPaneSearchContentNode.swift | 27 ++- .../TelegramUI/Components/ChatTitleView/BUILD | 1 - .../ChatTitleView/Sources/ChatTitleView.swift | 15 +- .../Sources/StickerAttachmentScreen.swift | 73 +++----- .../Sources/ForumCreateTopicScreen.swift | 17 +- .../Sources/ChatGiftPreviewItem.swift | 11 +- .../GroupStickerPackSetupController.swift | 75 ++++---- .../Sources/CreateLinkScreen.swift | 9 +- .../Sources/MediaEditorScreen.swift | 10 +- .../Sources/PeerMessagesMediaPlaylist.swift | 69 ++++---- .../PeerAllowedReactionsScreen/BUILD | 1 - .../Sources/PeerAllowedReactionsScreen.swift | 21 ++- .../Sources/Panes/PeerInfoGifPaneNode.swift | 55 +++--- .../PeerInfoScreen/Sources/PeerInfoData.swift | 2 +- .../Sources/PeerInfoMembers.swift | 2 +- .../Sources/PeerInfoStoryPaneNode.swift | 41 +++-- .../Sources/RankChatPreviewItem.swift | 28 +-- ...aticBusinessMessageSetupChatContents.swift | 23 ++- .../Sources/BusinessLinkChatContents.swift | 5 +- .../Sources/BusinessIntroSetupScreen.swift | 21 +-- .../PeerNameColorChatPreviewItem.swift | 19 +-- .../Sources/ReactionChatPreviewItem.swift | 15 +- .../ThemeAccentColorControllerNode.swift | 39 +++-- .../Sources/WallpaperGalleryController.swift | 13 +- .../Sources/WallpaperGalleryItem.swift | 27 ++- .../Sources/ThemeGridSearchContentNode.swift | 5 +- .../Sources/WallpaperUtils.swift | 5 +- .../Sources/ShareWithPeersScreen.swift | 2 +- .../Sources/ShareWithPeersScreenState.swift | 4 +- .../Stars/StarsAvatarComponent/BUILD | 1 - .../Sources/StarsAvatarComponent.swift | 7 +- .../Stars/StarsImageComponent/BUILD | 1 - .../Sources/StarsImageComponent.swift | 17 +- .../Sources/PeerListItemComponent.swift | 7 +- .../Sources/StoryContainerScreen.swift | 29 ++-- .../StoryItemSetContainerComponent.swift | 53 +++--- .../Sources/Chat/ChatControllerPaste.swift | 5 +- .../Sources/ChatControllerContentData.swift | 12 +- .../ChatControllerForwardMessages.swift | 9 +- .../ChatControllerOpenAttachmentMenu.swift | 37 ++-- .../ChatControllerOpenMessageShareMenu.swift | 1 - .../ChatInterfaceStateContextMenus.swift | 59 ++++--- .../ChatInterfaceStateContextQueries.swift | 29 ++-- .../TelegramUI/Sources/MediaManager.swift | 2 +- .../Sources/NavigateToChatController.swift | 14 +- .../OverlayAudioPlayerControllerNode.swift | 17 +- .../OverlayAudioPlayerControlsNode.swift | 2 +- .../Sources/OverlayInstantVideoNode.swift | 5 +- .../PreparedChatHistoryViewTransition.swift | 3 +- .../Sources/SharedAccountContext.swift | 2 +- .../Sources/SharedMediaPlayer.swift | 2 +- .../Sources/SharedNotificationManager.swift | 41 +++-- .../Sources/OverlayUniversalVideoNode.swift | 5 +- ...annelMemberCategoriesContextsManager.swift | 50 +++--- .../WebAppMessageChatPreviewItem.swift | 24 +-- .../Sources/WebAppMessagePreviewScreen.swift | 3 +- 131 files changed, 1387 insertions(+), 1494 deletions(-) create mode 100644 submodules/TelegramCore/Sources/TelegramEngine/ItemCollections/TelegramEngineItemCollections.swift diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 996f7705aa..ab53edec28 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import AsyncDisplayKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -51,7 +50,7 @@ public final class TelegramApplicationBindings { public let displayNotification: (String) -> Void public let applicationInForeground: Signal public let applicationIsActive: Signal - public let clearMessageNotifications: ([MessageId]) -> Void + public let clearMessageNotifications: ([EngineMessage.Id]) -> Void public let pushIdleTimerExtension: () -> Disposable public let openSettings: () -> Void public let openAppStorePage: () -> Void @@ -67,7 +66,7 @@ public final class TelegramApplicationBindings { public let requestSetAlternateIconName: (String?, @escaping (Bool) -> Void) -> Void public let forceOrientation: (UIInterfaceOrientation) -> Void - public init(isMainApp: Bool, appBundleId: String, appBuildType: TelegramAppBuildType, containerPath: String, appSpecificScheme: String, openUrl: @escaping (String) -> Void, openUniversalUrl: @escaping (String, TelegramApplicationOpenUrlCompletion) -> Void, canOpenUrl: @escaping (String) -> Bool, getTopWindow: @escaping () -> UIWindow?, displayNotification: @escaping (String) -> Void, applicationInForeground: Signal, applicationIsActive: Signal, clearMessageNotifications: @escaping ([MessageId]) -> Void, pushIdleTimerExtension: @escaping () -> Disposable, openSettings: @escaping () -> Void, openAppStorePage: @escaping () -> Void, openSubscriptions: @escaping () -> Void, registerForNotifications: @escaping (@escaping (Bool) -> Void) -> Void, requestSiriAuthorization: @escaping (@escaping (Bool) -> Void) -> Void, siriAuthorization: @escaping () -> AccessType, getWindowHost: @escaping () -> WindowHost?, presentNativeController: @escaping (UIViewController) -> Void, dismissNativeController: @escaping () -> Void, getAvailableAlternateIcons: @escaping () -> [PresentationAppIcon], getAlternateIconName: @escaping () -> String?, requestSetAlternateIconName: @escaping (String?, @escaping (Bool) -> Void) -> Void, forceOrientation: @escaping (UIInterfaceOrientation) -> Void) { + public init(isMainApp: Bool, appBundleId: String, appBuildType: TelegramAppBuildType, containerPath: String, appSpecificScheme: String, openUrl: @escaping (String) -> Void, openUniversalUrl: @escaping (String, TelegramApplicationOpenUrlCompletion) -> Void, canOpenUrl: @escaping (String) -> Bool, getTopWindow: @escaping () -> UIWindow?, displayNotification: @escaping (String) -> Void, applicationInForeground: Signal, applicationIsActive: Signal, clearMessageNotifications: @escaping ([EngineMessage.Id]) -> Void, pushIdleTimerExtension: @escaping () -> Disposable, openSettings: @escaping () -> Void, openAppStorePage: @escaping () -> Void, openSubscriptions: @escaping () -> Void, registerForNotifications: @escaping (@escaping (Bool) -> Void) -> Void, requestSiriAuthorization: @escaping (@escaping (Bool) -> Void) -> Void, siriAuthorization: @escaping () -> AccessType, getWindowHost: @escaping () -> WindowHost?, presentNativeController: @escaping (UIViewController) -> Void, dismissNativeController: @escaping () -> Void, getAvailableAlternateIcons: @escaping () -> [PresentationAppIcon], getAlternateIconName: @escaping () -> String?, requestSetAlternateIconName: @escaping (String?, @escaping (Bool) -> Void) -> Void, forceOrientation: @escaping (UIInterfaceOrientation) -> Void) { self.isMainApp = isMainApp self.appBundleId = appBundleId self.appBuildType = appBuildType @@ -131,7 +130,7 @@ public final class AccountWithInfo: Equatable { public enum OpenURLContext { case generic - case chat(peerId: PeerId, message: Message?, updatedPresentationData: (initial: PresentationData, signal: Signal)?) + case chat(peerId: EnginePeer.Id, message: EngineRawMessage?, updatedPresentationData: (initial: PresentationData, signal: Signal)?) case external } @@ -291,14 +290,14 @@ public enum ResolvedBotStartPeerType { public enum ResolvedUrl { case externalUrl(String) case urlAuth(String) - case peer(Peer?, ChatControllerInteractionNavigateToPeer) + case peer(EngineRawPeer?, ChatControllerInteractionNavigateToPeer) case inaccessiblePeer - case botStart(peer: Peer, payload: String) - case groupBotStart(peerId: PeerId, payload: String, adminRights: ResolvedBotAdminRights?, peerType: ResolvedBotStartPeerType?) - case gameStart(peerId: PeerId, game: String) - case channelMessage(peer: Peer, messageId: MessageId, timecode: Double?) - case replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage, messageId: MessageId) - case replyThread(messageId: MessageId) + case botStart(peer: EngineRawPeer, payload: String) + case groupBotStart(peerId: EnginePeer.Id, payload: String, adminRights: ResolvedBotAdminRights?, peerType: ResolvedBotStartPeerType?) + case gameStart(peerId: EnginePeer.Id, game: String) + case channelMessage(peer: EngineRawPeer, messageId: EngineMessage.Id, timecode: Double?) + case replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage, messageId: EngineMessage.Id) + case replyThread(messageId: EngineMessage.Id) case stickerPack(name: String, type: StickerPackUrlType) case instantView(TelegramMediaWebpage, String?) case proxy(host: String, port: Int32, username: String?, password: String?, secret: Data?) @@ -310,15 +309,15 @@ public enum ResolvedUrl { case share(url: String?, text: String?, to: String?) case wallpaper(WallpaperUrlParameter) case theme(String) - case joinVoiceChat(PeerId, String?) + case joinVoiceChat(EnginePeer.Id, String?) case importStickers - case startAttach(peerId: PeerId, payload: String?, choose: ResolvedBotChoosePeerTypes?) + case startAttach(peerId: EnginePeer.Id, payload: String?, choose: ResolvedBotChoosePeerTypes?) case invoice(slug: String, invoice: TelegramMediaInvoice?) case premiumOffer(reference: String?) case starsTopup(amount: Int64?, purpose: String?) case chatFolder(slug: String) - case story(peerId: PeerId, id: Int32) - case boost(peerId: PeerId?, status: ChannelBoostStatus?, myBoostStatus: MyBoostStatus?) + case story(peerId: EnginePeer.Id, id: Int32) + case boost(peerId: EnginePeer.Id?, status: ChannelBoostStatus?, myBoostStatus: MyBoostStatus?) case premiumGiftCode(slug: String) case premiumMultiGift(reference: String?) case auction(auction: GiftAuctionContext?) @@ -326,12 +325,12 @@ public enum ResolvedUrl { case stars case ton case shareStory(Int64) - case storyFolder(peerId: PeerId, id: Int64) - case giftCollection(peerId: PeerId, id: Int64) - case sendGift(peerId: PeerId?) + case storyFolder(peerId: EnginePeer.Id, id: Int64) + case giftCollection(peerId: EnginePeer.Id, id: Int64) + case sendGift(peerId: EnginePeer.Id?) case unknownDeepLink(path: String) case oauth(url: String) - case createBot(parentBot: PeerId, username: String?, title: String?) + case createBot(parentBot: EnginePeer.Id, username: String?, title: String?) case textStyle(style: TelegramComposeAIMessageMode.CloudStyle.Custom, initialPreview: AIMessageStylePreview?) public enum ResolvedCollectible { @@ -425,7 +424,7 @@ public final class ChatGreetingData: Equatable { public enum ChatSearchDomain: Equatable { case everything case members - case member(Peer) + case member(EngineRawPeer) case tag(MessageReaction.Reaction) public static func ==(lhs: ChatSearchDomain, rhs: ChatSearchDomain) -> Bool { @@ -459,7 +458,7 @@ public enum ChatSearchDomain: Equatable { } public enum ChatLocation: Equatable { - case peer(id: PeerId) + case peer(id: EnginePeer.Id) case replyThread(message: ChatReplyThreadMessage) case customChatContents } @@ -474,7 +473,7 @@ public extension ChatLocation { } } - var peerId: PeerId? { + var peerId: EnginePeer.Id? { switch self { case let .peer(peerId): return peerId @@ -579,7 +578,7 @@ public final class NavigateToChatControllerParams { public let animated: Bool public let forceAnimatedScroll: Bool public let options: NavigationAnimationOptions - public let parentGroupId: PeerGroupId? + public let parentGroupId: EnginePeerGroupId? public let chatListFilter: Int32? public let chatNavigationStack: [ChatNavigationStackItem] public let changeColors: Bool @@ -614,7 +613,7 @@ public final class NavigateToChatControllerParams { animated: Bool = true, forceAnimatedScroll: Bool = false, options: NavigationAnimationOptions = [], - parentGroupId: PeerGroupId? = nil, + parentGroupId: EnginePeerGroupId? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [ChatNavigationStackItem] = [], changeColors: Bool = false, @@ -737,8 +736,8 @@ public enum PeerInfoControllerMode { case generic case calls(messages: [EngineMessage]) case nearbyPeer(distance: Int32) - case group(sourceMessageId: MessageId) - case reaction(MessageId) + case group(sourceMessageId: EngineMessage.Id) + case reaction(EngineMessage.Id) case forumTopic(thread: ChatReplyThreadMessage) case recommendedChannels case myProfile @@ -810,7 +809,7 @@ public enum ChatListSearchFilter: Equatable { case music case voice case instantVideo - case peer(PeerId, Bool, String, String) + case peer(EnginePeer.Id, Bool, String, String) case date(Int32?, Int32, String) case publicPosts @@ -1361,15 +1360,15 @@ public protocol SharedAccountContext: AnyObject { func updateNotificationTokensRegistration() func setAccountUserInterfaceInUse(_ id: AccountRecordId) -> Disposable - func handleTextLinkAction(context: AccountContext, peerId: PeerId?, navigateDisposable: MetaDisposable, controller: ViewController, action: TextLinkItemActionType, itemLink: TextLinkItem) + func handleTextLinkAction(context: AccountContext, peerId: EnginePeer.Id?, navigateDisposable: MetaDisposable, controller: ViewController, action: TextLinkItemActionType, itemLink: TextLinkItem) func openSearch(filter: ChatListSearchFilter, query: String?) - func navigateToChat(accountId: AccountRecordId, peerId: PeerId, messageId: MessageId?) + func navigateToChat(accountId: AccountRecordId, peerId: EnginePeer.Id, messageId: EngineMessage.Id?) func openChatMessage(_ params: OpenChatMessageParams) -> Bool - func messageFromPreloadedChatHistoryViewForLocation(id: MessageId, location: ChatHistoryLocationInput, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject?, chatLocationContextHolder: Atomic, tag: HistoryViewInputTag?) -> Signal<(MessageIndex?, Bool), NoError> + func messageFromPreloadedChatHistoryViewForLocation(id: EngineMessage.Id, location: ChatHistoryLocationInput, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject?, chatLocationContextHolder: Atomic, tag: EngineHistoryViewInputTag?) -> Signal<(EngineMessage.Index?, Bool), NoError> - func makeOverlayAudioPlayerController(context: AccountContext, chatLocation: ChatLocation, type: MediaManagerPlayerType, initialMessageId: MessageId, initialOrder: MusicPlaybackSettingsOrder, playlistLocation: SharedMediaPlaylistLocation?, parentNavigationController: NavigationController?) -> ViewController & OverlayAudioPlayerController + func makeOverlayAudioPlayerController(context: AccountContext, chatLocation: ChatLocation, type: MediaManagerPlayerType, initialMessageId: EngineMessage.Id, initialOrder: MusicPlaybackSettingsOrder, playlistLocation: SharedMediaPlaylistLocation?, parentNavigationController: NavigationController?) -> ViewController & OverlayAudioPlayerController func makePeerInfoController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, peer: EnginePeer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, fromChat: Bool, requestsContext: PeerInvitationImportersContext?) -> ViewController? - func makeChannelAdminController(context: AccountContext, peerId: PeerId, adminId: PeerId, initialParticipant: ChannelParticipant) -> ViewController? + func makeChannelAdminController(context: AccountContext, peerId: EnginePeer.Id, adminId: EnginePeer.Id, initialParticipant: ChannelParticipant) -> ViewController? func makeDeviceContactInfoController(context: ShareControllerAccountContext, environment: ShareControllerEnvironment, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController func makePeersNearbyController(context: AccountContext) -> ViewController func makeComposeController(context: AccountContext) -> ViewController @@ -1380,25 +1379,25 @@ public protocol SharedAccountContext: AnyObject { updatedPresentationData: (initial: PresentationData, signal: Signal), chatLocation: ChatLocation, chatLocationContextHolder: Atomic, - tag: HistoryViewInputTag?, + tag: EngineHistoryViewInputTag?, source: ChatHistoryListSource, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteractionProtocol, - selectedMessages: Signal?, NoError>, + selectedMessages: Signal?, NoError>, mode: ChatHistoryListMode ) -> ChatHistoryListNode func subscribeChatListData(context: AccountContext, location: ChatListControllerLocation) -> Signal - func makeChatMessagePreviewItem(context: AccountContext, messages: [Message], theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder, forcedResourceStatus: FileMediaResourceStatus?, tapMessage: ((Message) -> Void)?, clickThroughMessage: ((UIView?, CGPoint?) -> Void)?, backgroundNode: ASDisplayNode?, availableReactions: AvailableReactions?, accountPeer: Peer?, isCentered: Bool, isPreview: Bool, isStandalone: Bool, rank: String?, rankRole: ChatRankInfoScreenRole?) -> ListViewItem + func makeChatMessagePreviewItem(context: AccountContext, messages: [EngineRawMessage], theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder, forcedResourceStatus: FileMediaResourceStatus?, tapMessage: ((EngineRawMessage) -> Void)?, clickThroughMessage: ((UIView?, CGPoint?) -> Void)?, backgroundNode: ASDisplayNode?, availableReactions: AvailableReactions?, accountPeer: EngineRawPeer?, isCentered: Bool, isPreview: Bool, isStandalone: Bool, rank: String?, rankRole: ChatRankInfoScreenRole?) -> ListViewItem func makeChatMessageDateHeaderItem(context: AccountContext, timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder) -> ListViewItemHeader - func makeChatMessageAvatarHeaderItem(context: AccountContext, timestamp: Int32, peer: Peer, message: Message, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder) -> ListViewItemHeader - func makePeerSharedMediaController(context: AccountContext, peerId: PeerId) -> ViewController? + func makeChatMessageAvatarHeaderItem(context: AccountContext, timestamp: Int32, peer: EngineRawPeer, message: EngineRawMessage, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder) -> ListViewItemHeader + func makePeerSharedMediaController(context: AccountContext, peerId: EnginePeer.Id) -> ViewController? func makeContactSelectionController(_ params: ContactSelectionControllerParams) -> ContactSelectionController func makeContactMultiselectionController(_ params: ContactMultiselectionControllerParams) -> ContactMultiselectionController func makePeerSelectionController(_ params: PeerSelectionControllerParams) -> PeerSelectionController func makeProxySettingsController(context: AccountContext) -> ViewController func makeLocalizationListController(context: AccountContext) -> ViewController - func makeCreateGroupController(context: AccountContext, peerIds: [PeerId], initialTitle: String?, mode: CreateGroupMode, completion: ((PeerId, @escaping () -> Void) -> Void)?) -> ViewController - func makeChatRecentActionsController(context: AccountContext, peer: EnginePeer, adminPeerId: PeerId?, starsState: StarsRevenueStats?) -> ViewController + func makeCreateGroupController(context: AccountContext, peerIds: [EnginePeer.Id], initialTitle: String?, mode: CreateGroupMode, completion: ((EnginePeer.Id, @escaping () -> Void) -> Void)?) -> ViewController + func makeChatRecentActionsController(context: AccountContext, peer: EnginePeer, adminPeerId: EnginePeer.Id?, starsState: StarsRevenueStats?) -> ViewController func makePrivacyAndSecurityController(context: AccountContext) -> ViewController func makeBioPrivacyController(context: AccountContext, settings: Promise, present: @escaping (ViewController) -> Void) func makeBirthdayPrivacyController(context: AccountContext, settings: Promise, openedFromBirthdayScreen: Bool, present: @escaping (ViewController) -> Void) @@ -1435,15 +1434,15 @@ public protocol SharedAccountContext: AnyObject { func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, scrollToEndIfExists: Bool, keepStack: NavigateToChatKeepStack, animated: Bool) -> Signal func chatControllerForForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64) -> Signal func openStorageUsage(context: AccountContext) - func openLocationScreen(context: AccountContext, messageId: MessageId, navigationController: NavigationController) + func openLocationScreen(context: AccountContext, messageId: EngineMessage.Id, navigationController: NavigationController) func openExternalUrl(context: AccountContext, urlContext: OpenURLContext, url: String, forceExternal: Bool, presentationData: PresentationData, navigationController: NavigationController?, dismissInput: @escaping () -> Void) func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set, keepUpdated: Bool) -> Signal func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set, messages: [EngineMessage.Id: EngineMessage], peers: [EnginePeer.Id: EnginePeer]) -> Signal - func resolveUrl(context: AccountContext, peerId: PeerId?, url: String, skipUrlAuth: Bool) -> Signal - func resolveUrlWithProgress(context: AccountContext, peerId: PeerId?, url: String, skipUrlAuth: Bool) -> Signal - func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, forceUpdate: Bool, openPeer: @escaping (EnginePeer, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, UIView?, CGRect?) -> Bool)?, sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?, progress: Promise?, completion: (() -> Void)?) + func resolveUrl(context: AccountContext, peerId: EnginePeer.Id?, url: String, skipUrlAuth: Bool) -> Signal + func resolveUrlWithProgress(context: AccountContext, peerId: EnginePeer.Id?, url: String, skipUrlAuth: Bool) -> Signal + func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, forceUpdate: Bool, openPeer: @escaping (EnginePeer, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, UIView?, CGRect?) -> Bool)?, sendEmoji: ((String, ChatTextInputTextCustomEmojiAttribute) -> Void)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((EnginePeer.Id, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?, progress: Promise?, completion: (() -> Void)?) func openAddContact(context: AccountContext, peer: EnginePeer?, firstName: String, lastName: String, phoneNumber: String, label: String, present: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, completed: @escaping () -> Void) - func openAddPersonContact(context: AccountContext, peerId: PeerId, pushController: @escaping (ViewController) -> Void, present: @escaping (ViewController, Any?) -> Void) + func openAddPersonContact(context: AccountContext, peerId: EnginePeer.Id, pushController: @escaping (ViewController) -> Void, present: @escaping (ViewController, Any?) -> Void) func presentContactsWarningSuppression(context: AccountContext, present: (ViewController, Any?) -> Void) func openImagePicker(context: AccountContext, completion: @escaping (UIImage) -> Void, present: @escaping (ViewController) -> Void) func displaySetPhoto( @@ -1454,9 +1453,9 @@ public protocol SharedAccountContext: AnyObject { completedWithUploadingImage: @escaping (UIImage, Signal) -> UIView? ) func openAddPeerMembers(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, parentController: ViewController, groupPeer: EnginePeer, selectAddMemberDisposable: MetaDisposable, addMemberDisposable: MetaDisposable) - func makeInstantPageController(context: AccountContext, message: Message, sourcePeerType: MediaAutoDownloadPeerType?) -> ViewController? + func makeInstantPageController(context: AccountContext, message: EngineRawMessage, sourcePeerType: MediaAutoDownloadPeerType?) -> ViewController? func makeInstantPageController(context: AccountContext, webPage: TelegramMediaWebpage, anchor: String?, sourceLocation: InstantPageSourceLocation) -> ViewController - func openChatWallpaper(context: AccountContext, message: Message, present: @escaping (ViewController, Any?) -> Void) + func openChatWallpaper(context: AccountContext, message: EngineRawMessage, present: @escaping (ViewController, Any?) -> Void) func makeRecentSessionsController(context: AccountContext, activeSessionsContext: ActiveSessionsContext) -> ViewController & RecentSessionsController func makeChatQrCodeScreen(context: AccountContext, peer: EnginePeer, threadId: Int64?, temporary: Bool) -> ViewController func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource, forceDark: Bool, dismissed: (() -> Void)?) -> ViewController @@ -1680,15 +1679,15 @@ public protocol AccountContext: AnyObject { func storeSecureIdPassword(password: String) func getStoredSecureIdPassword() -> String? - func chatLocationInput(for location: ChatLocation, contextHolder: Atomic) -> ChatLocationInput - func chatLocationOutgoingReadState(for location: ChatLocation, contextHolder: Atomic) -> Signal + func chatLocationInput(for location: ChatLocation, contextHolder: Atomic) -> EngineChatLocationInput + func chatLocationOutgoingReadState(for location: ChatLocation, contextHolder: Atomic) -> Signal func chatLocationUnreadCount(for location: ChatLocation, contextHolder: Atomic) -> Signal - func applyMaxReadIndex(for location: ChatLocation, contextHolder: Atomic, messageIndex: MessageIndex) - - func scheduleGroupCall(peerId: PeerId, parentController: ViewController) - func joinGroupCall(peerId: PeerId, invite: String?, requestJoinAsPeerId: ((@escaping (PeerId?) -> Void) -> Void)?, activeCall: EngineGroupCallDescription) + func applyMaxReadIndex(for location: ChatLocation, contextHolder: Atomic, messageIndex: EngineMessage.Index) + + func scheduleGroupCall(peerId: EnginePeer.Id, parentController: ViewController) + func joinGroupCall(peerId: EnginePeer.Id, invite: String?, requestJoinAsPeerId: ((@escaping (EnginePeer.Id?) -> Void) -> Void)?, activeCall: EngineGroupCallDescription) func joinConferenceCall(call: JoinCallLinkInformation, isVideo: Bool, unmuteByDefault: Bool) - func requestCall(peerId: PeerId, isVideo: Bool, completion: @escaping () -> Void) + func requestCall(peerId: EnginePeer.Id, isVideo: Bool, completion: @escaping () -> Void) } public struct AntiSpamBotConfiguration { diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index c4ad63952e..39418cacac 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import TelegramCore -import Postbox import TextFormat import AsyncDisplayKit import Display @@ -817,7 +816,7 @@ public enum ChatControllerSubject: Equatable { } } - case tag(MessageTags) + case tag(EngineMessage.Tags) case message(id: MessageSubject, highlight: MessageHighlight?, timecode: Double?, setupReply: Bool) case scheduledMessages case pinnedMessages(id: EngineMessage.Id?) @@ -1003,7 +1002,7 @@ public enum PeerInfoAvatarUploadStatus { } public protocol PeerInfoScreen: ViewController { - var peerId: PeerId { get } + var peerId: EnginePeer.Id { get } var privacySettings: Promise { get } var twoStepAuthData: Promise { get } var notificationExceptions: Promise { get } @@ -1021,7 +1020,7 @@ public protocol PeerInfoScreen: ViewController { func updateProfileVideo(_ image: UIImage, video: Any?, values: Any?, markup: UploadPeerPhotoMarkup?) } -public extension Peer { +public extension EngineRawPeer { func canSetupAutoremoveTimeout(accountPeerId: EnginePeer.Id) -> Bool { if let _ = self as? TelegramSecretChat { return false @@ -1157,19 +1156,19 @@ public enum FileMediaResourceMediaStatus: Equatable { public protocol ChatMessageItemNodeProtocol: ListViewItemNode { func makeProgress() -> Promise? func targetReactionView(value: MessageReaction.Reaction) -> UIView? - func targetForStoryTransition(id: StoryId) -> UIView? + func targetForStoryTransition(id: EngineStoryId) -> UIView? func contentFrame() -> CGRect - func matchesMessage(id: MessageId) -> Bool + func matchesMessage(id: EngineMessage.Id) -> Bool func cancelInsertionAnimations() - func messages() -> [Message] + func messages() -> [EngineRawMessage] func updateHiddenMedia() } public final class ChatControllerNavigationData: CustomViewControllerNavigationData { - public let peerId: PeerId + public let peerId: EnginePeer.Id public let threadId: Int64? - - public init(peerId: PeerId, threadId: Int64?) { + + public init(peerId: EnginePeer.Id, threadId: Int64?) { self.peerId = peerId self.threadId = threadId } @@ -1212,8 +1211,8 @@ public enum ChatHistoryListSource { } case `default` - case custom(messages: Signal<([Message], Int32, Bool), NoError>, messageId: MessageId?, quote: Quote?, isSavedMusic: Bool, canReorder: Bool, loadMore: (() -> Void)?) - case customView(historyView: Signal<(MessageHistoryView, ViewUpdateType), NoError>) + case custom(messages: Signal<([EngineRawMessage], Int32, Bool), NoError>, messageId: EngineMessage.Id?, quote: Quote?, isSavedMusic: Bool, canReorder: Bool, loadMore: (() -> Void)?) + case customView(historyView: Signal<(EngineRawMessageHistoryView, EngineViewUpdateType), NoError>) } public enum ChatQuickReplyShortcutType { @@ -1230,7 +1229,7 @@ public enum ChatCustomContentsKind: Equatable { public protocol ChatCustomContentsProtocol: AnyObject { var kind: ChatCustomContentsKind { get } - var historyView: Signal<(MessageHistoryView, ViewUpdateType), NoError> { get } + var historyView: Signal<(EngineRawMessageHistoryView, EngineViewUpdateType), NoError> { get } var messageLimit: Int? { get } func enqueueMessages(messages: [EnqueueMessage]) diff --git a/submodules/AccountContext/Sources/MediaManager.swift b/submodules/AccountContext/Sources/MediaManager.swift index 2af36d90ed..e4dbd1e68c 100644 --- a/submodules/AccountContext/Sources/MediaManager.swift +++ b/submodules/AccountContext/Sources/MediaManager.swift @@ -1,5 +1,4 @@ import Foundation -import Postbox import TelegramCore import SwiftSignalKit import UIKit @@ -9,10 +8,10 @@ import UniversalMediaPlayer import RangeSet public enum PeerMessagesMediaPlaylistId: Equatable, SharedMediaPlaylistId { - case peer(PeerId) - case recentActions(PeerId) + case peer(EnginePeer.Id) + case recentActions(EnginePeer.Id) case feed(Int32) - case savedMusic(PeerId) + case savedMusic(EnginePeer.Id) case custom public func isEqual(to: SharedMediaPlaylistId) -> Bool { @@ -24,11 +23,11 @@ public enum PeerMessagesMediaPlaylistId: Equatable, SharedMediaPlaylistId { } public enum PeerMessagesPlaylistLocation: Equatable, SharedMediaPlaylistLocation { - case messages(chatLocation: ChatLocation, tagMask: MessageTags, at: MessageId) - case singleMessage(MessageId) - case recentActions(Message) + case messages(chatLocation: ChatLocation, tagMask: EngineMessage.Tags, at: EngineMessage.Id) + case singleMessage(EngineMessage.Id) + case recentActions(EngineRawMessage) case savedMusic(context: ProfileSavedMusicContext, at: Int32, canReorder: Bool) - case custom(messages: Signal<([Message], Int32, Bool), NoError>, canReorder: Bool, at: MessageId, loadMore: (() -> Void)?, hidePanel: Bool) + case custom(messages: Signal<([EngineRawMessage], Int32, Bool), NoError>, canReorder: Bool, at: EngineMessage.Id, loadMore: (() -> Void)?, hidePanel: Bool) public var playlistId: PeerMessagesMediaPlaylistId { switch self { @@ -62,14 +61,14 @@ public enum PeerMessagesPlaylistLocation: Equatable, SharedMediaPlaylistLocation context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: savedMusicContext.peerId)) ) |> map { state, peer in - var messages: [Message] = [] - var peers = SimpleDictionary() + var messages: [EngineRawMessage] = [] + var peers = EngineSimpleDictionary() if let peer { peers[peerId] = peer._asPeer() } for file in state.files { let stableId = UInt32(clamping: file.fileId.id % Int64(Int32.max)) - messages.append(Message(stableId: stableId, stableVersion: 0, id: MessageId(peerId: peerId, namespace: Namespaces.Message.Local, id: Int32(stableId)), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [.music], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])) + messages.append(EngineRawMessage(stableId: stableId, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: Namespaces.Message.Local, id: Int32(stableId)), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [.music], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file], peers: peers, associatedMessages: EngineSimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])) } var canLoadMore = false if case let .ready(canLoadMoreValue) = state.dataState { @@ -78,7 +77,7 @@ public enum PeerMessagesPlaylistLocation: Equatable, SharedMediaPlaylistLocation return (messages, Int32(messages.count), canLoadMore) }, canReorder: canReorder, - at: MessageId(peerId: peerId, namespace: Namespaces.Message.Local, id: at), + at: EngineMessage.Id(peerId: peerId, namespace: Namespaces.Message.Local, id: at), loadMore: { [weak savedMusicContext] in guard let savedMusicContext else { return @@ -92,7 +91,7 @@ public enum PeerMessagesPlaylistLocation: Equatable, SharedMediaPlaylistLocation } } - public var messageId: MessageId? { + public var messageId: EngineMessage.Id? { switch self { case let .messages(_, _, messageId), let .singleMessage(messageId), let .custom(_, _, messageId, _, _): return messageId @@ -231,7 +230,7 @@ public protocol MediaManager: AnyObject { } public enum GalleryHiddenMediaId: Hashable { - case chat(AccountRecordId, MessageId, Media) + case chat(AccountRecordId, EngineMessage.Id, EngineRawMedia) public static func ==(lhs: GalleryHiddenMediaId, rhs: GalleryHiddenMediaId) -> Bool { switch lhs { diff --git a/submodules/ChatListSearchRecentPeersNode/Sources/ChatListSearchRecentPeersNode.swift b/submodules/ChatListSearchRecentPeersNode/Sources/ChatListSearchRecentPeersNode.swift index 447193c426..7bdb6ddf5a 100644 --- a/submodules/ChatListSearchRecentPeersNode/Sources/ChatListSearchRecentPeersNode.swift +++ b/submodules/ChatListSearchRecentPeersNode/Sources/ChatListSearchRecentPeersNode.swift @@ -4,7 +4,6 @@ import AsyncDisplayKit import Display import SwiftSignalKit import TelegramCore -import Postbox import TelegramPresentationData import MergeLists import HorizontalPeerItem @@ -254,16 +253,16 @@ public final class ChatListSearchRecentPeersNode: ASDisplayNode { } ) |> mapToSignal { peerViews -> Signal<([EnginePeer], [EnginePeer.Id: (Int32, Bool)], [EnginePeer.Id: EnginePeer.Presence]), NoError> in - return stateManager.postbox.combinedView(keys: peerViews.map { item -> PostboxViewKey in - let key = PostboxViewKey.unreadCounts(items: [UnreadMessageCountsItem.peer(id: item.peerId, handleThreads: true)]) + return stateManager.postbox.combinedView(keys: peerViews.map { item -> EngineRawPostboxViewKey in + let key = EngineRawPostboxViewKey.unreadCounts(items: [EngineRawUnreadMessageCountsItem.peer(id: item.peerId, handleThreads: true)]) return key }) |> map { views -> [EnginePeer.Id: Int] in var result: [EnginePeer.Id: Int] = [:] for item in peerViews { - let key = PostboxViewKey.unreadCounts(items: [UnreadMessageCountsItem.peer(id: item.peerId, handleThreads: true)]) - - if let view = views.views[key] as? UnreadMessageCountsView { + let key = EngineRawPostboxViewKey.unreadCounts(items: [EngineRawUnreadMessageCountsItem.peer(id: item.peerId, handleThreads: true)]) + + if let view = views.views[key] as? EngineRawUnreadMessageCountsView { result[item.peerId] = Int(view.count(for: .peer(id: item.peerId, handleThreads: true)) ?? 0) } else { result[item.peerId] = 0 diff --git a/submodules/ChatListUI/Sources/ChatContextMenus.swift b/submodules/ChatListUI/Sources/ChatContextMenus.swift index 64b01eecac..24b23d24e6 100644 --- a/submodules/ChatListUI/Sources/ChatContextMenus.swift +++ b/submodules/ChatListUI/Sources/ChatContextMenus.swift @@ -3,7 +3,6 @@ import UIKit import SwiftSignalKit import ContextUI import AccountContext -import Postbox import TelegramCore import Display import TelegramUIPreferences @@ -17,11 +16,11 @@ import TelegramStringFormatting import ChatTimerScreen import NotificationPeerExceptionController -func archiveContextMenuItems(context: AccountContext, groupId: PeerGroupId, chatListController: ChatListControllerImpl?) -> Signal<[ContextMenuItem], NoError> { +func archiveContextMenuItems(context: AccountContext, group: EngineChatList.Group, chatListController: ChatListControllerImpl?) -> Signal<[ContextMenuItem], NoError> { let presentationData = context.sharedContext.currentPresentationData.with({ $0 }) let strings = presentationData.strings return combineLatest( - context.engine.messages.unreadChatListPeerIds(groupId: EngineChatList.Group(groupId), filterPredicate: nil), + context.engine.messages.unreadChatListPeerIds(groupId: group, filterPredicate: nil), context.engine.data.get( TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key: ApplicationSpecificPreferencesKeys.chatArchiveSettings) ) @@ -31,7 +30,7 @@ func archiveContextMenuItems(context: AccountContext, groupId: PeerGroupId, chat if !unreadChatListPeerIds.isEmpty { items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_MarkAllAsRead, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MarkAsRead"), color: theme.contextMenu.primaryColor) }, action: { _, f in - let _ = (context.engine.messages.markAllChatsAsReadInteractively(items: [(groupId: EngineChatList.Group(groupId), filterPredicate: nil)]) + let _ = (context.engine.messages.markAllChatsAsReadInteractively(items: [(groupId: group, filterPredicate: nil)]) |> deliverOnMainQueue).startStandalone(completed: { f(.default) }) @@ -54,7 +53,7 @@ enum ChatContextMenuSource { case search(ChatListSearchContextActionSource) } -func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: ChatListNodeEntryPromoInfo?, source: ChatContextMenuSource, chatListController: ChatListControllerImpl?, joined: Bool) -> Signal<[ContextMenuItem], NoError> { +func chatContextMenuItems(context: AccountContext, peerId: EnginePeer.Id, promoInfo: ChatListNodeEntryPromoInfo?, source: ChatContextMenuSource, chatListController: ChatListControllerImpl?, joined: Bool) -> Signal<[ContextMenuItem], NoError> { let presentationData = context.sharedContext.currentPresentationData.with({ $0 }) let strings = presentationData.strings @@ -363,7 +362,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch } } - let archiveEnabled = !isSavedMessages && peerId != PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(777000)) && peerId == context.account.peerId + let archiveEnabled = !isSavedMessages && peerId != EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(777000)) && peerId == context.account.peerId if let group = peerGroup { if archiveEnabled { let isArchived = group == .archive @@ -587,7 +586,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch } } -public func chatForumTopicMenuItems(context: AccountContext, peerId: PeerId, threadId: Int64, isPinned: Bool?, isClosed: Bool?, chatListController: ViewController?, joined: Bool, canSelect: Bool, customEdit: ((ContextController) -> Void)? = nil, customPinUnpin: ((ContextController) -> Void)? = nil, reorder: (() -> Void)? = nil, onDeleted: (() -> Void)? = nil) -> Signal<[ContextMenuItem], NoError> { +public func chatForumTopicMenuItems(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, isPinned: Bool?, isClosed: Bool?, chatListController: ViewController?, joined: Bool, canSelect: Bool, customEdit: ((ContextController) -> Void)? = nil, customPinUnpin: ((ContextController) -> Void)? = nil, reorder: (() -> Void)? = nil, onDeleted: (() -> Void)? = nil) -> Signal<[ContextMenuItem], NoError> { let presentationData = context.sharedContext.currentPresentationData.with({ $0 }) let strings = presentationData.strings @@ -822,30 +821,30 @@ public func chatForumTopicMenuItems(context: AccountContext, peerId: PeerId, thr TelegramEngine.EngineData.Item.NotificationSettings.Global() ) |> deliverOnMainQueue).startStandalone(next: { globalSettings in - let updatePeerSound: (PeerId, PeerMessageSound) -> Signal = { peerId, sound in + let updatePeerSound: (EnginePeer.Id, PeerMessageSound) -> Signal = { peerId, sound in return context.engine.peers.updatePeerNotificationSoundInteractive(peerId: peerId, threadId: threadId, sound: sound) |> deliverOnMainQueue } - let updatePeerNotificationInterval: (PeerId, Int32?) -> Signal = { peerId, muteInterval in + let updatePeerNotificationInterval: (EnginePeer.Id, Int32?) -> Signal = { peerId, muteInterval in return context.engine.peers.updatePeerMuteSetting(peerId: peerId, threadId: threadId, muteInterval: muteInterval) |> deliverOnMainQueue } - let updatePeerDisplayPreviews: (PeerId, PeerNotificationDisplayPreviews) -> Signal = { + let updatePeerDisplayPreviews: (EnginePeer.Id, PeerNotificationDisplayPreviews) -> Signal = { peerId, displayPreviews in return context.engine.peers.updatePeerDisplayPreviewsSetting(peerId: peerId, threadId: threadId, displayPreviews: displayPreviews) |> deliverOnMainQueue } - let updatePeerStoriesMuted: (PeerId, PeerStoryNotificationSettings.Mute) -> Signal = { + let updatePeerStoriesMuted: (EnginePeer.Id, PeerStoryNotificationSettings.Mute) -> Signal = { peerId, mute in return context.engine.peers.updatePeerStoriesMutedSetting(peerId: peerId, mute: mute) |> deliverOnMainQueue } - let updatePeerStoriesHideSender: (PeerId, PeerStoryNotificationSettings.HideSender) -> Signal = { + let updatePeerStoriesHideSender: (EnginePeer.Id, PeerStoryNotificationSettings.HideSender) -> Signal = { peerId, hideSender in return context.engine.peers.updatePeerStoriesHideSenderSetting(peerId: peerId, hideSender: hideSender) |> deliverOnMainQueue } - let updatePeerStorySound: (PeerId, PeerMessageSound) -> Signal = { peerId, sound in + let updatePeerStorySound: (EnginePeer.Id, PeerMessageSound) -> Signal = { peerId, sound in return context.engine.peers.updatePeerStorySoundInteractive(peerId: peerId, sound: sound) |> deliverOnMainQueue } @@ -979,11 +978,9 @@ public func savedMessagesPeerMenuItems(context: AccountContext, threadId: Int64, return combineLatest( context.engine.data.get( - TelegramEngine.EngineData.Item.Peer.Peer(id: PeerId(threadId)) + TelegramEngine.EngineData.Item.Peer.Peer(id: EnginePeer.Id(threadId)) ), - context.account.postbox.transaction { transaction -> [Int64] in - return transaction.getPeerPinnedThreads(peerId: context.account.peerId) - } + context.engine.peers.getForumChannelPinnedTopics(id: context.account.peerId) ) |> mapToSignal { [weak parentController] peer, pinnedThreadIds -> Signal<[ContextMenuItem], NoError> in var items: [ContextMenuItem] = [] @@ -1014,7 +1011,7 @@ public func savedMessagesPeerMenuItems(context: AccountContext, threadId: Int64, }))) items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Delete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { _, f in - deletePeerChat(PeerId(threadId)) + deletePeerChat(EnginePeer.Id(threadId)) f(.default) }))) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index c9c94d3288..ac5cecec9d 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -1883,7 +1883,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController case let .groupReference(groupReference): let chatListController = ChatListControllerImpl(context: strongSelf.context, location: .chatList(groupId: groupReference.groupId), controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false) chatListController.navigationPresentation = .master - let contextController = makeContextController(presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: archiveContextMenuItems(context: strongSelf.context, groupId: groupReference.groupId._asGroup(), chatListController: strongSelf) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture) + let contextController = makeContextController(presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: archiveContextMenuItems(context: strongSelf.context, group: groupReference.groupId, chatListController: strongSelf) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture) strongSelf.presentInGlobalOverlay(contextController) case let .peer(peerData): let peer = peerData.peer @@ -6833,7 +6833,7 @@ private final class ChatListLocationContext { return (nil, value) } } else { - return context.peerChannelMemberCategoriesContextsManager.recentOnlineSmall(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) + return context.peerChannelMemberCategoriesContextsManager.recentOnlineSmall(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId) |> map { value -> (total: Int32?, recent: Int32?) in return (value.total, value.recent) } diff --git a/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift b/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift index d25137a6be..78b3dff62f 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift @@ -4,7 +4,6 @@ import UIKit import Display import TelegramCore import SwiftSignalKit -import Postbox import TelegramPresentationData import AccountContext import ContextUI @@ -20,17 +19,17 @@ private let mediaBadgeBackgroundColor = UIColor(white: 0.0, alpha: 0.6) private let mediaBadgeTextColor = UIColor.white private final class VisualMediaItemInteraction { - let openMessage: (Message) -> Void - let openMessageContextActions: (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void - let toggleSelection: (MessageId, Bool) -> Void - - var hiddenMedia: [MessageId: [Media]] = [:] - var selectedMessageIds: Set? - + let openMessage: (EngineRawMessage) -> Void + let openMessageContextActions: (EngineRawMessage, ASDisplayNode, CGRect, ContextGesture?) -> Void + let toggleSelection: (EngineMessage.Id, Bool) -> Void + + var hiddenMedia: [EngineMessage.Id: [EngineRawMedia]] = [:] + var selectedMessageIds: Set? + init( - openMessage: @escaping (Message) -> Void, - openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, - toggleSelection: @escaping (MessageId, Bool) -> Void + openMessage: @escaping (EngineRawMessage) -> Void, + openMessageContextActions: @escaping (EngineRawMessage, ASDisplayNode, CGRect, ContextGesture?) -> Void, + toggleSelection: @escaping (EngineMessage.Id, Bool) -> Void ) { self.openMessage = openMessage self.openMessageContextActions = openMessageContextActions @@ -53,9 +52,9 @@ private final class VisualMediaItemNode: ASDisplayNode { private let fetchStatusDisposable = MetaDisposable() private let fetchDisposable = MetaDisposable() - private var resourceStatus: MediaResourceStatus? + private var resourceStatus: EngineMediaResourceStatus? - private var item: (VisualMediaItem, Media?, CGSize, CGSize?)? + private var item: (VisualMediaItem, EngineRawMedia?, CGSize, CGSize?)? private var theme: PresentationTheme? private var hasVisibility: Bool = false @@ -117,7 +116,7 @@ private final class VisualMediaItemNode: ASDisplayNode { if let (gesture, _) = recognizer.lastRecognizedGestureAndLocation { if case .tap = gesture { if let _ = self.item { - var media: Media? + var media: EngineRawMedia? for value in message.media { if let image = value as? TelegramMediaImage { media = image @@ -150,7 +149,7 @@ private final class VisualMediaItemNode: ASDisplayNode { return } - var media: Media? + var media: EngineRawMedia? for value in message.media { if let image = value as? TelegramMediaImage { media = image @@ -185,7 +184,7 @@ private final class VisualMediaItemNode: ASDisplayNode { return } self.theme = theme - var media: Media? + var media: EngineRawMedia? if let message = item.message { for value in message.media { if let image = value as? TelegramMediaImage { @@ -404,11 +403,11 @@ private final class VisualMediaItemNode: ASDisplayNode { private final class VisualMediaItem { let index: UInt32? - let message: Message? + let message: EngineRawMessage? let dimensions: CGSize let aspectRatio: CGFloat - - init(message: Message, index: UInt32?) { + + init(message: EngineRawMessage, index: UInt32?) { self.index = index self.message = message @@ -637,7 +636,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, ASScrollViewDelegate { public var beganInteractiveDragging: (() -> Void)? public var loadMore: (() -> Void)? - init(context: AccountContext, contentType: ContentType, openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Void, messageContextAction: @escaping (Message, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void, toggleMessageSelection: @escaping (MessageId, Bool) -> Void) { + init(context: AccountContext, contentType: ContentType, openMessage: @escaping (EngineRawMessage, ChatControllerInteractionOpenMessageMode) -> Void, messageContextAction: @escaping (EngineRawMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void) { self.context = context self.contentType = contentType @@ -675,7 +674,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, ASScrollViewDelegate { guard let strongSelf = self else { return } - var hiddenMedia: [MessageId: [Media]] = [:] + var hiddenMedia: [EngineMessage.Id: [EngineRawMedia]] = [:] for id in ids { if case let .chat(accountId, messageId, media) = id, accountId == strongSelf.context.account.id { hiddenMedia[messageId] = [media] @@ -694,7 +693,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, ASScrollViewDelegate { self.animationTimer?.invalidate() } - func updateHistory(entries: [ChatListSearchEntry]?, totalCount: Int32, updateType: ViewUpdateType) { + func updateHistory(entries: [ChatListSearchEntry]?, totalCount: Int32, updateType: EngineViewUpdateType) { switch updateType { case .FillHole: break @@ -733,7 +732,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, ASScrollViewDelegate { } } - func findLoadedMessage(id: MessageId) -> Message? { + func findLoadedMessage(id: EngineMessage.Id) -> EngineRawMessage? { for item in self.mediaItems { if item.message?.id == id { return item.message @@ -754,7 +753,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, ASScrollViewDelegate { } } - func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + func transitionNodeForGallery(messageId: EngineMessage.Id, media: EngineRawMedia) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { for item in self.mediaItems { if let message = item.message, message.id == messageId { if let itemNode = self.visibleMediaItems[message.stableId] { @@ -770,7 +769,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, ASScrollViewDelegate { self.scrollNode.view.addSubview(view) } - var selectedMessageIds: Set? { + var selectedMessageIds: Set? { didSet { self.itemInteraction.selectedMessageIds = self.selectedMessageIds } @@ -865,7 +864,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, ASScrollViewDelegate { let (minVisibleIndex, maxVisibleIndex) = itemsLayout.visibleRange(rect: visibleRect) - var headerItem: Message? + var headerItem: EngineRawMessage? var validIds = Set() if minVisibleIndex <= maxVisibleIndex { diff --git a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift index 6120890cf6..1e3df440cf 100644 --- a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift +++ b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift @@ -5,7 +5,6 @@ import SwiftSignalKit import AsyncDisplayKit import TelegramPresentationData import AccountContext -import Postbox import TelegramUIPreferences import TelegramCore @@ -13,10 +12,10 @@ public func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatL return context.engine.peers.updatedChatListFilters() |> distinctUntilChanged |> mapToSignal { filters -> Signal<(Int, [(ChatListFilter, Int, Bool)]), NoError> in - var unreadCountItems: [UnreadMessageCountsItem] = [] + var unreadCountItems: [EngineRawUnreadMessageCountsItem] = [] unreadCountItems.append(.totalInGroup(.root)) - var additionalPeerIds = Set() - var additionalGroupIds = Set() + var additionalPeerIds = Set() + var additionalGroupIds = Set() for case let .filter(_, _, _, data) in filters { additionalPeerIds.formUnion(data.includePeers.peers) additionalPeerIds.formUnion(data.excludePeers) @@ -33,9 +32,9 @@ public func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatL unreadCountItems.append(.totalInGroup(groupId)) } - let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) - let unreadKey: PostboxViewKey = .unreadCounts(items: unreadCountItems) - var keys: [PostboxViewKey] = [] + let globalNotificationsKey: EngineRawPostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) + let unreadKey: EngineRawPostboxViewKey = .unreadCounts(items: unreadCountItems) + var keys: [EngineRawPostboxViewKey] = [] keys.append(globalNotificationsKey) keys.append(unreadKey) for peerId in additionalPeerIds { @@ -44,12 +43,12 @@ public func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatL return context.account.postbox.combinedView(keys: keys) |> map { view -> (Int, [(ChatListFilter, Int, Bool)]) in - guard let unreadCounts = view.views[unreadKey] as? UnreadMessageCountsView else { + guard let unreadCounts = view.views[unreadKey] as? EngineRawUnreadMessageCountsView else { return (0, []) } var globalNotificationSettings: GlobalNotificationSettingsSet - if let settingsView = view.views[globalNotificationsKey] as? PreferencesView, let settings = settingsView.values[PreferencesKeys.globalNotifications]?.get(GlobalNotificationSettings.self) { + if let settingsView = view.views[globalNotificationsKey] as? EngineRawPreferencesView, let settings = settingsView.values[PreferencesKeys.globalNotifications]?.get(GlobalNotificationSettings.self) { globalNotificationSettings = settings.effective } else { globalNotificationSettings = GlobalNotificationSettings.defaultSettings.effective @@ -57,9 +56,9 @@ public func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatL var result: [(ChatListFilter, Int, Bool)] = [] - var peerTagAndCount: [PeerId: (PeerSummaryCounterTags, Int, Bool, PeerGroupId?, Bool)] = [:] + var peerTagAndCount: [EnginePeer.Id: (EnginePeerSummaryCounterTags, Int, Bool, EnginePeerGroupId?, Bool)] = [:] - var totalStates: [PeerGroupId: ChatListTotalUnreadState] = [:] + var totalStates: [EnginePeerGroupId: EngineChatListTotalUnreadState] = [:] for entry in unreadCounts.entries { switch entry { case let .total(_, state): @@ -68,7 +67,7 @@ public func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatL totalStates[groupId] = state case let .peer(peerId, state): if let state = state, state.isUnread { - if let peerView = view.views[.basicPeer(peerId)] as? BasicPeerView, let peer = peerView.peer { + if let peerView = view.views[.basicPeer(peerId)] as? EngineRawBasicPeerView, let peer = peerView.peer { let tag = context.account.postbox.seedConfiguration.peerSummaryCounterTags(peer, peerView.isContact) var peerCount = Int(state.count) @@ -113,7 +112,7 @@ public func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatL var count = 0 var unmutedUnreadCount = 0 if case let .filter(_, _, _, data) = filter { - var tags: [PeerSummaryCounterTags] = [] + var tags: [EnginePeerSummaryCounterTags] = [] if data.categories.contains(.contacts) { tags.append(.contact) } diff --git a/submodules/FeaturedStickersScreen/Sources/ChatMediaInputTrendingPane.swift b/submodules/FeaturedStickersScreen/Sources/ChatMediaInputTrendingPane.swift index 44beeb380e..580693d0f1 100644 --- a/submodules/FeaturedStickersScreen/Sources/ChatMediaInputTrendingPane.swift +++ b/submodules/FeaturedStickersScreen/Sources/ChatMediaInputTrendingPane.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import Display -import Postbox import TelegramCore import SwiftSignalKit import TelegramPresentationData @@ -14,13 +13,13 @@ import UndoUI import StickerResources public final class TrendingPaneInteraction { - public let installPack: (ItemCollectionInfo) -> Void - public let openPack: (ItemCollectionInfo) -> Void + public let installPack: (EngineRawItemCollectionInfo) -> Void + public let openPack: (EngineRawItemCollectionInfo) -> Void public let getItemIsPreviewed: (StickerPackItem) -> Bool public let openSearch: () -> Void public let itemContext = StickerPaneSearchGlobalItemContext() - - public init(installPack: @escaping (ItemCollectionInfo) -> Void, openPack: @escaping (ItemCollectionInfo) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, openSearch: @escaping () -> Void) { + + public init(installPack: @escaping (EngineRawItemCollectionInfo) -> Void, openPack: @escaping (EngineRawItemCollectionInfo) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool, openSearch: @escaping () -> Void) { self.installPack = installPack self.openPack = openPack self.getItemIsPreviewed = getItemIsPreviewed @@ -49,7 +48,7 @@ public final class TrendingPanePackEntry: Identifiable, Comparable { self.topSeparator = topSeparator } - public var stableId: ItemCollectionId { + public var stableId: EngineItemCollectionId { return self.info.id } @@ -99,7 +98,7 @@ public final class TrendingPanePackEntry: Identifiable, Comparable { private enum TrendingPaneEntryId: Hashable { case search - case pack(ItemCollectionId) + case pack(EngineItemCollectionId) } private enum TrendingPaneEntry: Identifiable, Comparable { @@ -175,7 +174,7 @@ private func preparedTransition(from fromEntries: [TrendingPaneEntry], to toEntr return TrendingPaneTransition(deletions: deletions, insertions: insertions, updates: updates, initial: initial) } -private func trendingPaneEntries(trendingEntries: [FeaturedStickerPackItem], installedPacks: Set, theme: PresentationTheme, strings: PresentationStrings, isPane: Bool) -> [TrendingPaneEntry] { +private func trendingPaneEntries(trendingEntries: [FeaturedStickerPackItem], installedPacks: Set, theme: PresentationTheme, strings: PresentationStrings, isPane: Bool) -> [TrendingPaneEntry] { var result: [TrendingPaneEntry] = [] var index = 0 if isPane { @@ -192,12 +191,12 @@ private func trendingPaneEntries(trendingEntries: [FeaturedStickerPackItem], ins public final class ChatMediaInputTrendingPane: ChatMediaInputPane { public final class Interaction { - let sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, UIView?, CGRect?, CALayer?, [ItemCollectionId]) -> Bool + let sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, UIView?, CGRect?, CALayer?, [EngineItemCollectionId]) -> Bool let presentController: (ViewController, Any?) -> Void let getNavigationController: () -> NavigationController? - + public init( - sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, UIView?, CGRect?, CALayer?, [ItemCollectionId]) -> Bool, + sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, UIView?, CGRect?, CALayer?, [EngineItemCollectionId]) -> Bool, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: @escaping () -> NavigationController? ) { @@ -388,19 +387,15 @@ public final class ChatMediaInputTrendingPane: ChatMediaInputPane { let previousEntries = Atomic<[TrendingPaneEntry]?>(value: nil) let context = self.context let forceTheme = self.forceTheme - self.disposable = (combineLatest(context.account.viewTracker.featuredStickerPacks(), context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])]), context.sharedContext.presentationData) - |> map { trendingEntries, view, presentationData -> TrendingPaneTransition in + self.disposable = (combineLatest(context.account.viewTracker.featuredStickerPacks(), context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCollections.InstalledPackInfos(namespace: Namespaces.ItemCollection.CloudStickerPacks)), context.sharedContext.presentationData) + |> map { trendingEntries, packsEntries, presentationData -> TrendingPaneTransition in var presentationData = presentationData if let forceTheme { presentationData = presentationData.withUpdated(theme: forceTheme) } - var installedPacks = Set() - if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionInfosView { - if let packsEntries = stickerPacksView.entriesByNamespace[Namespaces.ItemCollection.CloudStickerPacks] { - for entry in packsEntries { - installedPacks.insert(entry.id) - } - } + var installedPacks = Set() + for entry in packsEntries { + installedPacks.insert(entry.id) } let entries = trendingPaneEntries(trendingEntries: trendingEntries, installedPacks: installedPacks, theme: presentationData.theme, strings: presentationData.strings, isPane: isPane) let previous = previousEntries.swap(entries) diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index 1b5551a902..88e6dc1925 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import Display -import Postbox import TelegramCore import SwiftSignalKit import Photos @@ -49,7 +48,7 @@ private let cloudFetchIcon = generateTintedImage(image: UIImage(bundleImageName: enum ChatItemGalleryFooterContent: Equatable { case info - case fetch(status: MediaResourceStatus, seekable: Bool) + case fetch(status: EngineMediaResource.FetchStatus, seekable: Bool) case playback(paused: Bool, seekable: Bool) static func ==(lhs: ChatItemGalleryFooterContent, rhs: ChatItemGalleryFooterContent) -> Bool { @@ -80,11 +79,11 @@ enum ChatItemGalleryFooterContentTapAction { case none case url(url: String, concealed: Bool) case textMention(String) - case peerMention(PeerId, String) + case peerMention(EnginePeer.Id, String) case botCommand(String) case hashtag(String?, String) case instantPage - case call(PeerId) + case call(EnginePeer.Id) case openMessage case ignore } @@ -169,8 +168,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll private var currentMessageText: NSAttributedString? - private var currentMessage: Message? - private var currentWebPageAndMedia: (TelegramMediaWebpage, Media)? + private var currentMessage: EngineRawMessage? + private var currentWebPageAndMedia: (TelegramMediaWebpage, EngineRawMedia)? private var mediaSubject: GalleryMediaSubject? private let messageContextDisposable = MetaDisposable() @@ -208,7 +207,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll private var currentSpeechHolder: SpeechSynthesizerHolder? var performAction: ((GalleryControllerInteractionTapAction) -> Void)? - var openActionOptions: ((GalleryControllerInteractionTapAction, Message) -> Void)? + var openActionOptions: ((GalleryControllerInteractionTapAction, EngineRawMessage) -> Void)? private var isAd: Bool { if self.currentMessage?.adAttribute != nil { @@ -846,7 +845,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll } } - func setMessage(_ message: Message, mediaSubject: GalleryMediaSubject? = nil, displayInfo: Bool = true, translateToLanguage: String? = nil, peerIsCopyProtected: Bool = false, displayPictureInPictureButton: Bool = false, settingsButtonState: SettingsButtonState? = nil, displayTextRecognitionButton: Bool = false, displayStickersButton: Bool = false, animated: Bool = false) { + func setMessage(_ message: EngineRawMessage, mediaSubject: GalleryMediaSubject? = nil, displayInfo: Bool = true, translateToLanguage: String? = nil, peerIsCopyProtected: Bool = false, displayPictureInPictureButton: Bool = false, settingsButtonState: SettingsButtonState? = nil, displayTextRecognitionButton: Bool = false, displayStickersButton: Bool = false, animated: Bool = false) { self.currentMessage = message self.mediaSubject = mediaSubject @@ -1141,7 +1140,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll } } - func setWebPage(_ webPage: TelegramMediaWebpage, media: Media) { + func setWebPage(_ webPage: TelegramMediaWebpage, media: EngineRawMedia) { self.currentWebPageAndMedia = (webPage, media) } @@ -1665,7 +1664,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll var items: [ActionSheetItem] = [] var personalPeerName: String? var isChannel = false - let peerId: PeerId = messages[0].id.peerId + let peerId: EnginePeer.Id = messages[0].id.peerId if let user = messages[0].peers[messages[0].id.peerId] as? TelegramUser { personalPeerName = EnginePeer(user).compactDisplayTitle } else if let channel = messages[0].peers[messages[0].id.peerId] as? TelegramChannel, case .broadcast = channel.info { @@ -1743,7 +1742,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll for message in messages { var currentKind = messageContentKind(contentSettings: strongSelf.context.currentContentSettings.with { $0 }, message: message, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: strongSelf.context.account.peerId) if case .poll = currentKind, let poll = message.media.first(where: { $0 is TelegramMediaPoll }) as? TelegramMediaPoll { - var media: Media? + var media: EngineRawMedia? switch strongSelf.mediaSubject { case .pollDescription: media = poll.attachedMedia @@ -1993,7 +1992,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll } } - let shareAction: ([Message]) -> Void = { messages in + let shareAction: ([EngineRawMessage]) -> Void = { messages in if let strongSelf = self { let shareController = strongSelf.context.sharedContext.makeShareController(context: strongSelf.context, params: ShareControllerParams(subject: .messages(messages), preferredAction: preferredAction, forceTheme: forceTheme, actionCompleted: { [weak self] in if let strongSelf = self { diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 015887386d..5919706cff 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -1860,7 +1860,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if item.content is HLSVideoContent { footerContent = .playback(paused: true, seekable: seekable) } else { - footerContent = .fetch(status: fetchStatus, seekable: seekable) + footerContent = .fetch(status: EngineMediaResource.FetchStatus(fetchStatus), seekable: seekable) } } else { footerContent = .info @@ -3016,7 +3016,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { let baseNavigationController = self.baseNavigationController() let mediaManager = self.context.sharedContext.mediaManager var expandImpl: (() -> Void)? - let overlayNode = OverlayUniversalVideoNode(context: self.context, postbox: self.context.account.postbox, audioSession: context.sharedContext.mediaManager.audioSession, manager: context.sharedContext.mediaManager.universalVideoManager, content: item.content, expand: { + let overlayNode = OverlayUniversalVideoNode(context: self.context, audioSession: context.sharedContext.mediaManager.audioSession, manager: context.sharedContext.mediaManager.universalVideoManager, content: item.content, expand: { expandImpl?() }, close: { [weak mediaManager] in mediaManager?.setOverlayVideoNode(nil) diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchGlobalChatContents.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchGlobalChatContents.swift index 7bb94a7882..d67f0eaf64 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchGlobalChatContents.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchGlobalChatContents.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import SwiftSignalKit -import Postbox import TelegramCore import AccountContext @@ -20,11 +19,11 @@ final class HashtagSearchGlobalChatContents: ChatCustomContentsProtocol { private let publicPosts: Bool private var currentSearchState: SearchMessagesState? - private(set) var mergedHistoryView: MessageHistoryView? - private var sourceHistoryView: MessageHistoryView? - + private(set) var mergedHistoryView: EngineRawMessageHistoryView? + private var sourceHistoryView: EngineRawMessageHistoryView? + private var historyViewDisposable: Disposable? - let historyViewStream = ValuePipe<(MessageHistoryView, ViewUpdateType)>() + let historyViewStream = ValuePipe<(EngineRawMessageHistoryView, EngineViewUpdateType)>() private var nextUpdateIsHoleFill: Bool = false var hashtagSearchResultsUpdate: ((SearchMessagesResult, SearchMessagesState)) -> Void = { _ in } @@ -64,9 +63,9 @@ final class HashtagSearchGlobalChatContents: ChatCustomContentsProtocol { return } - let updateType: ViewUpdateType = .Initial - - let historyView = MessageHistoryView(tag: nil, namespaces: .just(Set([Namespaces.Message.Cloud])), entries: result.0.messages.reversed().map { MessageHistoryEntry(message: $0, isRead: false, location: nil, monthLocation: nil, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: false)) }, holeEarlier: !result.0.completed, holeLater: false, isLoading: false) + let updateType: EngineViewUpdateType = .Initial + + let historyView = EngineRawMessageHistoryView(tag: nil, namespaces: .just(Set([Namespaces.Message.Cloud])), entries: result.0.messages.reversed().map { EngineRawMessageHistoryEntry(message: $0, isRead: false, location: nil, monthLocation: nil, attributes: EngineRawMutableMessageHistoryEntryAttributes(authorIsContact: false)) }, holeEarlier: !result.0.completed, holeLater: false, isLoading: false) self.sourceHistoryView = historyView self.updateHistoryView(updateType: updateType) @@ -83,11 +82,11 @@ final class HashtagSearchGlobalChatContents: ChatCustomContentsProtocol { }) } - private func updateHistoryView(updateType: ViewUpdateType) { + private func updateHistoryView(updateType: EngineViewUpdateType) { var entries = self.sourceHistoryView?.entries ?? [] entries.sort(by: { $0.message.index < $1.message.index }) - - let mergedHistoryView = MessageHistoryView(tag: nil, namespaces: .just(Set([Namespaces.Message.Cloud])), entries: entries, holeEarlier: self.sourceHistoryView?.holeEarlier ?? false, holeLater: false, isLoading: false) + + let mergedHistoryView = EngineRawMessageHistoryView(tag: nil, namespaces: .just(Set([Namespaces.Message.Cloud])), entries: entries, holeEarlier: self.sourceHistoryView?.holeEarlier ?? false, holeLater: false, isLoading: false) self.mergedHistoryView = mergedHistoryView self.historyViewStream.putNext((mergedHistoryView, updateType)) @@ -112,9 +111,9 @@ final class HashtagSearchGlobalChatContents: ChatCustomContentsProtocol { return } - let updateType: ViewUpdateType = .FillHole - - let historyView = MessageHistoryView(tag: nil, namespaces: .just(Set([Namespaces.Message.Cloud])), entries: result.0.messages.reversed().map { MessageHistoryEntry(message: $0, isRead: false, location: nil, monthLocation: nil, attributes: MutableMessageHistoryEntryAttributes(authorIsContact: false)) }, holeEarlier: !result.0.completed, holeLater: false, isLoading: false) + let updateType: EngineViewUpdateType = .FillHole + + let historyView = EngineRawMessageHistoryView(tag: nil, namespaces: .just(Set([Namespaces.Message.Cloud])), entries: result.0.messages.reversed().map { EngineRawMessageHistoryEntry(message: $0, isRead: false, location: nil, monthLocation: nil, attributes: EngineRawMutableMessageHistoryEntryAttributes(authorIsContact: false)) }, holeEarlier: !result.0.completed, holeLater: false, isLoading: false) self.sourceHistoryView = historyView self.updateHistoryView(updateType: updateType) @@ -143,7 +142,7 @@ final class HashtagSearchGlobalChatContents: ChatCustomContentsProtocol { var kind: ChatCustomContentsKind - var historyView: Signal<(MessageHistoryView, ViewUpdateType), NoError> { + var historyView: Signal<(EngineRawMessageHistoryView, EngineViewUpdateType), NoError> { return self.impl.signalWith({ impl, subscriber in if let mergedHistoryView = impl.mergedHistoryView { subscriber.putNext((mergedHistoryView, .Initial)) diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift index ed09858c52..b11536ead8 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift @@ -3,7 +3,6 @@ import UIKit import LegacyComponents import SwiftSignalKit import TelegramCore -import Postbox import SSignalKit import Display import TelegramPresentationData @@ -20,7 +19,7 @@ public func guessMimeTypeByFileExtension(_ ext: String) -> String { return TGMimeTypeMap.mimeType(forExtension: ext) ?? "application/binary" } -public func configureLegacyAssetPicker(_ controller: TGMediaAssetsController, context: AccountContext, peer: Peer, chatLocation: ChatLocation, captionsEnabled: Bool = true, storeCreatedAssets: Bool = true, showFileTooltip: Bool = false, initialCaption: NSAttributedString, hasSchedule: Bool, presentWebSearch: (() -> Void)?, presentSelectionLimitExceeded: @escaping () -> Void, presentSchedulePicker: @escaping (Bool, @escaping (Int32, Bool) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?) { +public func configureLegacyAssetPicker(_ controller: TGMediaAssetsController, context: AccountContext, peer: EngineRawPeer, chatLocation: ChatLocation, captionsEnabled: Bool = true, storeCreatedAssets: Bool = true, showFileTooltip: Bool = false, initialCaption: NSAttributedString, hasSchedule: Bool, presentWebSearch: (() -> Void)?, presentSelectionLimitExceeded: @escaping () -> Void, presentSchedulePicker: @escaping (Bool, @escaping (Int32, Bool) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?) { let paintStickersContext = LegacyPaintStickersContext(context: context) paintStickersContext.captionPanelView = { return getCaptionPanelView() @@ -65,7 +64,7 @@ public func configureLegacyAssetPicker(_ controller: TGMediaAssetsController, co } } -public func legacyAssetPicker(context: AccountContext, presentationData: PresentationData, editingMedia: Bool, fileMode: Bool, peer: Peer?, threadTitle: String?, saveEditedPhotos: Bool, allowGrouping: Bool, selectionLimit: Int) -> Signal<(LegacyComponentsContext) -> TGMediaAssetsController, Void> { +public func legacyAssetPicker(context: AccountContext, presentationData: PresentationData, editingMedia: Bool, fileMode: Bool, peer: EngineRawPeer?, threadTitle: String?, saveEditedPhotos: Bool, allowGrouping: Bool, selectionLimit: Int) -> Signal<(LegacyComponentsContext) -> TGMediaAssetsController, Void> { let isSecretChat = (peer?.id.namespace._internalGetInt32Value() ?? 0) == Namespaces.Peer.SecretChat._internalGetInt32Value() let recipientName: String? @@ -162,7 +161,7 @@ public func legacyAssetPickerItemGenerator() -> ((Any?, NSAttributedString?, Str return { anyDict, caption, hash, uniqueId in let dict = anyDict as! NSDictionary let stickers = (dict["stickers"] as? [Data])?.compactMap { data -> FileMediaReference? in - let decoder = PostboxDecoder(buffer: MemoryBuffer(data: data)) + let decoder = EnginePostboxDecoder(buffer: EngineMemoryBuffer(data: data)) if let file = decoder.decodeRootObject() as? TelegramMediaFile { return FileMediaReference.standalone(media: file) } else { @@ -350,7 +349,7 @@ public func legacyEnqueueGifMessage(account: Account, data: Data, correlationId: fileAttributes.append(.FileName(fileName: fileName)) fileAttributes.append(.Animated) - let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes, alternativeRepresentations: []) + let media = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes, alternativeRepresentations: []) subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])) subscriber.putCompletion() } else { @@ -381,7 +380,7 @@ public func legacyAssetPickerEnqueueMessages( var price: Int64 var text: String var entities: [MessageTextEntity] - var media: [Media] + var media: [EngineRawMedia] } var paidMessage: EnqueuePaidMessage? @@ -409,9 +408,9 @@ public func legacyAssetPickerEnqueueMessages( let scaledSize = image.size.aspectFittedOrSmaller(maxSize) if let scaledImage = TGScaleImageToPixelSize(image, scaledSize) { - let tempFile = TempBox.shared.tempFile(fileName: "file") + let tempFile = EngineTempBox.shared.tempFile(fileName: "file") defer { - TempBox.shared.dispose(tempFile) + EngineTempBox.shared.dispose(tempFile) } if let scaledImageData = compressImageToJPEG(scaledImage, quality: 0.6, tempFilePath: tempFile.path) { let _ = try? scaledImageData.write(to: URL(fileURLWithPath: tempFilePath)) @@ -421,7 +420,7 @@ public func legacyAssetPickerEnqueueMessages( var imageFlags: TelegramMediaImageFlags = [] - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] var stickerFiles: [TelegramMediaFile] = [] if !stickers.isEmpty { @@ -449,8 +448,8 @@ public func legacyAssetPickerEnqueueMessages( } if let dict = adjustments.dictionary(), let data = try? NSKeyedArchiver.archivedData(withRootObject: dict, requiringSecureCoding: false) { - let adjustmentsData = MemoryBuffer(data: data) - let digest = MemoryBuffer(data: adjustmentsData.md5Digest()) + let adjustmentsData = EngineMemoryBuffer(data: data) + let digest = EngineMemoryBuffer(data: adjustmentsData.md5Digest()) resourceAdjustments = VideoMediaResourceAdjustments(data: adjustmentsData, digest: digest, isStory: false) } } @@ -463,11 +462,11 @@ public func legacyAssetPickerEnqueueMessages( if estimatedSize > 10 * 1024 * 1024 { fileAttributes.append(.hintFileIsLarge) } - videoFile = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], videoCover: nil, immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes, alternativeRepresentations: []) + videoFile = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], videoCover: nil, immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes, alternativeRepresentations: []) imageFlags.insert(.isLivePhoto) } - let media = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: randomId), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: imageFlags, video: videoFile) + let media = TelegramMediaImage(imageId: EngineMedia.Id(namespace: Namespaces.Media.LocalImage, id: randomId), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: imageFlags, video: videoFile) if let timer = item.timer, timer > 0 && (timer <= 60 || timer == viewOnceTimeout) { attributes.append(AutoremoveTimeoutMessageAttribute(timeout: Int32(timer), countdownBeginTime: nil)) } @@ -480,7 +479,7 @@ public func legacyAssetPickerEnqueueMessages( if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - var bubbleUpEmojiOrStickersetsById: [Int64: ItemCollectionId] = [:] + var bubbleUpEmojiOrStickersetsById: [Int64: EngineItemCollectionId] = [:] text.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: text.length), using: { value, _, _ in if let value = value as? ChatTextInputTextCustomEmojiAttribute { if let file = value.file { @@ -490,7 +489,7 @@ public func legacyAssetPickerEnqueueMessages( } } }) - var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + var bubbleUpEmojiOrStickersets: [EngineItemCollectionId] = [] for entity in entities { if case let .CustomEmoji(_, fileId) = entity.type { if let packId = bubbleUpEmojiOrStickersetsById[fileId] { @@ -552,13 +551,13 @@ public func legacyAssetPickerEnqueueMessages( let size = CGSize(width: CGFloat(asset.pixelWidth), height: CGFloat(asset.pixelHeight)) let scaledSize = size.aspectFittedOrSmaller(CGSize(width: CGFloat(sizeSide), height: CGFloat(sizeSide))) - let media: Media - media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: format == .jxl ? "image/jxl" : "image/jpeg", size: nil, attributes: [ + let media: EngineRawMedia + media = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: format == .jxl ? "image/jxl" : "image/jpeg", size: nil, attributes: [ .FileName(fileName: format == .jxl ? "image\(sizeSide)-q\(quality).jxl" : "image\(sizeSide)-q\(quality).jpg"), .ImageSize(size: PixelDimensions(scaledSize)) ], alternativeRepresentations: []) - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] if let timer = item.timer, timer > 0 && (timer <= 60 || timer == viewOnceTimeout) { attributes.append(AutoremoveTimeoutMessageAttribute(timeout: Int32(timer), countdownBeginTime: nil)) } @@ -572,7 +571,7 @@ public func legacyAssetPickerEnqueueMessages( attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - var bubbleUpEmojiOrStickersetsById: [Int64: ItemCollectionId] = [:] + var bubbleUpEmojiOrStickersetsById: [Int64: EngineItemCollectionId] = [:] text.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: text.length), using: { value, _, _ in if let value = value as? ChatTextInputTextCustomEmojiAttribute { if let file = value.file { @@ -582,7 +581,7 @@ public func legacyAssetPickerEnqueueMessages( } } }) - var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + var bubbleUpEmojiOrStickersets: [EngineItemCollectionId] = [] for entity in entities { if case let .CustomEmoji(_, fileId) = entity.type { if let packId = bubbleUpEmojiOrStickersetsById[fileId] { @@ -622,11 +621,11 @@ public func legacyAssetPickerEnqueueMessages( let scaledSize = size.aspectFittedOrSmaller(CGSize(width: 1280.0, height: 1280.0)) let resource = PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: Int64.random(in: Int64.min ... Int64.max), forceHd: item.forceHd) - let media: Media + let media: EngineRawMedia representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(scaledSize), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)) - media = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: randomId), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []) + media = TelegramMediaImage(imageId: EngineMedia.Id(namespace: Namespaces.Media.LocalImage, id: randomId), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []) - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] if let timer = item.timer, timer > 0 && (timer <= 60 || timer == viewOnceTimeout) { attributes.append(AutoremoveTimeoutMessageAttribute(timeout: Int32(timer), countdownBeginTime: nil)) } @@ -640,7 +639,7 @@ public func legacyAssetPickerEnqueueMessages( attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - var bubbleUpEmojiOrStickersetsById: [Int64: ItemCollectionId] = [:] + var bubbleUpEmojiOrStickersetsById: [Int64: EngineItemCollectionId] = [:] text.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: text.length), using: { value, _, _ in if let value = value as? ChatTextInputTextCustomEmojiAttribute { if let file = value.file { @@ -650,7 +649,7 @@ public func legacyAssetPickerEnqueueMessages( } } }) - var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + var bubbleUpEmojiOrStickersets: [EngineItemCollectionId] = [] for entity in entities { if case let .CustomEmoji(_, fileId) = entity.type { if let packId = bubbleUpEmojiOrStickersetsById[fileId] { @@ -701,16 +700,16 @@ public func legacyAssetPickerEnqueueMessages( var randomId: Int64 = 0 arc4random_buf(&randomId, 8) let resource = LocalFileReferenceMediaResource(localFilePath: path, randomId: randomId) - let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: fileSize(path), attributes: [.FileName(fileName: name)], alternativeRepresentations: []) + let media = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: engineFileSize(path), attributes: [.FileName(fileName: name)], alternativeRepresentations: []) - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] let text = trimChatInputText(convertMarkdownToAttributes(caption ?? NSAttributedString())) let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text)) if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - var bubbleUpEmojiOrStickersetsById: [Int64: ItemCollectionId] = [:] + var bubbleUpEmojiOrStickersetsById: [Int64: EngineItemCollectionId] = [:] text.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: text.length), using: { value, _, _ in if let value = value as? ChatTextInputTextCustomEmojiAttribute { if let file = value.file { @@ -720,7 +719,7 @@ public func legacyAssetPickerEnqueueMessages( } } }) - var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + var bubbleUpEmojiOrStickersets: [EngineItemCollectionId] = [] for entity in entities { if case let .CustomEmoji(_, fileId) = entity.type { if let packId = bubbleUpEmojiOrStickersetsById[fileId] { @@ -754,16 +753,16 @@ public func legacyAssetPickerEnqueueMessages( var randomId: Int64 = 0 arc4random_buf(&randomId, 8) let resource = PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: Int64.random(in: Int64.min ... Int64.max)) - let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: nil, attributes: [.FileName(fileName: name)], alternativeRepresentations: []) + let media = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: nil, attributes: [.FileName(fileName: name)], alternativeRepresentations: []) - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] let text = trimChatInputText(convertMarkdownToAttributes(caption ?? NSAttributedString())) let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text)) if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - var bubbleUpEmojiOrStickersetsById: [Int64: ItemCollectionId] = [:] + var bubbleUpEmojiOrStickersetsById: [Int64: EngineItemCollectionId] = [:] text.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: text.length), using: { value, _, _ in if let value = value as? ChatTextInputTextCustomEmojiAttribute { if let file = value.file { @@ -773,7 +772,7 @@ public func legacyAssetPickerEnqueueMessages( } } }) - var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + var bubbleUpEmojiOrStickersets: [EngineItemCollectionId] = [] for entity in entities { if case let .CustomEmoji(_, fileId) = entity.type { if let packId = bubbleUpEmojiOrStickersetsById[fileId] { @@ -858,7 +857,7 @@ public func legacyAssetPickerEnqueueMessages( if let coverData = coverImage.jpegData(compressionQuality: 0.87) { account.postbox.mediaBox.storeResourceData(resource.id, data: coverData) videoCover = TelegramMediaImage( - imageId: MediaId(namespace: 0, id: 0), + imageId: EngineMedia.Id(namespace: 0, id: 0), representations: [ TelegramMediaImageRepresentation(dimensions: PixelDimensions(coverSize), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false) ], @@ -891,8 +890,8 @@ public func legacyAssetPickerEnqueueMessages( } if let dict = adjustments.dictionary(), let data = try? NSKeyedArchiver.archivedData(withRootObject: dict, requiringSecureCoding: false) { - let adjustmentsData = MemoryBuffer(data: data) - let digest = MemoryBuffer(data: adjustmentsData.md5Digest()) + let adjustmentsData = EngineMemoryBuffer(data: data) + let digest = EngineMemoryBuffer(data: adjustmentsData.md5Digest()) resourceAdjustments = VideoMediaResourceAdjustments(data: adjustmentsData, digest: digest, isStory: false) } } @@ -907,7 +906,7 @@ public func legacyAssetPickerEnqueueMessages( resource = VideoLibraryMediaResource(localIdentifier: asset.backingAsset.localIdentifier, conversion: asFile ? .passthrough : .compress(resourceAdjustments)) case let .tempFile(path, _, _): if asFile || (asAnimation && !path.contains(".jpg")) { - if let size = fileSize(path) { + if let size = engineFileSize(path) { resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max), size: size) account.postbox.mediaBox.moveResourceData(resource.id, fromTempPath: path) } else { @@ -947,7 +946,7 @@ public func legacyAssetPickerEnqueueMessages( } } - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] var stickerFiles: [TelegramMediaFile] = [] if !stickers.isEmpty { @@ -960,13 +959,13 @@ public func legacyAssetPickerEnqueueMessages( fileAttributes.append(.HasLinkedStickers) } - let media: Media + let media: EngineRawMedia let mediaReference: AnyMediaReference if let adjustments, adjustments.isDefaultValuesForGif(), let originalMediaReference { media = originalMediaReference.media mediaReference = originalMediaReference } else { - media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], videoCover: videoCover, immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes, alternativeRepresentations: []) + media = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], videoCover: videoCover, immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes, alternativeRepresentations: []) mediaReference = .standalone(media: media) } @@ -983,7 +982,7 @@ public func legacyAssetPickerEnqueueMessages( attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - var bubbleUpEmojiOrStickersetsById: [Int64: ItemCollectionId] = [:] + var bubbleUpEmojiOrStickersetsById: [Int64: EngineItemCollectionId] = [:] text.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: text.length), using: { value, _, _ in if let value = value as? ChatTextInputTextCustomEmojiAttribute { if let file = value.file { @@ -993,7 +992,7 @@ public func legacyAssetPickerEnqueueMessages( } } }) - var bubbleUpEmojiOrStickersets: [ItemCollectionId] = [] + var bubbleUpEmojiOrStickersets: [EngineItemCollectionId] = [] for entity in entities { if case let .CustomEmoji(_, fileId) = entity.type { if let packId = bubbleUpEmojiOrStickersetsById[fileId] { @@ -1028,7 +1027,7 @@ public func legacyAssetPickerEnqueueMessages( } if let paidMessage { - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] if !paidMessage.entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: paidMessage.entities)) } diff --git a/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift b/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift index 75d4055d15..3d6e78d82e 100644 --- a/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift +++ b/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import Display -import Postbox import TelegramCore import SwiftSignalKit import TelegramPresentationData @@ -121,7 +120,7 @@ private struct FetchControls { } private enum FileIconImage: Equatable { - case imageRepresentation(Media, TelegramMediaImageRepresentation) + case imageRepresentation(EngineRawMedia, TelegramMediaImageRepresentation) case albumArt(TelegramMediaFile, SharedMediaPlaybackAlbumArt) case roundVideo(TelegramMediaFile) @@ -171,7 +170,7 @@ final class CachedChatListSearchResult { } } -private func selectStoryMedia(item: Stories.Item, preferredHighQuality: Bool) -> Media? { +private func selectStoryMedia(item: Stories.Item, preferredHighQuality: Bool) -> EngineRawMedia? { if !preferredHighQuality, let alternativeMediaValue = item.alternativeMediaList.first { return alternativeMediaValue } else { @@ -372,11 +371,11 @@ public final class ListMessageFileItemNode: ListMessageNode { private let restrictionNode: ASDisplayNode private var currentIconImage: FileIconImage? - public var currentMedia: Media? + public var currentMedia: EngineRawMedia? private let statusDisposable = MetaDisposable() private let fetchControls = Atomic(value: nil) - private var fetchStatus: MediaResourceStatus? + private var fetchStatus: EngineMediaResourceStatus? private var resourceStatus: FileMediaResourceMediaStatus? private let fetchDisposable = MetaDisposable() private let playbackStatusDisposable = MetaDisposable() @@ -389,7 +388,7 @@ public final class ListMessageFileItemNode: ListMessageNode { private var absoluteLocation: (CGRect, CGSize)? private var context: AccountContext? - private(set) var message: Message? + private(set) var message: EngineRawMessage? private var appliedItem: ListMessageItem? private var layoutParams: ListViewItemLayoutParams? @@ -681,7 +680,7 @@ public final class ListMessageFileItemNode: ListMessageNode { var descriptionExtraData: (title: NSAttributedString, showIcon: Bool, iconId: Int64?, iconColor: Int32)? = nil var globalAuthorTitle: String? - var selectedMedia: Media? + var selectedMedia: EngineRawMedia? if let message = message { var effectiveMessageMedia = message.media for media in message.media { @@ -1093,7 +1092,7 @@ public final class ListMessageFileItemNode: ListMessageNode { updateIconImageSignal = .complete() } case let .albumArt(file, albumArt): - updateIconImageSignal = playerAlbumArt(postbox: item.context.account.postbox, engine: item.context.engine, fileReference: .message(message: MessageReference(message), media: file), albumArt: albumArt, thumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3), emptyColor: item.presentationData.theme.theme.list.itemAccentColor) + updateIconImageSignal = playerAlbumArt(engine: item.context.engine, fileReference: .message(message: MessageReference(message), media: file), albumArt: albumArt, thumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3), emptyColor: item.presentationData.theme.theme.list.itemAccentColor) case let .roundVideo(file): updateIconImageSignal = mediaGridMessageVideo(postbox: item.context.account.postbox, userLocation: .peer(message.id.peerId), videoReference: FileMediaReference.message(message: MessageReference(message), media: file), autoFetchFullSizeThumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3)) } @@ -1526,7 +1525,7 @@ public final class ListMessageFileItemNode: ListMessageNode { } } - override public func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(id: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if let item = self.item, let message = item.message, message.id == id, self.iconImageNode.supernode != nil { let iconImageNode = self.iconImageNode return (self.iconImageNode, self.iconImageNode.bounds, { [weak iconImageNode] in @@ -1559,7 +1558,7 @@ public final class ListMessageFileItemNode: ListMessageNode { var downloadingString: String? if let resourceStatus = self.resourceStatus, !item.isAttachMusic { - var maybeFetchStatus: MediaResourceStatus = .Local + var maybeFetchStatus: EngineMediaResourceStatus = .Local switch resourceStatus { case .playbackStatus: break diff --git a/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift b/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift index b743aaf3fe..dfb3bb7f37 100644 --- a/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift +++ b/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import Display -import Postbox import TelegramCore import SwiftSignalKit import TelegramPresentationData @@ -57,7 +56,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode { private let iconImageNode: TransformImageNode private var currentIconImageRepresentation: TelegramMediaImageRepresentation? - private var currentMedia: Media? + private var currentMedia: EngineRawMedia? public var currentPrimaryUrl: String? private var currentIsInstantView: Bool? @@ -861,7 +860,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode { } } - override public func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + override public func transitionNode(id: EngineMessage.Id, media: EngineRawMedia, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if let item = self.item, item.message?.id == id, self.iconImageNode.supernode != nil { let iconImageNode = self.iconImageNode return (self.iconImageNode, self.iconImageNode.bounds, { [weak iconImageNode] in diff --git a/submodules/MediaPickerUI/Sources/AvatarEditorPreviewView.swift b/submodules/MediaPickerUI/Sources/AvatarEditorPreviewView.swift index b65ab55594..83c5a88320 100644 --- a/submodules/MediaPickerUI/Sources/AvatarEditorPreviewView.swift +++ b/submodules/MediaPickerUI/Sources/AvatarEditorPreviewView.swift @@ -3,7 +3,6 @@ import UIKit import Display import SwiftSignalKit import TelegramCore -import Postbox import AvatarBackground import AccountContext import EmojiTextAttachmentView @@ -37,28 +36,25 @@ final class AvatarEditorPreviewView: UIView { self.addSubview(self.backgroundView) - let stickersKey: PostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedProfilePhotoEmoji) - self.disposable = (context.account.postbox.combinedView(keys: [stickersKey]) + self.disposable = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedProfilePhotoEmoji)) |> runOn(Queue.concurrentDefaultQueue()) - |> deliverOnMainQueue).start(next: { [weak self] views in + |> deliverOnMainQueue).start(next: { [weak self] items in guard let self else { return } - if let view = views.views[stickersKey] as? OrderedItemListView { - var files: [TelegramMediaFile] = [] - for item in view.items.prefix(8) { - if let mediaItem = item.contents.get(RecentMediaItem.self) { - 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()) - } - } - self.files = files - if let size = self.currentSize { - self.updateLayout(size: size) + var files: [TelegramMediaFile] = [] + for item in items.prefix(8) { + if let mediaItem = item.contents.get(RecentMediaItem.self) { + 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()) } } + self.files = files + if let size = self.currentSize { + self.updateLayout(size: size) + } }) let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTap)) diff --git a/submodules/PeerInfoUI/Sources/ChannelAdminsController.swift b/submodules/PeerInfoUI/Sources/ChannelAdminsController.swift index 21f5dd4927..3ee97b784d 100644 --- a/submodules/PeerInfoUI/Sources/ChannelAdminsController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelAdminsController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -845,7 +844,7 @@ public func channelAdminsController(context: AccountContext, updatedPresentation |> deliverOnMainQueue).start(next: { peerId in if peerId.namespace == Namespaces.Peer.CloudChannel { var didReportLoadCompleted = false - let membersAndLoadMoreControl: (Disposable, PeerChannelMemberCategoryControl?) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) { membersState in + let membersAndLoadMoreControl: (Disposable, PeerChannelMemberCategoryControl?) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId) { membersState in if case .loading = membersState.loadingState, membersState.list.isEmpty { adminsPromise.set(.single(nil)) } else { @@ -912,7 +911,7 @@ public func channelAdminsController(context: AccountContext, updatedPresentation } for (participant, peer, presence) in participants { if let peer { - var presences: [PeerId: PeerPresence] = [:] + var presences: [EnginePeer.Id: EngineRawPeerPresence] = [:] if let presence { presences[peer.id] = presence._asPresence() } diff --git a/submodules/PeerInfoUI/Sources/ChannelBannedMemberController.swift b/submodules/PeerInfoUI/Sources/ChannelBannedMemberController.swift index ef2cb34f5a..f23d0903a7 100644 --- a/submodules/PeerInfoUI/Sources/ChannelBannedMemberController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelBannedMemberController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import ItemListUI @@ -425,7 +424,7 @@ func completeRights(_ flags: TelegramChatBannedRightsFlags) -> TelegramChatBanne return result } -private func channelBannedMemberControllerEntries(presentationData: PresentationData, state: ChannelBannedMemberControllerState, accountPeerId: PeerId, channelPeer: EnginePeer?, memberPeer: EnginePeer?, memberPresence: EnginePeer.Presence?, initialParticipant: ChannelParticipant?, initialBannedBy: EnginePeer?, editMember: Bool) -> [ChannelBannedMemberEntry] { +private func channelBannedMemberControllerEntries(presentationData: PresentationData, state: ChannelBannedMemberControllerState, accountPeerId: EnginePeer.Id, channelPeer: EnginePeer?, memberPeer: EnginePeer?, memberPresence: EnginePeer.Presence?, initialParticipant: ChannelParticipant?, initialBannedBy: EnginePeer?, editMember: Bool) -> [ChannelBannedMemberEntry] { var entries: [ChannelBannedMemberEntry] = [] if case let .channel(channel) = channelPeer, let defaultBannedRights = channel.defaultBannedRights, let member = memberPeer { @@ -586,7 +585,7 @@ private func channelBannedMemberControllerEntries(presentationData: Presentation return entries } -public func channelBannedMemberController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: PeerId, memberId: PeerId, editMember: Bool = false, initialParticipant: ChannelParticipant?, updated: @escaping (TelegramChatBannedRights?) -> Void, upgradedToSupergroup: @escaping (PeerId, @escaping () -> Void) -> Void) -> ViewController { +public func channelBannedMemberController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: EnginePeer.Id, memberId: EnginePeer.Id, editMember: Bool = false, initialParticipant: ChannelParticipant?, updated: @escaping (TelegramChatBannedRights?) -> Void, upgradedToSupergroup: @escaping (EnginePeer.Id, @escaping () -> Void) -> Void) -> ViewController { let initialState = ChannelBannedMemberControllerState(referenceTimestamp: Int32(Date().timeIntervalSince1970), updatedFlags: nil, updatedTimeout: nil, updating: false, updatedRank: nil, focusedOnRank: false) let statePromise = ValuePromise(initialState, ignoreRepeated: true) let stateValue = Atomic(value: initialState) @@ -609,20 +608,20 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen var errorImpl: (() -> Void)? var scrollToRankImpl: (() -> Void)? - let peerView = Promise() - peerView.set(context.account.viewTracker.peerView(peerId)) + let peerSignal = Promise() + peerSignal.set(context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))) let arguments = ChannelBannedMemberControllerArguments(context: context, toggleRight: { rights, value in - let _ = (peerView.get() + let _ = (peerSignal.get() |> take(1) - |> deliverOnMainQueue).start(next: { view in + |> deliverOnMainQueue).start(next: { peer in var defaultBannedRightsFlagsValue: TelegramChatBannedRightsFlags? - guard let peer = view.peers[peerId] else { + guard let peer else { return } - if let channel = peer as? TelegramChannel, let initialRightFlags = channel.defaultBannedRights?.flags { + if case let .channel(channel) = peer, let initialRightFlags = channel.defaultBannedRights?.flags { defaultBannedRightsFlagsValue = initialRightFlags - } else if let group = peer as? TelegramGroup, let initialRightFlags = group.defaultBannedRights?.flags { + } else if case let .legacyGroup(group) = peer, let initialRightFlags = group.defaultBannedRights?.flags { defaultBannedRightsFlagsValue = initialRightFlags } guard let defaultBannedRightsFlags = defaultBannedRightsFlagsValue else { @@ -648,7 +647,7 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen } } else { effectiveRightsFlags.insert(rights) - for (right, _) in allGroupPermissionList(peer: EnginePeer(peer), expandMedia: false) { + for (right, _) in allGroupPermissionList(peer: peer, expandMedia: false) { if groupPermissionDependencies(right).contains(rights) { effectiveRightsFlags.insert(right) } @@ -656,7 +655,7 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen for item in banSendMediaSubList() { effectiveRightsFlags.insert(item.0) - for (right, _) in allGroupPermissionList(peer: EnginePeer(peer), expandMedia: false) { + for (right, _) in allGroupPermissionList(peer: peer, expandMedia: false) { if groupPermissionDependencies(right).contains(item.0) { effectiveRightsFlags.insert(right) } @@ -669,7 +668,7 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen effectiveRightsFlags = effectiveRightsFlags.subtracting(groupPermissionDependencies(rights)) } else { effectiveRightsFlags.insert(rights) - for (right, _) in allGroupPermissionList(peer: EnginePeer(peer), expandMedia: false) { + for (right, _) in allGroupPermissionList(peer: peer, expandMedia: false) { if groupPermissionDependencies(right).contains(rights) { effectiveRightsFlags.insert(right) } @@ -681,10 +680,10 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen } }) }, toggleRightWhileDisabled: { right in - let _ = (peerView.get() + let _ = (peerSignal.get() |> take(1) - |> deliverOnMainQueue).start(next: { view in - guard let channel = view.peers[view.peerId] as? TelegramChannel else { + |> deliverOnMainQueue).start(next: { peer in + guard case let .channel(channel) = peer else { return } guard let defaultBannedRights = channel.defaultBannedRights else { @@ -839,16 +838,16 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen var footerButtonTitle: String = presentationData.strings.GroupPermission_SaveChanges let rightButtonActionImpl = { - let _ = (peerView.get() + let _ = (peerSignal.get() |> take(1) - |> deliverOnMainQueue).start(next: { view in + |> deliverOnMainQueue).start(next: { peer in var defaultBannedRightsFlagsValue: TelegramChatBannedRightsFlags? - guard let peer = view.peers[peerId] else { + guard let peer else { return } - if let channel = peer as? TelegramChannel, let initialRightFlags = channel.defaultBannedRights?.flags { + if case let .channel(channel) = peer, let initialRightFlags = channel.defaultBannedRights?.flags { defaultBannedRightsFlagsValue = initialRightFlags - } else if let group = peer as? TelegramGroup, let initialRightFlags = group.defaultBannedRights?.flags { + } else if case let .legacyGroup(group) = peer, let initialRightFlags = group.defaultBannedRights?.flags { defaultBannedRightsFlagsValue = initialRightFlags } guard let defaultBannedRightsFlags = defaultBannedRightsFlagsValue else { @@ -933,7 +932,7 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen previousRights = banInfo?.rights } - let updateRankSignal: (PeerId) -> Signal + let updateRankSignal: (EnginePeer.Id) -> Signal if let updateRank { updateRankSignal = { peerId in return context.peerChannelMemberCategoriesContextsManager.updateMemberRank(engine: context.engine, peerId: peerId, memberId: memberId, rank: updateRank) @@ -965,7 +964,7 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen if peerId.namespace == Namespaces.Peer.CloudGroup { let signal = context.engine.peers.convertGroupToSupergroup(peerId: peerId) |> map(Optional.init) - |> `catch` { error -> Signal in + |> `catch` { error -> Signal in switch error { case .tooManyChannels: Queue.mainQueue().async { @@ -976,7 +975,7 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen } return .single(nil) } - |> mapToSignal { upgradedPeerId -> Signal in + |> mapToSignal { upgradedPeerId -> Signal in guard let upgradedPeerId = upgradedPeerId else { return .single(nil) } @@ -984,9 +983,9 @@ public func channelBannedMemberController(context: AccountContext, updatedPresen let rankSignal = updateRankSignal(upgradedPeerId) return context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: upgradedPeerId, memberId: memberId, bannedRights: cleanResolvedRights) - |> mapToSignal { _ -> Signal in + |> mapToSignal { _ -> Signal in return rankSignal - |> mapToSignal { _ -> Signal in + |> mapToSignal { _ -> Signal in return .complete() } } diff --git a/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift b/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift index 4ac22010a9..563e800c12 100644 --- a/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift @@ -431,7 +431,7 @@ public func channelBlacklistController(context: AccountContext, updatedPresentat }) }) - let (listDisposable, loadMoreControl) = context.peerChannelMemberCategoriesContextsManager.banned(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { listState in + let (listDisposable, loadMoreControl) = context.peerChannelMemberCategoriesContextsManager.banned(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, updated: { listState in if case .loading(true) = listState.loadingState, listState.list.isEmpty { blacklistPromise.set(.single(nil)) } else { diff --git a/submodules/PeerInfoUI/Sources/ChannelMembersController.swift b/submodules/PeerInfoUI/Sources/ChannelMembersController.swift index 92ddbb53ed..0019fb3423 100644 --- a/submodules/PeerInfoUI/Sources/ChannelMembersController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelMembersController.swift @@ -15,7 +15,6 @@ import ItemListPeerActionItem import InviteLinksUI import UndoUI import SendInviteLinkScreen -import Postbox private final class ChannelMembersControllerArguments { let context: AccountContext @@ -394,7 +393,7 @@ private struct ChannelMembersControllerState: Equatable { } } -private func channelMembersControllerEntries(context: AccountContext, presentationData: PresentationData, view: PeerView, state: ChannelMembersControllerState, contacts: [RenderedChannelParticipant]?, participants: [RenderedChannelParticipant]?, isGroup: Bool) -> [ChannelMembersEntry] { +private func channelMembersControllerEntries(context: AccountContext, presentationData: PresentationData, view: EngineRawPeerView, state: ChannelMembersControllerState, contacts: [RenderedChannelParticipant]?, participants: [RenderedChannelParticipant]?, isGroup: Bool) -> [ChannelMembersEntry] { if participants == nil || participants?.count == nil { return [] } @@ -721,10 +720,10 @@ public func channelMembersController(context: AccountContext, updatedPresentatio let peerView = context.account.viewTracker.peerView(peerId) - let (contactsDisposable, _) = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: { state in + let (contactsDisposable, _) = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: { state in contactsPromise.set(.single(state.list)) }) - let (disposable, loadMoreControl) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in + let (disposable, loadMoreControl) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in peersPromise.set(.single(state.list)) }) actionsDisposable.add(disposable) diff --git a/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift b/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift index 131210bdf4..eceacff875 100644 --- a/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift +++ b/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift @@ -263,13 +263,13 @@ private func categorySignal(context: AccountContext, peerId: EnginePeer.Id, cate } switch category { case .admins: - disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState) + disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState) case .contacts: - disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState) + disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState) case .bots: - disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.bots(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState) + disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.bots(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState) case .members: - disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState) + disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState) } let (disposable, _) = disposableAndLoadMoreControl @@ -637,7 +637,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon switch mode { case .searchMembers, .banAndPromoteActions: foundGroupMembers = Signal { subscriber in - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in + let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in if case .ready = state.loadingState { subscriber.putNext(state.list) } @@ -652,7 +652,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon |> map { $0 ?? [] } case .searchAdmins: foundGroupMembers = Signal { subscriber in - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in + let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in if case .ready = state.loadingState { subscriber.putNext(state.list) } @@ -662,7 +662,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon foundMembers = .single([]) case .searchBanned: foundGroupMembers = Signal { subscriber in - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.restricted(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in + let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.restricted(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in if case .ready = state.loadingState { subscriber.putNext(state.list) subscriber.putCompletion() @@ -672,7 +672,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon } |> runOn(Queue.mainQueue()) foundMembers = Signal { subscriber in - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in + let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in if case .ready = state.loadingState { subscriber.putNext(state.list.filter({ participant in return participant.peer.id != context.account.peerId @@ -684,7 +684,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon |> runOn(Queue.mainQueue()) case .searchKicked: foundGroupMembers = Signal { subscriber in - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.banned(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in + let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.banned(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in if case .ready = state.loadingState { subscriber.putNext(state.list) subscriber.putCompletion() diff --git a/submodules/PeerInfoUI/Sources/ChannelMembersSearchControllerNode.swift b/submodules/PeerInfoUI/Sources/ChannelMembersSearchControllerNode.swift index cbbe58d850..fd86e031e0 100644 --- a/submodules/PeerInfoUI/Sources/ChannelMembersSearchControllerNode.swift +++ b/submodules/PeerInfoUI/Sources/ChannelMembersSearchControllerNode.swift @@ -439,12 +439,12 @@ class ChannelMembersSearchControllerNode: ASDisplayNode { } else { let membersState = Promise() - disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in + disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in membersState.set(.single(state)) }) let contactsState = Promise() - contactsDisposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: { state in + contactsDisposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: { state in contactsState.set(.single(state)) }) diff --git a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift index e035ee457c..6cd1c9491c 100644 --- a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift @@ -18,7 +18,6 @@ import TelegramPermissionsUI import ItemListPeerActionItem import Markdown import UndoUI -import Postbox import OldChannelsController import MessagePriceItem @@ -683,7 +682,7 @@ func groupPermissionDependencies(_ right: TelegramChatBannedRightsFlags) -> Tele } } -private func channelPermissionsControllerEntries(context: AccountContext, presentationData: PresentationData, view: PeerView, state: ChannelPermissionsControllerState, participants: [RenderedChannelParticipant]?, configuration: StarsSubscriptionConfiguration) -> [ChannelPermissionsEntry] { +private func channelPermissionsControllerEntries(context: AccountContext, presentationData: PresentationData, view: EngineRawPeerView, state: ChannelPermissionsControllerState, participants: [RenderedChannelParticipant]?, configuration: StarsSubscriptionConfiguration) -> [ChannelPermissionsEntry] { var entries: [ChannelPermissionsEntry] = [] if let channel = view.peers[view.peerId] as? TelegramChannel, let participants = participants, let cachedData = view.cachedData as? CachedChannelData, let defaultBannedRights = channel.defaultBannedRights { @@ -870,7 +869,7 @@ public func channelPermissionsController(context: AccountContext, updatedPresent peersPromise.set(.single((peerId, nil))) } else { var loadCompletedCalled = false - let disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.restricted(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in + let disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.restricted(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in if case .loading(true) = state.loadingState, !updated { peersPromise.set(.single((peerId, nil))) } else { @@ -897,7 +896,7 @@ public func channelPermissionsController(context: AccountContext, updatedPresent let updateSendPaidMessageStarsDisposable = MetaDisposable() actionsDisposable.add(updateSendPaidMessageStarsDisposable) - let peerView = Promise() + let peerView = Promise() peerView.set(sourcePeerId.get() |> mapToSignal(context.account.viewTracker.peerView)) @@ -1313,7 +1312,7 @@ public func channelPermissionsController(context: AccountContext, updatedPresent let previousParticipants = Atomic<[RenderedChannelParticipant]?>(value: nil) let viewAndParticipants = combineLatest(queue: .mainQueue(), sourcePeerId.get(), peerView.get(), peersPromise.get()) - |> mapToSignal { peerIdAndChanged, view, peers -> Signal<(PeerView, [RenderedChannelParticipant]?), NoError> in + |> mapToSignal { peerIdAndChanged, view, peers -> Signal<(EngineRawPeerView, [RenderedChannelParticipant]?), NoError> in let (peerId, changed) = peerIdAndChanged if view.peerId != peerId { return .complete() diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index 032111510f..c9bed2e235 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -3,7 +3,6 @@ import UIKit import Display import AsyncDisplayKit import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -795,7 +794,7 @@ private struct ChannelVisibilityControllerState: Equatable { self.approveMembers = nil } - init(selectedType: CurrentChannelType?, editingPublicLinkText: String?, addressNameValidationStatus: AddressNameValidationStatus?, updatingAddressName: Bool, revealedRevokePeerId: PeerId?, revokingPeerId: PeerId?, revokingPrivateLink: Bool, forwardingEnabled: Bool?, joinToSend: CurrentChannelJoinToSend?, approveMembers: Bool?) { + init(selectedType: CurrentChannelType?, editingPublicLinkText: String?, addressNameValidationStatus: AddressNameValidationStatus?, updatingAddressName: Bool, revealedRevokePeerId: EnginePeer.Id?, revokingPeerId: EnginePeer.Id?, revokingPrivateLink: Bool, forwardingEnabled: Bool?, joinToSend: CurrentChannelJoinToSend?, approveMembers: Bool?) { self.selectedType = selectedType self.editingPublicLinkText = editingPublicLinkText self.addressNameValidationStatus = addressNameValidationStatus @@ -883,7 +882,7 @@ private struct ChannelVisibilityControllerState: Equatable { } } -private func channelVisibilityControllerEntries(presentationData: PresentationData, mode: ChannelVisibilityControllerMode, view: PeerView, publicChannelsToRevoke: [EnginePeer]?, importers: PeerInvitationImportersState?, state: ChannelVisibilityControllerState, limits: EngineConfiguration.UserLimits, premiumLimits: EngineConfiguration.UserLimits, isPremium: Bool, isPremiumDisabled: Bool, temporaryOrder: [String]?) -> [ChannelVisibilityEntry] { +private func channelVisibilityControllerEntries(presentationData: PresentationData, mode: ChannelVisibilityControllerMode, view: EngineRawPeerView, publicChannelsToRevoke: [EnginePeer]?, importers: PeerInvitationImportersState?, state: ChannelVisibilityControllerState, limits: EngineConfiguration.UserLimits, premiumLimits: EngineConfiguration.UserLimits, isPremium: Bool, isPremiumDisabled: Bool, temporaryOrder: [String]?) -> [ChannelVisibilityEntry] { var entries: [ChannelVisibilityEntry] = [] let isInitialSetup: Bool @@ -1321,7 +1320,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa return entries } -private func effectiveChannelType(mode: ChannelVisibilityControllerMode, state: ChannelVisibilityControllerState, peer: TelegramChannel, cachedData: CachedPeerData?) -> CurrentChannelType { +private func effectiveChannelType(mode: ChannelVisibilityControllerMode, state: ChannelVisibilityControllerState, peer: TelegramChannel, cachedData: EngineCachedPeerData?) -> CurrentChannelType { let selectedType: CurrentChannelType if let current = state.selectedType { selectedType = current @@ -1339,7 +1338,7 @@ private func effectiveChannelType(mode: ChannelVisibilityControllerMode, state: return selectedType } -private func updatedAddressName(mode: ChannelVisibilityControllerMode, state: ChannelVisibilityControllerState, peer: EnginePeer, cachedData: CachedPeerData?) -> String? { +private func updatedAddressName(mode: ChannelVisibilityControllerMode, state: ChannelVisibilityControllerState, peer: EnginePeer, cachedData: EngineCachedPeerData?) -> String? { if case let .channel(peer) = peer { let selectedType = effectiveChannelType(mode: mode, state: state, peer: peer, cachedData: cachedData) @@ -1995,12 +1994,12 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta _ = ApplicationSpecificNotice.markAsSeenSetPublicChannelLink(accountManager: context.sharedContext.accountManager).start() let signal = context.engine.peers.convertGroupToSupergroup(peerId: peerId) - |> mapToSignal { upgradedPeerId -> Signal in + |> mapToSignal { upgradedPeerId -> Signal in return context.engine.peers.updateAddressName(domain: .peer(upgradedPeerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue) |> `catch` { _ -> Signal in return .complete() } - |> mapToSignal { _ -> Signal in + |> mapToSignal { _ -> Signal in return .complete() } |> then(.single(upgradedPeerId)) @@ -2305,7 +2304,7 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta peerIds = peerIdsValue } - let filteredPeerIds = peerIds.compactMap({ peerId -> PeerId? in + let filteredPeerIds = peerIds.compactMap({ peerId -> EnginePeer.Id? in if case let .peer(id) = peerId { return id } else { diff --git a/submodules/PhotoResources/Sources/PhotoResources.swift b/submodules/PhotoResources/Sources/PhotoResources.swift index e4305b2f2c..75ad209daf 100644 --- a/submodules/PhotoResources/Sources/PhotoResources.swift +++ b/submodules/PhotoResources/Sources/PhotoResources.swift @@ -3102,7 +3102,8 @@ private func drawAlbumArtPlaceholder(into c: CGContext, arguments: TransformImag } } -public func playerAlbumArt(postbox: Postbox, engine: TelegramEngine, fileReference: FileMediaReference?, albumArt: SharedMediaPlaybackAlbumArt?, thumbnail: Bool, overlayColor: UIColor? = nil, emptyColor: UIColor? = nil, drawPlaceholderWhenEmpty: Bool = true, attemptSynchronously: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { +public func playerAlbumArt(engine: TelegramEngine, fileReference: FileMediaReference?, albumArt: SharedMediaPlaybackAlbumArt?, thumbnail: Bool, overlayColor: UIColor? = nil, emptyColor: UIColor? = nil, drawPlaceholderWhenEmpty: Bool = true, attemptSynchronously: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { + let postbox = engine.account.postbox var fileArtworkData: Signal = .single(nil) if let fileReference = fileReference { let size = thumbnail ? CGSize(width: 48.0, height: 48.0) : CGSize(width: 320.0, height: 320.0) diff --git a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift index def7028de2..0217b4dd9c 100644 --- a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import AsyncDisplayKit -import Postbox import TelegramCore import SwiftSignalKit import AccountContext @@ -556,21 +555,10 @@ private final class DemoSheetContent: CombinedComponent { EngineDataMap(accountSpecificStickerOverrides.map(\.messageId).map(TelegramEngine.EngineData.Item.Messages.Message.init)) ) - let stickersKey: PostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudPremiumStickers) self.disposable = (combineLatest( queue: Queue.mainQueue(), self.context.engine.stickers.availableReactions(), - self.context.account.postbox.combinedView(keys: [stickersKey]) - |> map { views -> [OrderedItemListEntry]? in - if let view = views.views[stickersKey] as? OrderedItemListView { - return view.items - } else { - return nil - } - } - |> filter { items in - return items != nil - } + self.context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudPremiumStickers)) |> take(1), self.context.engine.data.get( TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId), @@ -604,11 +592,9 @@ private final class DemoSheetContent: CombinedComponent { if let reactions = reactions { var result: [TelegramMediaFile] = [] - if let items = items { - for item in items { - if let mediaItem = item.contents.get(RecentMediaItem.self) { - result.append(mediaItem.media._parse()) - } + for item in items { + if let mediaItem = item.contents.get(RecentMediaItem.self) { + result.append(mediaItem.media._parse()) } } return (reactions.reactions.filter({ $0.isPremium }).map { reaction -> AvailableReactions.Reaction in diff --git a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index 1e58c28be8..c2d9c19c5b 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -4,7 +4,6 @@ import Display import ComponentFlow import SwiftSignalKit import TelegramCore -import Postbox import TelegramPresentationData import PresentationDataUtils import ViewControllerComponent @@ -154,13 +153,13 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { let _ = updatePremiumPromoConfigurationOnce(account: context.account).start() - let stickersKey: PostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudPremiumStickers) + let stickersKey: EngineRawPostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudPremiumStickers) self.stickersDisposable = (self.context.account.postbox.combinedView(keys: [stickersKey]) |> deliverOnMainQueue).start(next: { [weak self] views in guard let strongSelf = self else { return } - if let view = views.views[stickersKey] as? OrderedItemListView { + if let view = views.views[stickersKey] as? EngineRawOrderedItemListView { for item in view.items { if let mediaItem = item.contents.get(RecentMediaItem.self) { let file = mediaItem.media._parse() diff --git a/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift b/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift index f5c6e6af7b..5b24d6a6e0 100644 --- a/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift @@ -3,7 +3,6 @@ import UIKit import Display import AsyncDisplayKit import TelegramCore -import Postbox import SwiftSignalKit import AccountContext import TelegramPresentationData @@ -103,20 +102,9 @@ public class PremiumLimitsListScreen: ViewController { self.appIcons = controller.context.sharedContext.applicationBindings.getAvailableAlternateIcons() - let stickersKey: PostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudPremiumStickers) self.disposable = (combineLatest( queue: Queue.mainQueue(), - context.account.postbox.combinedView(keys: [stickersKey]) - |> map { views -> [OrderedItemListEntry]? in - if let view = views.views[stickersKey] as? OrderedItemListView { - return view.items - } else { - return nil - } - } - |> filter { items in - return items != nil - } + context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudPremiumStickers)) |> take(1), context.engine.data.get( TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId), @@ -137,11 +125,9 @@ public class PremiumLimitsListScreen: ViewController { } var result: [TelegramMediaFile.Accessor] = [] - if let items = items { - for item in items { - if let mediaItem = item.contents.get(RecentMediaItem.self) { - result.append(mediaItem.media) - } + for item in items { + if let mediaItem = item.contents.get(RecentMediaItem.self) { + result.append(mediaItem.media) } } return (result.map { file -> TelegramMediaFile in diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index ebd644eea5..89d3a1cee3 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -643,16 +643,15 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { } if let getEmojiContent = getEmojiContent, !self.reactionsLocked { - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks) - self.stableEmptyResultEmojiDisposable.set((self.context.account.postbox.combinedView(keys: [viewKey]) + self.stableEmptyResultEmojiDisposable.set((self.context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks)) |> take(1) - |> deliverOnMainQueue).start(next: { [weak self] views in - guard let strongSelf = self, let view = views.views[viewKey] as? OrderedItemListView else { + |> deliverOnMainQueue).start(next: { [weak self] items in + guard let strongSelf = self else { return } var filteredFiles: [TelegramMediaFile] = [] let filterList: [String] = ["😖", "😫", "🫠", "😨", "❓"] - for featuredEmojiPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + for featuredEmojiPack in items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { for item in featuredEmojiPack.topItems { if let alt = item.file.customEmojiAlt { if filterList.contains(alt) { @@ -1743,20 +1742,19 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { return } - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks) - let _ = (strongSelf.context.account.postbox.combinedView(keys: [viewKey]) + let _ = (strongSelf.context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks)) |> take(1) - |> deliverOnMainQueue).start(next: { views in - guard let strongSelf = self, let view = views.views[viewKey] as? OrderedItemListView else { + |> deliverOnMainQueue).start(next: { items in + guard let strongSelf = self else { return } - for featuredEmojiPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + for featuredEmojiPack in items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { if featuredEmojiPack.info.id == collectionId { if let strongSelf = self { strongSelf.scheduledEmojiContentAnimationHint = EmojiPagerContentComponent.ContentAnimation(type: .groupInstalled(id: collectionId, scrollToGroup: true)) } let _ = strongSelf.context.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info._parse(), items: featuredEmojiPack.topItems).start() - + break } } @@ -2039,14 +2037,14 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { let remoteSignal = emojiSearchContext.state return combineLatest( - context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000) |> take(1), + context.engine.itemCollections.allItems(namespace: Namespaces.ItemCollection.CloudEmojiPacks) |> take(1), context.engine.stickers.availableReactions() |> take(1), hasPremium |> take(1), remotePacksSignal, remoteSignal, localPacksSignal ) - |> map { view, availableReactions, hasPremium, foundPacks, foundEmoji, foundLocalPacks -> (groups: [EmojiPagerContentComponent.ItemGroup], canLoadMore: Bool, isSearching: Bool, searchContext: EmojiSearchContext?) in + |> map { rawItems, availableReactions, hasPremium, foundPacks, foundEmoji, foundLocalPacks -> (groups: [EmojiPagerContentComponent.ItemGroup], canLoadMore: Bool, isSearching: Bool, searchContext: EmojiSearchContext?) in var result: [(String, TelegramMediaFile.Accessor?, String)] = [] var allEmoticons: [String: String] = [:] @@ -2071,8 +2069,8 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { } } - for entry in view.entries { - guard let item = entry.item as? StickerPackItem else { + for rawItem in rawItems { + guard let item = rawItem as? StickerPackItem else { continue } if !item.file.isPremiumEmoji { diff --git a/submodules/SearchPeerMembers/Sources/SearchPeerMembers.swift b/submodules/SearchPeerMembers/Sources/SearchPeerMembers.swift index 5b282a77d0..e1f0532fdf 100644 --- a/submodules/SearchPeerMembers/Sources/SearchPeerMembers.swift +++ b/submodules/SearchPeerMembers/Sources/SearchPeerMembers.swift @@ -20,7 +20,7 @@ public func searchPeerMembers(context: AccountContext, peerId: EnginePeer.Id, ch |> mapToSignal { participantCount -> Signal<([EnginePeer], Bool), NoError> in if case .peer = chatLocation, let memberCount = participantCount, memberCount <= 64 { return Signal { subscriber in - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, requestUpdate: false, updated: { state in + let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, requestUpdate: false, updated: { state in if case .ready = state.loadingState { subscriber.putNext((state.list.compactMap { participant -> EnginePeer? in if participant.peer.isDeleted { @@ -52,7 +52,7 @@ public func searchPeerMembers(context: AccountContext, peerId: EnginePeer.Id, ch return Signal { subscriber in switch chatLocation { case let .peer(peerId): - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: normalizedQuery.isEmpty ? nil : normalizedQuery, updated: { state in + let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: normalizedQuery.isEmpty ? nil : normalizedQuery, updated: { state in if case .ready = state.loadingState { subscriber.putNext((state.list.compactMap { participant in if participant.peer.isDeleted { @@ -67,7 +67,7 @@ public func searchPeerMembers(context: AccountContext, peerId: EnginePeer.Id, ch disposable.dispose() } case let .replyThread(replyThreadMessage): - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.mentions(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, threadMessageId: EngineMessage.Id(peerId: replyThreadMessage.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: replyThreadMessage.threadId)), searchQuery: normalizedQuery.isEmpty ? nil : normalizedQuery, updated: { state in + let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.mentions(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, threadMessageId: EngineMessage.Id(peerId: replyThreadMessage.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: replyThreadMessage.threadId)), searchQuery: normalizedQuery.isEmpty ? nil : normalizedQuery, updated: { state in if case .ready = state.loadingState { subscriber.putNext((state.list.compactMap { participant in if participant.peer.isDeleted { diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index 4b2c5e68fe..8b2ab482a5 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import Display -import Postbox import SwiftSignalKit import AsyncDisplayKit import TelegramCore @@ -159,30 +158,30 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, ASScrollViewDel let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) var items: [ListViewItem] = [] - let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) + let peerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)) let otherPeerId = self.context.account.peerId - var peers = SimpleDictionary() - var messages = SimpleDictionary() + var peers = EngineSimpleDictionary() + var messages = EngineSimpleDictionary() peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) - let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) - messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let replyMessageId = EngineMessage.Id(peerId: peerId, namespace: 0, id: 3) + messages[replyMessageId] = EngineRawMessage(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: EngineSimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) - let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message1 = EngineRawMessage(stableId: 4, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) - let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message2 = EngineRawMessage(stableId: 3, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA=" let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)] - let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes, alternativeRepresentations: []) - - let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let voiceMedia = TelegramMediaFile(fileId: EngineMedia.Id(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes, alternativeRepresentations: []) + + let message3 = EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) - let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message4 = EngineRawMessage(stableId: 2, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message4], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) let width: CGFloat diff --git a/submodules/SettingsUI/Sources/Data and Storage/DataAndStorageSettingsController.swift b/submodules/SettingsUI/Sources/Data and Storage/DataAndStorageSettingsController.swift index 9f122dc341..301d9da4dd 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/DataAndStorageSettingsController.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/DataAndStorageSettingsController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import LegacyComponents import TelegramPresentationData @@ -933,10 +932,10 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da } }) - let preferencesKey: PostboxViewKey = .preferences(keys: Set([ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings])) + let preferencesKey: EngineRawPostboxViewKey = .preferences(keys: Set([ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings])) let preferences = context.account.postbox.combinedView(keys: [preferencesKey]) |> map { views -> MediaAutoSaveSettings in - guard let view = views.views[preferencesKey] as? PreferencesView else { + guard let view = views.views[preferencesKey] as? EngineRawPreferencesView else { return .default } return view.values[ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings]?.get(MediaAutoSaveSettings.self) ?? MediaAutoSaveSettings.default diff --git a/submodules/SettingsUI/Sources/Data and Storage/ProxyListSettingsController.swift b/submodules/SettingsUI/Sources/Data and Storage/ProxyListSettingsController.swift index 1e3adc0e28..18bbed17c7 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/ProxyListSettingsController.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/ProxyListSettingsController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import MtProtoKit @@ -329,10 +328,10 @@ public enum ProxySettingsControllerMode { public func proxySettingsController(context: AccountContext, mode: ProxySettingsControllerMode = .default, focusOnItemTag: ProxySettingsEntryTag? = nil) -> ViewController { let presentationData = context.sharedContext.currentPresentationData.with { $0 } - return proxySettingsController(accountManager: context.sharedContext.accountManager, sharedContext: context.sharedContext, context: context, postbox: context.account.postbox, network: context.account.network, mode: mode, presentationData: presentationData, updatedPresentationData: context.sharedContext.presentationData, focusOnItemTag: focusOnItemTag) + return proxySettingsController(accountManager: context.sharedContext.accountManager, sharedContext: context.sharedContext, context: context, network: context.account.network, mode: mode, presentationData: presentationData, updatedPresentationData: context.sharedContext.presentationData, focusOnItemTag: focusOnItemTag) } -public func proxySettingsController(accountManager: AccountManager, sharedContext: SharedAccountContext, context: AccountContext? = nil, postbox: Postbox, network: Network, mode: ProxySettingsControllerMode, presentationData: PresentationData, updatedPresentationData: Signal, focusOnItemTag: ProxySettingsEntryTag? = nil) -> ViewController { +public func proxySettingsController(accountManager: AccountManager, sharedContext: SharedAccountContext, context: AccountContext? = nil, network: Network, mode: ProxySettingsControllerMode, presentationData: PresentationData, updatedPresentationData: Signal, focusOnItemTag: ProxySettingsEntryTag? = nil) -> ViewController { var pushControllerImpl: ((ViewController) -> Void)? var dismissImpl: (() -> Void)? let stateValue = Atomic(value: ProxySettingsControllerState()) diff --git a/submodules/SettingsUI/Sources/Data and Storage/SaveIncomingMediaController.swift b/submodules/SettingsUI/Sources/Data and Storage/SaveIncomingMediaController.swift index c127449e59..e808ffbbae 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/SaveIncomingMediaController.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/SaveIncomingMediaController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -515,10 +514,10 @@ public func saveIncomingMediaController(context: AccountContext, scope: SaveInco controller.peerSelected = { [weak controller] peer, _ in let peerId = peer.id - let preferencesKey: PostboxViewKey = .preferences(keys: Set([ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings])) + let preferencesKey: EngineRawPostboxViewKey = .preferences(keys: Set([ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings])) let preferences = context.account.postbox.combinedView(keys: [preferencesKey]) |> map { views -> MediaAutoSaveSettings in - guard let view = views.views[preferencesKey] as? PreferencesView else { + guard let view = views.views[preferencesKey] as? EngineRawPreferencesView else { return .default } return view.values[ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings]?.get(MediaAutoSaveSettings.self) ?? MediaAutoSaveSettings.default @@ -622,10 +621,10 @@ public func saveIncomingMediaController(context: AccountContext, scope: SaveInco } ) - let preferencesKey: PostboxViewKey = .preferences(keys: Set([ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings])) + let preferencesKey: EngineRawPostboxViewKey = .preferences(keys: Set([ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings])) let preferences = context.account.postbox.combinedView(keys: [preferencesKey]) |> map { views -> MediaAutoSaveSettings in - guard let view = views.views[preferencesKey] as? PreferencesView else { + guard let view = views.views[preferencesKey] as? EngineRawPreferencesView else { return .default } return view.values[ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings]?.get(MediaAutoSaveSettings.self) ?? MediaAutoSaveSettings.default diff --git a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift index 2efd3336d2..13dea1935b 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift @@ -4,7 +4,6 @@ import Display import AsyncDisplayKit import SwiftSignalKit import TelegramCore -import Postbox import TelegramPresentationData import TelegramUIPreferences import ItemListUI @@ -142,16 +141,16 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { let insets: UIEdgeInsets let separatorHeight = UIScreenPixel - let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) - - var peers = SimpleDictionary() - let messages = SimpleDictionary() + let peerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)) + + var peers = EngineSimpleDictionary() + let messages = EngineSimpleDictionary() peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: item.peerName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) - let forwardInfo = MessageForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.peerName, psaType: nil, flags: []) - - let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil) + let forwardInfo = EngineMessage.ForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.peerName, psaType: nil, flags: []) + + let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil) var node: ListViewItemNode? if let current = currentNode { diff --git a/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift index 91570aadf6..db053a13a4 100644 --- a/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -24,12 +23,12 @@ private final class ArchivedStickerPacksControllerArguments { let context: AccountContext let openStickerPack: (StickerPackCollectionInfo) -> Void - let setPackIdWithRevealedOptions: (ItemCollectionId?, ItemCollectionId?) -> Void + let setPackIdWithRevealedOptions: (EngineItemCollectionId?, EngineItemCollectionId?) -> Void let addPack: (StickerPackCollectionInfo) -> Void let removePack: (StickerPackCollectionInfo) -> Void - let togglePackSelected: (ItemCollectionId) -> Void - - init(context: AccountContext, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, addPack: @escaping (StickerPackCollectionInfo) -> Void, removePack: @escaping (StickerPackCollectionInfo) -> Void, togglePackSelected: @escaping (ItemCollectionId) -> Void) { + let togglePackSelected: (EngineItemCollectionId) -> Void + + init(context: AccountContext, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (EngineItemCollectionId?, EngineItemCollectionId?) -> Void, addPack: @escaping (StickerPackCollectionInfo) -> Void, removePack: @escaping (StickerPackCollectionInfo) -> Void, togglePackSelected: @escaping (EngineItemCollectionId) -> Void) { self.context = context self.openStickerPack = openStickerPack self.setPackIdWithRevealedOptions = setPackIdWithRevealedOptions @@ -45,7 +44,7 @@ private enum ArchivedStickerPacksSection: Int32 { private enum ArchivedStickerPacksEntryId: Hashable { case index(Int32) - case pack(ItemCollectionId) + case pack(EngineItemCollectionId) } private enum ArchivedStickerPacksEntry: ItemListNodeEntry { @@ -157,18 +156,18 @@ private enum ArchivedStickerPacksEntry: ItemListNodeEntry { private struct ArchivedStickerPacksControllerState: Equatable { let editing: Bool - let selectedPackIds: Set? - let packIdWithRevealedOptions: ItemCollectionId? - let removingPackIds: Set - + let selectedPackIds: Set? + let packIdWithRevealedOptions: EngineItemCollectionId? + let removingPackIds: Set + init() { self.editing = false self.selectedPackIds = nil self.packIdWithRevealedOptions = nil self.removingPackIds = Set() } - - init(editing: Bool, selectedPackIds: Set?, packIdWithRevealedOptions: ItemCollectionId?, removingPackIds: Set) { + + init(editing: Bool, selectedPackIds: Set?, packIdWithRevealedOptions: EngineItemCollectionId?, removingPackIds: Set) { self.editing = editing self.selectedPackIds = selectedPackIds self.packIdWithRevealedOptions = packIdWithRevealedOptions @@ -196,22 +195,22 @@ private struct ArchivedStickerPacksControllerState: Equatable { return ArchivedStickerPacksControllerState(editing: editing, selectedPackIds: self.selectedPackIds, packIdWithRevealedOptions: self.packIdWithRevealedOptions, removingPackIds: self.removingPackIds) } - func withUpdatedSelectedPackIds(_ selectedPackIds: Set?) -> ArchivedStickerPacksControllerState { + func withUpdatedSelectedPackIds(_ selectedPackIds: Set?) -> ArchivedStickerPacksControllerState { return ArchivedStickerPacksControllerState(editing: self.editing, selectedPackIds: selectedPackIds, packIdWithRevealedOptions: self.packIdWithRevealedOptions, removingPackIds: self.removingPackIds) } - - func withUpdatedPackIdWithRevealedOptions(_ packIdWithRevealedOptions: ItemCollectionId?) -> ArchivedStickerPacksControllerState { + + func withUpdatedPackIdWithRevealedOptions(_ packIdWithRevealedOptions: EngineItemCollectionId?) -> ArchivedStickerPacksControllerState { return ArchivedStickerPacksControllerState(editing: self.editing, selectedPackIds: self.selectedPackIds, packIdWithRevealedOptions: packIdWithRevealedOptions, removingPackIds: self.removingPackIds) } - - func withUpdatedRemovingPackIds(_ removingPackIds: Set) -> ArchivedStickerPacksControllerState { + + func withUpdatedRemovingPackIds(_ removingPackIds: Set) -> ArchivedStickerPacksControllerState { return ArchivedStickerPacksControllerState(editing: self.editing, selectedPackIds: self.selectedPackIds, packIdWithRevealedOptions: self.packIdWithRevealedOptions, removingPackIds: removingPackIds) } } -private func archivedStickerPacksControllerEntries(context: AccountContext, mode: ArchivedStickerPacksControllerMode, presentationData: PresentationData, state: ArchivedStickerPacksControllerState, packs: [ArchivedStickerPackItem]?, installedView: CombinedView, stickerSettings: StickerSettings) -> [ArchivedStickerPacksEntry] { +private func archivedStickerPacksControllerEntries(context: AccountContext, mode: ArchivedStickerPacksControllerMode, presentationData: PresentationData, state: ArchivedStickerPacksControllerState, packs: [ArchivedStickerPackItem]?, installedIds: [EngineItemCollectionId], stickerSettings: StickerSettings) -> [ArchivedStickerPacksEntry] { var entries: [ArchivedStickerPacksEntry] = [] - + if let packs = packs { let info: String switch mode { @@ -221,11 +220,8 @@ private func archivedStickerPacksControllerEntries(context: AccountContext, mode info = presentationData.strings.StickerPacksSettings_ArchivedPacks_Info } entries.append(.info(presentationData.theme, info + "\n\n")) - - var installedIds = Set() - if let view = installedView.views[.itemCollectionIds(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionIdsView, let ids = view.idsByNamespace[Namespaces.ItemCollection.CloudStickerPacks] { - installedIds = ids - } + + let installedIds = Set(installedIds) var index: Int32 = 0 for item in packs { @@ -269,7 +265,7 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv let resolveDisposable = MetaDisposable() actionsDisposable.add(resolveDisposable) - let removePackDisposables = DisposableDict() + let removePackDisposables = DisposableDict() actionsDisposable.add(removePackDisposables) let namespace: ArchivedStickerPacksNamespace @@ -288,8 +284,8 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv updatedPacks(packs) })) - let installedStickerPacks = Promise() - installedStickerPacks.set(context.account.postbox.combinedView(keys: [.itemCollectionIds(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])])) + let installedStickerPacks = Promise<[EngineItemCollectionId]>() + installedStickerPacks.set(context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCollections.InstalledPackIds(namespace: Namespaces.ItemCollection.CloudStickerPacks))) var presentationData = context.sharedContext.currentPresentationData.with { $0 } if let forceTheme { @@ -446,7 +442,7 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv let signal = combineLatest(context.sharedContext.presentationData, statePromise.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, installedStickerPacks.get() |> deliverOnMainQueue, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]) |> deliverOnMainQueue) |> deliverOnMainQueue - |> map { presentationData, state, packs, installedView, sharedData -> (ItemListControllerState, (ItemListNodeState, Any)) in + |> map { presentationData, state, packs, installedIds, sharedData -> (ItemListControllerState, (ItemListNodeState, Any)) in var presentationData = presentationData if let forceTheme { presentationData = presentationData.withUpdated(theme: forceTheme) @@ -538,7 +534,7 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv $0.withUpdatedEditing(false).withUpdatedSelectedPackIds(nil) } - var packIds: [ItemCollectionId] = [] + var packIds: [EngineItemCollectionId] = [] for entry in packs { if let selectedPackIds = state.selectedPackIds, selectedPackIds.contains(entry.info.id) { packIds.append(entry.info.id) @@ -595,7 +591,7 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: archivedStickerPacksControllerEntries(context: context, mode: mode, presentationData: presentationData, state: state, packs: packs, installedView: installedView, stickerSettings: stickerSettings), style: .blocks, emptyStateItem: emptyStateItem, toolbarItem: toolbarItem, animateChanges: previous != nil && packs != nil && (previous! != 0 && previous! >= packs!.count - 10)) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: archivedStickerPacksControllerEntries(context: context, mode: mode, presentationData: presentationData, state: state, packs: packs, installedIds: installedIds, stickerSettings: stickerSettings), style: .blocks, emptyStateItem: emptyStateItem, toolbarItem: toolbarItem, animateChanges: previous != nil && packs != nil && (previous! != 0 && previous! >= packs!.count - 10)) return (controllerState, (listState, arguments)) } |> afterDisposed { actionsDisposable.dispose() diff --git a/submodules/SettingsUI/Sources/Stickers/FeaturedStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/FeaturedStickerPacksController.swift index c62b4f08c5..a190949068 100644 --- a/submodules/SettingsUI/Sources/Stickers/FeaturedStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/FeaturedStickerPacksController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -30,7 +29,7 @@ private enum FeaturedStickerPacksSection: Int32 { } private enum FeaturedStickerPacksEntryId: Hashable { - case pack(ItemCollectionId) + case pack(EngineItemCollectionId) } private enum FeaturedStickerPacksEntry: ItemListNodeEntry { @@ -123,37 +122,35 @@ private struct FeaturedStickerPacksControllerState: Equatable { } } -private func featuredStickerPacksControllerEntries(context: AccountContext, presentationData: PresentationData, state: FeaturedStickerPacksControllerState, view: CombinedView, featured: [FeaturedStickerPackItem], unreadPacks: [ItemCollectionId: Bool], stickerSettings: StickerSettings) -> [FeaturedStickerPacksEntry] { +private func featuredStickerPacksControllerEntries(context: AccountContext, presentationData: PresentationData, state: FeaturedStickerPacksControllerState, view: [EngineRawItemCollectionInfoEntry], featured: [FeaturedStickerPackItem], unreadPacks: [EngineItemCollectionId: Bool], stickerSettings: StickerSettings) -> [FeaturedStickerPacksEntry] { var entries: [FeaturedStickerPacksEntry] = [] - - if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionInfosView, !featured.isEmpty { - if let packsEntries = stickerPacksView.entriesByNamespace[Namespaces.ItemCollection.CloudStickerPacks] { - var installedPacks = Set() - for entry in packsEntries { - installedPacks.insert(entry.id) + + if !featured.isEmpty { + var installedPacks = Set() + for entry in view { + installedPacks.insert(entry.id) + } + var index: Int32 = 0 + for item in featured { + var unread = false + if let value = unreadPacks[item.info.id] { + unread = value } - var index: Int32 = 0 - for item in featured { - var unread = false - if let value = unreadPacks[item.info.id] { - unread = value - } - - let countTitle: String - if item.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { - countTitle = presentationData.strings.StickerPack_EmojiCount(item.info.count) - } else if item.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { - countTitle = presentationData.strings.StickerPack_MaskCount(item.info.count) - } else { - countTitle = presentationData.strings.StickerPack_StickerCount(item.info.count) - } - - entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, unread, item.topItems.first, countTitle, context.sharedContext.energyUsageSettings.loopStickers, installedPacks.contains(item.info.id))) - index += 1 + + let countTitle: String + if item.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + countTitle = presentationData.strings.StickerPack_EmojiCount(item.info.count) + } else if item.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + countTitle = presentationData.strings.StickerPack_MaskCount(item.info.count) + } else { + countTitle = presentationData.strings.StickerPack_StickerCount(item.info.count) } + + entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, unread, item.topItems.first, countTitle, context.sharedContext.energyUsageSettings.loopStickers, installedPacks.contains(item.info.id))) + index += 1 } } - + return entries } @@ -198,13 +195,13 @@ public func featuredStickerPacksController(context: AccountContext) -> ViewContr presentControllerImpl?(textAlertController(context: context, updatedPresentationData: nil, title: nil, text: presentationData.strings.ArchivedPacksAlert_Title, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) })) - let stickerPacks = Promise() - stickerPacks.set(context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])])) + let stickerPacks = Promise<[EngineRawItemCollectionInfoEntry]>() + stickerPacks.set(context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCollections.InstalledPackInfos(namespace: Namespaces.ItemCollection.CloudStickerPacks))) let featured = Promise<[FeaturedStickerPackItem]>() featured.set(context.account.viewTracker.featuredStickerPacks()) - var initialUnreadPacks: [ItemCollectionId: Bool] = [:] + var initialUnreadPacks: [EngineItemCollectionId: Bool] = [:] let signal = combineLatest(context.sharedContext.presentationData, statePromise.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, featured.get() |> deliverOnMainQueue, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]) |> deliverOnMainQueue) |> deliverOnMainQueue @@ -232,10 +229,10 @@ public func featuredStickerPacksController(context: AccountContext) -> ViewContr let controller = ItemListController(context: context, state: signal) - var alreadyReadIds = Set() + var alreadyReadIds = Set() controller.visibleEntriesUpdated = { entries in - var unreadIds: [ItemCollectionId] = [] + var unreadIds: [EngineItemCollectionId] = [] for entry in entries { if let entry = entry as? FeaturedStickerPacksEntry { switch entry { diff --git a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift index 59dda715e0..6ba3bb2f34 100644 --- a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -24,7 +23,7 @@ private final class InstalledStickerPacksControllerArguments { let context: AccountContext let openStickerPack: (StickerPackCollectionInfo) -> Void - let setPackIdWithRevealedOptions: (ItemCollectionId?, ItemCollectionId?) -> Void + let setPackIdWithRevealedOptions: (EngineItemCollectionId?, EngineItemCollectionId?) -> Void let removePack: (ArchivedStickerPackItem) -> Void let openStickersBot: () -> Void let openMasks: () -> Void @@ -34,12 +33,12 @@ private final class InstalledStickerPacksControllerArguments { let openArchived: ([ArchivedStickerPackItem]?) -> Void let openSuggestOptions: () -> Void let toggleSuggestAnimatedEmoji: (Bool) -> Void - let togglePackSelected: (ItemCollectionId) -> Void + let togglePackSelected: (EngineItemCollectionId) -> Void let toggleLargeEmoji: (Bool) -> Void let toggleDynamicPackOrder: (Bool) -> Void let addPack: (StickerPackCollectionInfo) -> Void - init(context: AccountContext, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, removePack: @escaping (ArchivedStickerPackItem) -> Void, openStickersBot: @escaping () -> Void, openMasks: @escaping () -> Void, openEmoji: @escaping () -> Void, openQuickReaction: @escaping () -> Void, openFeatured: @escaping () -> Void, openArchived: @escaping ([ArchivedStickerPackItem]?) -> Void, openSuggestOptions: @escaping () -> Void, toggleSuggestAnimatedEmoji: @escaping (Bool) -> Void, togglePackSelected: @escaping (ItemCollectionId) -> Void, toggleLargeEmoji: @escaping (Bool) -> Void, toggleDynamicPackOrder: @escaping (Bool) -> Void, addPack: @escaping (StickerPackCollectionInfo) -> Void) { + init(context: AccountContext, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (EngineItemCollectionId?, EngineItemCollectionId?) -> Void, removePack: @escaping (ArchivedStickerPackItem) -> Void, openStickersBot: @escaping () -> Void, openMasks: @escaping () -> Void, openEmoji: @escaping () -> Void, openQuickReaction: @escaping () -> Void, openFeatured: @escaping () -> Void, openArchived: @escaping ([ArchivedStickerPackItem]?) -> Void, openSuggestOptions: @escaping () -> Void, toggleSuggestAnimatedEmoji: @escaping (Bool) -> Void, togglePackSelected: @escaping (EngineItemCollectionId) -> Void, toggleLargeEmoji: @escaping (Bool) -> Void, toggleDynamicPackOrder: @escaping (Bool) -> Void, addPack: @escaping (StickerPackCollectionInfo) -> Void) { self.context = context self.openStickerPack = openStickerPack self.setPackIdWithRevealedOptions = setPackIdWithRevealedOptions @@ -84,7 +83,7 @@ public enum InstalledStickerPacksEntryTag: ItemListItemTag { private enum InstalledStickerPacksEntryId: Hashable { case index(Int32) - case pack(ItemCollectionId) + case pack(EngineItemCollectionId) } private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry { @@ -457,18 +456,18 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry { private struct InstalledStickerPacksControllerState: Equatable { let editing: Bool - let selectedPackIds: Set? - let packIdWithRevealedOptions: ItemCollectionId? + let selectedPackIds: Set? + let packIdWithRevealedOptions: EngineItemCollectionId? let trendingPacksExpanded: Bool - + init() { self.editing = false self.selectedPackIds = nil self.packIdWithRevealedOptions = nil self.trendingPacksExpanded = false } - - init(editing: Bool, selectedPackIds: Set?, packIdWithRevealedOptions: ItemCollectionId?, trendingPacksExpanded: Bool) { + + init(editing: Bool, selectedPackIds: Set?, packIdWithRevealedOptions: EngineItemCollectionId?, trendingPacksExpanded: Bool) { self.editing = editing self.selectedPackIds = selectedPackIds self.packIdWithRevealedOptions = packIdWithRevealedOptions @@ -495,11 +494,11 @@ private struct InstalledStickerPacksControllerState: Equatable { return InstalledStickerPacksControllerState(editing: editing, selectedPackIds: self.selectedPackIds, packIdWithRevealedOptions: self.packIdWithRevealedOptions, trendingPacksExpanded: self.trendingPacksExpanded) } - func withUpdatedSelectedPackIds(_ selectedPackIds: Set?) -> InstalledStickerPacksControllerState { + func withUpdatedSelectedPackIds(_ selectedPackIds: Set?) -> InstalledStickerPacksControllerState { return InstalledStickerPacksControllerState(editing: editing, selectedPackIds: selectedPackIds, packIdWithRevealedOptions: self.packIdWithRevealedOptions, trendingPacksExpanded: self.trendingPacksExpanded) } - - func withUpdatedPackIdWithRevealedOptions(_ packIdWithRevealedOptions: ItemCollectionId?) -> InstalledStickerPacksControllerState { + + func withUpdatedPackIdWithRevealedOptions(_ packIdWithRevealedOptions: EngineItemCollectionId?) -> InstalledStickerPacksControllerState { return InstalledStickerPacksControllerState(editing: self.editing, selectedPackIds: self.selectedPackIds, packIdWithRevealedOptions: packIdWithRevealedOptions, trendingPacksExpanded: self.trendingPacksExpanded) } @@ -508,7 +507,7 @@ private struct InstalledStickerPacksControllerState: Equatable { } } -private func namespaceForMode(_ mode: InstalledStickerPacksControllerMode) -> ItemCollectionId.Namespace { +private func namespaceForMode(_ mode: InstalledStickerPacksControllerMode) -> EngineItemCollectionId.Namespace { switch mode { case .general, .modal: return Namespaces.ItemCollection.CloudStickerPacks @@ -521,18 +520,16 @@ private func namespaceForMode(_ mode: InstalledStickerPacksControllerMode) -> It private let maxTrendingPacksDisplayedLimit: Int32 = 3 -private func installedStickerPacksControllerEntries(context: AccountContext, presentationData: PresentationData, state: InstalledStickerPacksControllerState, mode: InstalledStickerPacksControllerMode, view: CombinedView, temporaryPackOrder: [ItemCollectionId]?, featured: [FeaturedStickerPackItem], archived: [ArchivedStickerPackItem]?, stickerSettings: StickerSettings, quickReaction: MessageReaction.Reaction?, availableReactions: AvailableReactions?, emojiCount: Int32) -> [InstalledStickerPacksEntry] { +private func installedStickerPacksControllerEntries(context: AccountContext, presentationData: PresentationData, state: InstalledStickerPacksControllerState, mode: InstalledStickerPacksControllerMode, view: [EngineRawItemCollectionInfoEntry], temporaryPackOrder: [EngineItemCollectionId]?, featured: [FeaturedStickerPackItem], archived: [ArchivedStickerPackItem]?, stickerSettings: StickerSettings, quickReaction: MessageReaction.Reaction?, availableReactions: AvailableReactions?, emojiCount: Int32) -> [InstalledStickerPacksEntry] { var entries: [InstalledStickerPacksEntry] = [] - - var installedPacks = Set() - if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespaceForMode(mode)])] as? ItemCollectionInfosView { - if let packsEntries = stickerPacksView.entriesByNamespace[namespaceForMode(mode)] { - var sortedPacks: [ItemCollectionInfoEntry] = [] - for entry in packsEntries { - if let _ = entry.info as? StickerPackCollectionInfo { - installedPacks.insert(entry.id) - sortedPacks.append(entry) - } + + var installedPacks = Set() + do { + var sortedPacks: [EngineRawItemCollectionInfoEntry] = [] + for entry in view { + if let _ = entry.info as? StickerPackCollectionInfo { + installedPacks.insert(entry.id) + sortedPacks.append(entry) } } } @@ -580,45 +577,43 @@ private func installedStickerPacksControllerEntries(context: AccountContext, pre entries.append(.suggestAnimatedEmojiInfo(presentationData.theme, presentationData.strings.StickerPacksSettings_SuggestAnimatedEmojiInfo)) } - if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespaceForMode(mode)])] as? ItemCollectionInfosView { - if let packsEntries = stickerPacksView.entriesByNamespace[namespaceForMode(mode)] { - var sortedPacks: [ItemCollectionInfoEntry] = [] - for entry in packsEntries { - if let _ = entry.info as? StickerPackCollectionInfo { - sortedPacks.append(entry) + do { + var sortedPacks: [EngineRawItemCollectionInfoEntry] = [] + for entry in view { + if let _ = entry.info as? StickerPackCollectionInfo { + sortedPacks.append(entry) + } + } + if let temporaryPackOrder = temporaryPackOrder { + var packDict: [EngineItemCollectionId: Int] = [:] + for i in 0 ..< sortedPacks.count { + packDict[sortedPacks[i].id] = i + } + var tempSortedPacks: [EngineRawItemCollectionInfoEntry] = [] + var processedPacks = Set() + for id in temporaryPackOrder { + if let index = packDict[id] { + tempSortedPacks.append(sortedPacks[index]) + processedPacks.insert(id) } } - if let temporaryPackOrder = temporaryPackOrder { - var packDict: [ItemCollectionId: Int] = [:] - for i in 0 ..< sortedPacks.count { - packDict[sortedPacks[i].id] = i - } - var tempSortedPacks: [ItemCollectionInfoEntry] = [] - var processedPacks = Set() - for id in temporaryPackOrder { - if let index = packDict[id] { - tempSortedPacks.append(sortedPacks[index]) - processedPacks.insert(id) - } - } - let restPacks = sortedPacks.filter { !processedPacks.contains($0.id) } - sortedPacks = restPacks + tempSortedPacks - } - var index: Int32 = 0 - for entry in sortedPacks { - if let info = entry.info as? StickerPackCollectionInfo { - let countTitle: String - if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { - countTitle = presentationData.strings.StickerPack_EmojiCount(info.count == 0 ? entry.count : info.count) - } else if info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { - countTitle = presentationData.strings.StickerPack_MaskCount(info.count == 0 ? entry.count : info.count) - } else { - countTitle = presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count) - } - - entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, countTitle, context.sharedContext.energyUsageSettings.loopStickers, true, ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == entry.id, reorderable: true, selectable: true), state.selectedPackIds?.contains(info.id))) - index += 1 + let restPacks = sortedPacks.filter { !processedPacks.contains($0.id) } + sortedPacks = restPacks + tempSortedPacks + } + var index: Int32 = 0 + for entry in sortedPacks { + if let info = entry.info as? StickerPackCollectionInfo { + let countTitle: String + if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + countTitle = presentationData.strings.StickerPack_EmojiCount(info.count == 0 ? entry.count : info.count) + } else if info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + countTitle = presentationData.strings.StickerPack_MaskCount(info.count == 0 ? entry.count : info.count) + } else { + countTitle = presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count) } + + entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, countTitle, context.sharedContext.energyUsageSettings.loopStickers, true, ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == entry.id, reorderable: true, selectable: true), state.selectedPackIds?.contains(info.id))) + index += 1 } } } @@ -668,7 +663,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)? var pushControllerImpl: ((ViewController) -> Void)? - var navigateToChatControllerImpl: ((PeerId) -> Void)? + var navigateToChatControllerImpl: ((EnginePeer.Id) -> Void)? var dismissImpl: (() -> Void)? let actionsDisposable = DisposableSet() @@ -874,9 +869,9 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta return .complete() } |> deliverOnMainQueue).start() }) - let stickerPacks = Promise() - stickerPacks.set(context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [namespaceForMode(mode)])])) - let temporaryPackOrder = Promise<[ItemCollectionId]?>(nil) + let stickerPacks = Promise<[EngineRawItemCollectionInfoEntry]>() + stickerPacks.set(context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCollections.InstalledPackInfos(namespace: namespaceForMode(mode)))) + let temporaryPackOrder = Promise<[EngineItemCollectionId]?>(nil) let featured = Promise<[FeaturedStickerPackItem]>() let quickReaction: Signal @@ -904,14 +899,11 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta return reactionSettings.effectiveQuickReaction(hasPremium: hasPremium) } |> distinctUntilChanged - emojiCount.set(context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudEmojiPacks])]) - |> map { view in - if let info = view.views[.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudEmojiPacks])] as? ItemCollectionInfosView, let entries = info.entriesByNamespace[Namespaces.ItemCollection.CloudEmojiPacks] { - return Int32(entries.count) - } else { - return 0 - } - }) + emojiCount.set(context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCollections.InstalledPackInfos(namespace: Namespaces.ItemCollection.CloudEmojiPacks)) + |> map { entries in + return Int32(entries.count) + }) + case .masks: featured.set(.single([])) archivedPromise.set(.single(nil) |> then(context.engine.stickers.archivedStickerPacks(namespace: .masks) |> map(Optional.init))) @@ -948,10 +940,10 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta } var packCount: Int? = nil - var stickerPacks: [ItemCollectionInfoEntry] = [] - if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespaceForMode(mode)])] as? ItemCollectionInfosView, let entries = stickerPacksView.entriesByNamespace[namespaceForMode(mode)] { - packCount = entries.count - stickerPacks = entries + var stickerPacks: [EngineRawItemCollectionInfoEntry] = [] + do { + packCount = view.count + stickerPacks = view } let leftNavigationButton: ItemListNavigationButton? = nil @@ -998,7 +990,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta } } - var packIds: [ItemCollectionId] = [] + var packIds: [EngineItemCollectionId] = [] for entry in stickerPacks { if let selectedPackIds = state.selectedPackIds, selectedPackIds.contains(entry.id) { packIds.append(entry.id) @@ -1029,7 +1021,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta } } - var packIds: [ItemCollectionId] = [] + var packIds: [EngineItemCollectionId] = [] for entry in stickerPacks { if let selectedPackIds = state.selectedPackIds, selectedPackIds.contains(entry.id) { packIds.append(entry.id) @@ -1112,7 +1104,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta guard case let .pack(_, _, _, fromPackInfo, _, _, _, _, _, _) = fromEntry else { return .single(false) } - var referenceId: ItemCollectionId? + var referenceId: EngineItemCollectionId? var beforeAll = false var afterAll = false if toIndex < entries.count { @@ -1130,7 +1122,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta afterAll = true } - var currentIds: [ItemCollectionId] = [] + var currentIds: [EngineItemCollectionId] = [] for entry in entries { switch entry { case let .pack(_, _, _, info, _, _, _, _, _, _): @@ -1184,7 +1176,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta }) controller.setReorderCompleted({ (entries: [InstalledStickerPacksEntry]) -> Void in - var currentIds: [ItemCollectionId] = [] + var currentIds: [EngineItemCollectionId] = [] for entry in entries { switch entry { case let .pack(_, _, _, info, _, _, _, _, _, _): @@ -1224,10 +1216,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta presentStickerPackController = { [weak controller] info in let _ = (stickerPacks.get() |> take(1) - |> deliverOnMainQueue).start(next: { view in - guard let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespaceForMode(mode)])] as? ItemCollectionInfosView, let entries = stickerPacksView.entriesByNamespace[namespaceForMode(mode)] else { - return - } + |> deliverOnMainQueue).start(next: { entries in var mainStickerPack: StickerPackReference? var packs: [StickerPackReference] = [] for entry in entries { diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift index 631148e302..6c86563d64 100644 --- a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift @@ -4,7 +4,6 @@ import Display import SwiftSignalKit import AsyncDisplayKit import TelegramCore -import Postbox import TelegramPresentationData import TelegramUIPreferences import AccountContext @@ -268,7 +267,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, ASScrollView context: self.context, chatListLocation: .chatList(groupId: .root), filterData: nil, - index: .chatList(ChatListIndex(pinningIndex: isPinned ? 0 : nil, messageIndex: MessageIndex(id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), timestamp: timestamp))), + index: .chatList(EngineChatListIndex(pinningIndex: isPinned ? 0 : nil, messageIndex: EngineMessage.Index(id: EngineMessage.Id(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), timestamp: timestamp))), content: .peer(ChatListItemContent.PeerData( messages: [ EngineMessage( @@ -334,13 +333,13 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, ASScrollView } let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)) - let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer5: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)) - let peer6: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer2: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer3: EnginePeer = .channel(TelegramChannel(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudChannel, id: EnginePeer.Id.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)) + let peer3Author: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer4: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer5: EnginePeer = .channel(TelegramChannel(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudChannel, id: EnginePeer.Id.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)) + let peer6: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.SecretChat, id: EnginePeer.Id.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) let timestamp = self.referenceTimestamp @@ -452,30 +451,30 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, ASScrollView let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) var items: [ListViewItem] = [] - let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) + let peerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)) let otherPeerId = self.context.account.peerId - var peers = SimpleDictionary() - var messages = SimpleDictionary() + var peers = EngineSimpleDictionary() + var messages = EngineSimpleDictionary() peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) - let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) - messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let replyMessageId = EngineMessage.Id(peerId: peerId, namespace: 0, id: 3) + messages[replyMessageId] = EngineRawMessage(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: EngineSimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) - let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message1 = EngineRawMessage(stableId: 4, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) - let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message2 = EngineRawMessage(stableId: 3, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA=" let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)] - let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes, alternativeRepresentations: []) + let voiceMedia = TelegramMediaFile(fileId: EngineMedia.Id(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes, alternativeRepresentations: []) - let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message3 = EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) - let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message4 = EngineRawMessage(stableId: 2, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message4], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) let width: CGFloat diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift index bd2b74b03d..ff77efe3b5 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import Display -import Postbox import SwiftSignalKit import AsyncDisplayKit import TelegramCore @@ -400,7 +399,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, ASScrollViewDelegate { context: self.context, chatListLocation: .chatList(groupId: .root), filterData: nil, - index: .chatList(ChatListIndex(pinningIndex: isPinned ? 0 : nil, messageIndex: MessageIndex(id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), timestamp: timestamp))), + index: .chatList(EngineChatListIndex(pinningIndex: isPinned ? 0 : nil, messageIndex: EngineMessage.Index(id: EngineMessage.Id(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), timestamp: timestamp))), content: .peer(ChatListItemContent.PeerData( messages: [ EngineMessage( @@ -468,14 +467,14 @@ final class ThemePreviewControllerNode: ASDisplayNode, ASScrollViewDelegate { let chatListPresentationData = ChatListPresentationData(theme: self.previewTheme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true) let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)) - let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer5: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)) - let peer6: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer7: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(6)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer2: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer3: EnginePeer = .channel(TelegramChannel(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudChannel, id: EnginePeer.Id.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)) + let peer3Author: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer4: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer5: EnginePeer = .channel(TelegramChannel(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudChannel, id: EnginePeer.Id.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)) + let peer6: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.SecretChat, id: EnginePeer.Id.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer7: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(6)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) let timestamp = self.referenceTimestamp @@ -592,43 +591,43 @@ final class ThemePreviewControllerNode: ASDisplayNode, ASScrollViewDelegate { let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.previewTheme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) var items: [ListViewItem] = [] - let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) + let peerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)) let otherPeerId = self.context.account.peerId - var peers = SimpleDictionary() - var messages = SimpleDictionary() + var peers = EngineSimpleDictionary() + var messages = EngineSimpleDictionary() peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) - var sampleMessages: [Message] = [] + var sampleMessages: [EngineRawMessage] = [] - let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message1 = EngineRawMessage(stableId:1, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id:1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message1) - let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message2 = EngineRawMessage(stableId:2, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id:2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message2) - let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message3 = EngineRawMessage(stableId:3, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id:3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message3) - let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message4 = EngineRawMessage(stableId:4, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id:4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) messages[message4.id] = message4 sampleMessages.append(message4) - let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message5 = EngineRawMessage(stableId:5, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id:5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) messages[message5.id] = message5 sampleMessages.append(message5) let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA=" let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)] - let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes, alternativeRepresentations: []) + let voiceMedia = TelegramMediaFile(fileId: EngineMedia.Id(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes, alternativeRepresentations: []) - let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message6 = EngineRawMessage(stableId:6, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id:6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message6) - let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message7 = EngineRawMessage(stableId:7, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id:7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message7) - let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message8 = EngineRawMessage(stableId:8, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id:8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message8) items = sampleMessages.reversed().map { message in diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index e96aed13d8..58e3acebfc 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -4,7 +4,6 @@ import Display import AsyncDisplayKit import SwiftSignalKit import TelegramCore -import Postbox import TelegramPresentationData import TelegramUIPreferences import ItemListUI @@ -156,20 +155,20 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { let insets: UIEdgeInsets let separatorHeight = UIScreenPixel - let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) - let otherPeerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)) + let peerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)) + let otherPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(2)) var items: [ListViewItem] = [] for messageItem in item.messageItems.reversed() { - var peers = SimpleDictionary() - var messages = SimpleDictionary() + var peers = EngineSimpleDictionary() + var messages = EngineSimpleDictionary() - let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) + let replyMessageId = EngineMessage.Id(peerId: peerId, namespace: 0, id: 3) if let (author, text) = messageItem.reply { peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: author, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: messageItem.nameColor, backgroundEmojiId: messageItem.backgroundEmojiId, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) - messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + messages[replyMessageId] = EngineRawMessage(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: EngineSimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) } - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message = EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) } diff --git a/submodules/SettingsUI/Sources/UsernameSetupController.swift b/submodules/SettingsUI/Sources/UsernameSetupController.swift index 24f5af80ab..97434becf5 100644 --- a/submodules/SettingsUI/Sources/UsernameSetupController.swift +++ b/submodules/SettingsUI/Sources/UsernameSetupController.swift @@ -10,18 +10,15 @@ import AccountContext import UndoUI import InviteLinksUI import TextFormat -import Postbox private final class UsernameSetupControllerArguments { - let account: Account let updatePublicLinkText: (String?, String) -> Void let shareLink: () -> Void let activateLink: (String) -> Void let deactivateLink: (String) -> Void let openAuction: (String) -> Void - - init(account: Account, updatePublicLinkText: @escaping (String?, String) -> Void, shareLink: @escaping () -> Void, activateLink: @escaping (String) -> Void, deactivateLink: @escaping (String) -> Void, openAuction: @escaping (String) -> Void) { - self.account = account + + init(updatePublicLinkText: @escaping (String?, String) -> Void, shareLink: @escaping () -> Void, activateLink: @escaping (String) -> Void, deactivateLink: @escaping (String) -> Void, openAuction: @escaping (String) -> Void) { self.updatePublicLinkText = updatePublicLinkText self.shareLink = shareLink self.activateLink = activateLink @@ -291,10 +288,10 @@ private struct UsernameSetupControllerState: Equatable { } } -private func usernameSetupControllerEntries(presentationData: PresentationData, view: PeerView, state: UsernameSetupControllerState, temporaryOrder: [String]?, mode: UsernameSetupMode) -> [UsernameSetupEntry] { +private func usernameSetupControllerEntries(presentationData: PresentationData, peer: EnginePeer?, state: UsernameSetupControllerState, temporaryOrder: [String]?, mode: UsernameSetupMode) -> [UsernameSetupEntry] { var entries: [UsernameSetupEntry] = [] - - if let peer = view.peers[view.peerId] as? TelegramUser { + + if case let .user(peer) = peer { let currentUsername: String if let current = state.editingPublicLinkText { currentUsername = current @@ -444,7 +441,7 @@ public func usernameSetupController(context: AccountContext, mode: UsernameSetup peerId = botPeerId } - let arguments = UsernameSetupControllerArguments(account: context.account, updatePublicLinkText: { currentText, text in + let arguments = UsernameSetupControllerArguments(updatePublicLinkText: { currentText, text in if text.isEmpty { checkAddressNameDisposable.set(nil) updateState { state in @@ -544,20 +541,18 @@ public func usernameSetupController(context: AccountContext, mode: UsernameSetup let temporaryOrder = Promise<[String]?>(nil) - let peerView = context.account.viewTracker.peerView(peerId) + let peerSignal = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) |> deliverOnMainQueue - + let signal = combineLatest( context.sharedContext.presentationData, statePromise.get() |> deliverOnMainQueue, - peerView, + peerSignal, temporaryOrder.get() ) - |> map { presentationData, state, view, temporaryOrder -> (ItemListControllerState, (ItemListNodeState, Any)) in - let peer = peerViewMainPeer(view) - + |> map { presentationData, state, peer, temporaryOrder -> (ItemListControllerState, (ItemListNodeState, Any)) in var rightNavigationButton: ItemListNavigationButton? - if let peer = peer as? TelegramUser { + if case let .user(peer) = peer { var doneEnabled = true if let addressNameValidationStatus = state.addressNameValidationStatus { @@ -613,7 +608,7 @@ public func usernameSetupController(context: AccountContext, mode: UsernameSetup title = presentationData.strings.Username_Title } let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: usernameSetupControllerEntries(presentationData: presentationData, view: view, state: state, temporaryOrder: temporaryOrder, mode: mode), style: .blocks, focusItemTag: mode == .account ? UsernameEntryTag.username : nil, animateChanges: true) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: usernameSetupControllerEntries(presentationData: presentationData, peer: peer, state: state, temporaryOrder: temporaryOrder, mode: mode), style: .blocks, focusItemTag: mode == .account ? UsernameEntryTag.username : nil, animateChanges: true) return (controllerState, (listState, arguments)) } |> afterDisposed { diff --git a/submodules/ShareController/Sources/ShareControllerNode.swift b/submodules/ShareController/Sources/ShareControllerNode.swift index 043a07e64e..492089f2e9 100644 --- a/submodules/ShareController/Sources/ShareControllerNode.swift +++ b/submodules/ShareController/Sources/ShareControllerNode.swift @@ -1497,7 +1497,7 @@ final class ShareControllerNode: ViewControllerTracingNode, ASScrollViewDelegate if fromForeignApp, case let .preparing(long) = status, !transitioned { transitioned = true if long { - strongSelf.transitionToContentNode(ShareProlongedLoadingContainerNode(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, forceNativeAppearance: true, postbox: strongSelf.context?.stateManager.postbox, environment: strongSelf.environment), fastOut: true) + strongSelf.transitionToContentNode(ShareProlongedLoadingContainerNode(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, forceNativeAppearance: true, environment: strongSelf.environment), fastOut: true) } else { strongSelf.transitionToContentNode(ShareLoadingContainerNode(theme: strongSelf.presentationData.theme, forceNativeAppearance: true), fastOut: true) } @@ -1880,7 +1880,7 @@ final class ShareControllerNode: ViewControllerTracingNode, ASScrollViewDelegate transition.updateAlpha(node: startAtTimestampNode, alpha: 0.0) } - self.transitionToContentNode(ShareProlongedLoadingContainerNode(theme: self.presentationData.theme, strings: self.presentationData.strings, forceNativeAppearance: true, postbox: self.context?.stateManager.postbox, environment: self.environment), fastOut: true) + self.transitionToContentNode(ShareProlongedLoadingContainerNode(theme: self.presentationData.theme, strings: self.presentationData.strings, forceNativeAppearance: true, environment: self.environment), fastOut: true) let timestamp = CACurrentMediaTime() self.shareDisposable.set(signal.start(completed: { [weak self] in let minDelay = 0.6 diff --git a/submodules/ShareController/Sources/ShareLoadingContainerNode.swift b/submodules/ShareController/Sources/ShareLoadingContainerNode.swift index e6bd8fd778..06ef0c4c47 100644 --- a/submodules/ShareController/Sources/ShareLoadingContainerNode.swift +++ b/submodules/ShareController/Sources/ShareLoadingContainerNode.swift @@ -11,7 +11,6 @@ import TelegramAnimatedStickerNode import AppBundle import TelegramUniversalVideoContent import TelegramCore -import Postbox import AccountContext private func fileSize(_ path: String, useTotalFileAllocatedSize: Bool = false) -> Int64? { @@ -235,7 +234,7 @@ public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareConte return self.elapsedTime + 3.0 + 0.15 } - public init(theme: PresentationTheme, strings: PresentationStrings, forceNativeAppearance: Bool, postbox: Postbox?, environment: ShareControllerEnvironment) { + public init(theme: PresentationTheme, strings: PresentationStrings, forceNativeAppearance: Bool, environment: ShareControllerEnvironment) { self.theme = theme self.strings = strings @@ -276,8 +275,7 @@ public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareConte } })) - if let postbox, let mediaManager = environment.mediaManager, let path = getAppBundle().path(forResource: "BlankVideo", ofType: "m4v"), let size = fileSize(path) { - let _ = postbox + if let mediaManager = environment.mediaManager, let path = getAppBundle().path(forResource: "BlankVideo", ofType: "m4v"), let size = fileSize(path) { let _ = mediaManager let decoration = ChatBubbleVideoDecoration(corners: ImageCorners(), nativeSize: CGSize(width: 100.0, height: 100.0), contentMode: .aspectFit, backgroundColor: .black) diff --git a/submodules/StatisticsUI/Sources/StatsMessageItem.swift b/submodules/StatisticsUI/Sources/StatsMessageItem.swift index 2751c95efd..b3aee6ff57 100644 --- a/submodules/StatisticsUI/Sources/StatsMessageItem.swift +++ b/submodules/StatisticsUI/Sources/StatsMessageItem.swift @@ -4,7 +4,6 @@ import Display import AsyncDisplayKit import ComponentFlow import SwiftSignalKit -import Postbox import TelegramCore import AccountContext import TelegramPresentationData @@ -124,7 +123,7 @@ final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode { private let activateArea: AccessibilityAreaNode private var item: StatsMessageItem? - private var contentImageMedia: Media? + private var contentImageMedia: EngineRawMedia? override public var canBeSelected: Bool { return true @@ -307,7 +306,7 @@ final class StatsMessageItemNode: ListViewItemNode, ItemListItemNode { let presentationData = item.context.sharedContext.currentPresentationData.with { $0 } var text: String - var contentImageMedia: Media? + var contentImageMedia: EngineRawMedia? let timestamp: Int32 switch item.item { diff --git a/submodules/TelegramCallsUI/Sources/CallController.swift b/submodules/TelegramCallsUI/Sources/CallController.swift index a830950e41..58b4bd3d1a 100644 --- a/submodules/TelegramCallsUI/Sources/CallController.swift +++ b/submodules/TelegramCallsUI/Sources/CallController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import AsyncDisplayKit -import Postbox import TelegramCore import SwiftSignalKit import TelegramPresentationData @@ -357,19 +356,19 @@ public final class CallController: ViewController { self.superDismiss() } - let callPeerView: Signal - callPeerView = self.account.postbox.peerView(id: self.call.peerId) |> map(Optional.init) - + let callPeerView: Signal + callPeerView = TelegramEngine(account: self.account).data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: self.call.peerId)) + self.peerDisposable = (combineLatest(queue: .mainQueue(), - self.account.postbox.peerView(id: self.account.peerId) |> take(1), + TelegramEngine(account: self.account).data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: self.account.peerId)) |> take(1), callPeerView, self.sharedContext.activeAccountsWithInfo |> take(1) ) |> deliverOnMainQueue).start(next: { [weak self] accountView, view, activeAccountsWithInfo in if let strongSelf = self { if let view { - if let accountPeer = accountView.peers[accountView.peerId], let peer = view.peers[view.peerId] { - strongSelf.controllerNode.updatePeer(accountPeer: EnginePeer(accountPeer), peer: EnginePeer(peer), hasOther: activeAccountsWithInfo.accounts.count > 1) + if let accountPeer = accountView { + strongSelf.controllerNode.updatePeer(accountPeer: accountPeer, peer: view, hasOther: activeAccountsWithInfo.accounts.count > 1) strongSelf.isDataReady.set(.single(true)) } } else { diff --git a/submodules/TelegramCallsUI/Sources/CallStatusBarNode.swift b/submodules/TelegramCallsUI/Sources/CallStatusBarNode.swift index 050decd464..0e65484512 100644 --- a/submodules/TelegramCallsUI/Sources/CallStatusBarNode.swift +++ b/submodules/TelegramCallsUI/Sources/CallStatusBarNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -368,9 +367,9 @@ public class CallStatusBarNodeImpl: CallStatusBarNode { strongSelf.update() } })) - let callPeerView: Signal + let callPeerView: Signal if let peerId = call.peerId { - callPeerView = account.postbox.peerView(id: peerId) |> map(Optional.init) + callPeerView = TelegramEngine(account: account).data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) } else { callPeerView = .single(nil) } @@ -384,7 +383,7 @@ public class CallStatusBarNodeImpl: CallStatusBarNode { |> deliverOnMainQueue).start(next: { [weak self] view, state, isMuted, members in if let strongSelf = self { if let view { - strongSelf.currentPeer = view.peers[view.peerId].flatMap(EnginePeer.init) + strongSelf.currentPeer = view } else { strongSelf.currentPeer = nil } @@ -429,14 +428,14 @@ public class CallStatusBarNodeImpl: CallStatusBarNode { var effectiveLevel: Float = 0.0 var audioLevels = audioLevels if !strongSelf.currentIsMuted { - audioLevels.append((PeerId(0), 0, myAudioLevel, true)) + audioLevels.append((EnginePeer.Id(0), 0, myAudioLevel, true)) } effectiveLevel = audioLevels.map { $0.2 }.max() ?? 0.0 strongSelf.backgroundNode.audioLevel = effectiveLevel })) if let groupCall = call as? PresentationGroupCallImpl { - let _ = (allowedStoryReactions(account: account) + let _ = (allowedStoryReactions(engine: TelegramEngine(account: account)) |> deliverOnMainQueue).start(next: { [weak self] reactionItems in self?.reactionItems = reactionItems }) @@ -479,19 +478,19 @@ public class CallStatusBarNodeImpl: CallStatusBarNode { membersCount = 1 } - var speakingPeer: Peer? + var speakingPeer: EnginePeer? if let members = currentMembers { - var speakingPeers: [Peer] = [] + var speakingPeers: [EnginePeer] = [] for member in members.participants { if let memberPeer = member.peer, members.speakingParticipants.contains(memberPeer.id) { - speakingPeers.append(memberPeer._asPeer()) + speakingPeers.append(memberPeer) } } speakingPeer = speakingPeers.first } - + if let speakingPeer = speakingPeer { - speakerSubtitle = EnginePeer(speakingPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + speakerSubtitle = speakingPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) } displaySpeakerSubtitle = speakerSubtitle != title && !speakerSubtitle.isEmpty diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index 501ee547dd..cb51d94260 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -1497,7 +1497,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { if let peerId { if peerId.namespace == Namespaces.Peer.CloudChannel { rawAdminIds = Signal { subscriber in - let (disposable, _) = accountContext.peerChannelMemberCategoriesContextsManager.admins(engine: accountContext.engine, postbox: accountContext.account.postbox, network: accountContext.account.network, accountPeerId: accountContext.account.peerId, peerId: peerId, updated: { list in + let (disposable, _) = accountContext.peerChannelMemberCategoriesContextsManager.admins(engine: accountContext.engine, accountPeerId: accountContext.account.peerId, peerId: peerId, updated: { list in var peerIds = Set() for item in list.list { if let adminInfo = item.participant.adminInfo, adminInfo.rights.rights.contains(.canManageCalls) { @@ -1982,7 +1982,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { return EmptyDisposable } - let (disposable, _) = self.accountContext.peerChannelMemberCategoriesContextsManager.admins(engine: self.accountContext.engine, postbox: self.accountContext.account.postbox, network: self.accountContext.account.network, accountPeerId: self.accountContext.account.peerId, peerId: peerId, updated: { list in + let (disposable, _) = self.accountContext.peerChannelMemberCategoriesContextsManager.admins(engine: self.accountContext.engine, accountPeerId: self.accountContext.account.peerId, peerId: peerId, updated: { list in var peerIds = Set() for item in list.list { if let adminInfo = item.participant.adminInfo, adminInfo.rights.rights.contains(.canManageCalls) { @@ -2326,7 +2326,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { if let peerId = peerId ?? self.streamPeerId { if peerId.namespace == Namespaces.Peer.CloudChannel { rawAdminIds = Signal { subscriber in - let (disposable, _) = accountContext.peerChannelMemberCategoriesContextsManager.admins(engine: accountContext.engine, postbox: accountContext.account.postbox, network: accountContext.account.network, accountPeerId: accountContext.account.peerId, peerId: peerId, updated: { list in + let (disposable, _) = accountContext.peerChannelMemberCategoriesContextsManager.admins(engine: accountContext.engine, accountPeerId: accountContext.account.peerId, peerId: peerId, updated: { list in var peerIds = Set() for item in list.list { if let adminInfo = item.participant.adminInfo, adminInfo.rights.rights.contains(.canManageCalls) { diff --git a/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift b/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift index 7cc99459e5..ef8217b3cb 100644 --- a/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift +++ b/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift @@ -5,7 +5,6 @@ import AsyncDisplayKit import Display import ComponentFlow import ViewControllerComponent -import Postbox import TelegramCore import AccountContext import PlainButtonComponent @@ -1419,7 +1418,7 @@ final class VideoChatScreenComponent: Component { ) self.inputMediaInteraction?.forceTheme = defaultDarkColorPresentationTheme - let _ = (allowedStoryReactions(account: context.account) + let _ = (allowedStoryReactions(engine: context.engine) |> deliverOnMainQueue).start(next: { [weak self] reactionItems in self?.reactionItems = reactionItems }) @@ -4269,20 +4268,16 @@ private func hasFirstResponder(_ view: UIView) -> Bool { return false } -func allowedStoryReactions(account: Account) -> Signal<[ReactionItem], NoError> { - let viewKey: PostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudTopReactions) - let topReactions = account.postbox.combinedView(keys: [viewKey]) - |> map { views -> [RecentReactionItem] in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return [] - } - return view.items.compactMap { item -> RecentReactionItem? in +func allowedStoryReactions(engine: TelegramEngine) -> Signal<[ReactionItem], NoError> { + let topReactions = engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudTopReactions)) + |> map { items -> [RecentReactionItem] in + return items.compactMap { item -> RecentReactionItem? in return item.contents.get(RecentReactionItem.self) } } return combineLatest( - TelegramEngine(account: account).stickers.availableReactions(), + engine.stickers.availableReactions(), topReactions ) |> take(1) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/OrderedListsData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/OrderedListsData.swift index 84ee94709c..e9bb29c45e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/OrderedListsData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/OrderedListsData.swift @@ -66,4 +66,48 @@ public extension TelegramEngine.EngineData.Item { } } } + + enum ItemCollections { + public struct InstalledPackInfos: TelegramEngineDataItem, PostboxViewDataItem { + public typealias Result = [EngineRawItemCollectionInfoEntry] + + private let namespace: ItemCollectionId.Namespace + + public init(namespace: ItemCollectionId.Namespace) { + self.namespace = namespace + } + + var key: PostboxViewKey { + return .itemCollectionInfos(namespaces: [self.namespace]) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? ItemCollectionInfosView else { + preconditionFailure() + } + return view.entriesByNamespace[self.namespace] ?? [] + } + } + + public struct InstalledPackIds: TelegramEngineDataItem, PostboxViewDataItem { + public typealias Result = [ItemCollectionId] + + private let namespace: ItemCollectionId.Namespace + + public init(namespace: ItemCollectionId.Namespace) { + self.namespace = namespace + } + + var key: PostboxViewKey { + return .itemCollectionIds(namespaces: [self.namespace]) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? ItemCollectionIdsView else { + preconditionFailure() + } + return Array(view.idsByNamespace[self.namespace] ?? []) + } + } + } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift index 0cfb3c20bc..dd447e85b7 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift @@ -310,6 +310,30 @@ public extension TelegramEngine.EngineData.Item { } } + public struct CachedData: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { + public typealias Result = Optional + + fileprivate var id: EnginePeer.Id + public var mapKey: EnginePeer.Id { + return self.id + } + + public init(id: EnginePeer.Id) { + self.id = id + } + + var key: PostboxViewKey { + return .cachedPeerData(peerId: self.id) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? CachedPeerDataView else { + preconditionFailure() + } + return view.cachedPeerData + } + } + public struct ParticipantCount: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { public typealias Result = Optional diff --git a/submodules/TelegramCore/Sources/TelegramEngine/ItemCollections/TelegramEngineItemCollections.swift b/submodules/TelegramCore/Sources/TelegramEngine/ItemCollections/TelegramEngineItemCollections.swift new file mode 100644 index 0000000000..bcf815f141 --- /dev/null +++ b/submodules/TelegramCore/Sources/TelegramEngine/ItemCollections/TelegramEngineItemCollections.swift @@ -0,0 +1,20 @@ +import Foundation +import SwiftSignalKit +import Postbox + +public extension TelegramEngine { + final class ItemCollections { + private let account: Account + + init(account: Account) { + self.account = account + } + + public func allItems(namespace: ItemCollectionId.Namespace) -> Signal<[EngineRawItemCollectionItem], NoError> { + return self.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [namespace], aroundIndex: nil, count: 10000000) + |> map { view -> [EngineRawItemCollectionItem] in + return view.entries.map { $0.item } + } + } + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift index 5b186894b5..5f27b85d41 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift @@ -80,7 +80,11 @@ public final class TelegramEngine { public lazy var orderedLists: OrderedLists = { return OrderedLists(account: self.account) }() - + + public lazy var itemCollections: ItemCollections = { + return ItemCollections(account: self.account) + }() + public lazy var itemCache: ItemCache = { return ItemCache(account: self.account) }() diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Utils/EnginePostboxCoding.swift b/submodules/TelegramCore/Sources/TelegramEngine/Utils/EnginePostboxCoding.swift index 23714d0d0a..22c3243c68 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Utils/EnginePostboxCoding.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Utils/EnginePostboxCoding.swift @@ -32,6 +32,7 @@ public typealias EngineMediaResourceDataFetchError = MediaResourceDataFetchError public typealias EngineMediaResourceStatus = MediaResourceStatus public typealias EnginePostboxCoding = PostboxCoding public typealias EngineRawItemCollectionInfo = ItemCollectionInfo +public typealias EngineRawItemCollectionInfoEntry = ItemCollectionInfoEntry public typealias EngineRawItemCollectionItem = ItemCollectionItem public typealias EngineRawMedia = Media public typealias EngineRawMessage = Message @@ -43,11 +44,43 @@ public typealias EngineRawMediaResourceDataFetchCopyLocalItem = MediaResourceDat public typealias EngineRawCachedMediaResourceRepresentation = CachedMediaResourceRepresentation public typealias EngineCachedMediaRepresentationKeepDuration = CachedMediaRepresentationKeepDuration public typealias EngineCachedPeerData = CachedPeerData +public typealias EngineMessageHistoryThreadData = MessageHistoryThreadData +public typealias EngineViewUpdateType = ViewUpdateType +public typealias EngineRawPeerPresence = PeerPresence +public typealias EnginePeerGroupId = PeerGroupId +public typealias EngineChatLocationInput = ChatLocationInput +public typealias EngineHistoryViewInputTag = HistoryViewInputTag +public typealias EngineInitialMessageHistoryData = InitialMessageHistoryData +public typealias EngineSimpleDictionary = SimpleDictionary +public typealias EngineRawValueBoxKey = ValueBoxKey +public typealias EngineRawMessageHistoryView = MessageHistoryView +public typealias EngineRawPeerView = PeerView +public typealias EngineRawMessageHistoryEntry = MessageHistoryEntry +public typealias EngineRawMutableMessageHistoryEntryAttributes = MutableMessageHistoryEntryAttributes +public typealias EngineMessageHistoryViewReadState = MessageHistoryViewReadState +public typealias EngineMessageIdNamespaces = MessageIdNamespaces +public typealias EngineHistoryViewInputAnchor = HistoryViewInputAnchor +public typealias EngineRawPostboxViewKey = PostboxViewKey +public typealias EngineRawPreferencesView = PreferencesView +public typealias EngineRawOrderedItemListView = OrderedItemListView +public typealias EngineRawUnreadMessageCountsView = UnreadMessageCountsView +public typealias EngineRawMessageHistoryThreadIndexView = MessageHistoryThreadIndexView +public typealias EngineRawCombinedReadStateView = CombinedReadStateView +public typealias EngineRawMessageHistoryThreadInfoView = MessageHistoryThreadInfoView +public typealias EngineRawBasicPeerView = BasicPeerView +public typealias EngineRawCachedPeerDataView = CachedPeerDataView +public typealias EngineRawUnreadMessageCountsItem = UnreadMessageCountsItem +public typealias EngineRawMessageHistorySavedMessagesIndexView = MessageHistorySavedMessagesIndexView +public typealias EngineRawChatInterfaceStateView = ChatInterfaceStateView public func engineFileSize(_ path: String, useTotalFileAllocatedSize: Bool = false) -> Int64? { return fileSize(path, useTotalFileAllocatedSize: useTotalFileAllocatedSize) } +public func engineAreMediaArraysEqual(_ lhs: [EngineRawMedia], _ rhs: [EngineRawMedia]) -> Bool { + return areMediaArraysEqual(lhs, rhs) +} + public func enginePersistentHash32(_ string: String) -> Int32 { return persistentHash32(string) } diff --git a/submodules/TelegramIntents/Sources/TelegramIntents.swift b/submodules/TelegramIntents/Sources/TelegramIntents.swift index f6a782d87c..e4910f5905 100644 --- a/submodules/TelegramIntents/Sources/TelegramIntents.swift +++ b/submodules/TelegramIntents/Sources/TelegramIntents.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Intents import Display -import Postbox import TelegramCore import SwiftSignalKit import TelegramUIPreferences @@ -55,7 +54,7 @@ public enum SendMessageIntentSubject: CaseIterable { } } -public func donateSendMessageIntent(account: Account, sharedContext: SharedAccountContext, intentContext: SendMessageIntentContext, peerIds: [PeerId]) { +public func donateSendMessageIntent(account: Account, sharedContext: SharedAccountContext, intentContext: SendMessageIntentContext, peerIds: [EnginePeer.Id]) { if #available(iOSApplicationExtension 13.2, iOS 13.2, *) { let _ = (sharedContext.accountManager.transaction { transaction -> Bool in if case .none = transaction.getAccessChallengeData() { @@ -64,11 +63,11 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou return false } } - |> mapToSignal { unlocked -> Signal<[(Peer, SendMessageIntentSubject, UIImage?)], NoError> in + |> mapToSignal { unlocked -> Signal<[(EngineRawPeer, SendMessageIntentSubject, UIImage?)], NoError> in if unlocked { return sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.intentsSettings]) |> take(1) - |> mapToSignal { sharedData -> Signal<[(Peer, SendMessageIntentSubject)], NoError> in + |> mapToSignal { sharedData -> Signal<[(EngineRawPeer, SendMessageIntentSubject)], NoError> in let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.intentsSettings]?.get(IntentsSettings.self) ?? IntentsSettings.defaultSettings if let accountId = settings.account, accountId != account.peerId { return .single([]) @@ -82,8 +81,8 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou EngineDataMap(peerIds.map(TelegramEngine.EngineData.Item.Peer.IsContact.init)), EngineDataMap(peerIds.map(TelegramEngine.EngineData.Item.Messages.ChatListGroup.init)) ) - |> map { peerMap, isContactMap, chatListGroupMap -> [(Peer, SendMessageIntentSubject)] in - var peers: [(Peer, SendMessageIntentSubject)] = [] + |> map { peerMap, isContactMap, chatListGroupMap -> [(EngineRawPeer, SendMessageIntentSubject)] in + var peers: [(EngineRawPeer, SendMessageIntentSubject)] = [] for peerId in peerIds { if peerId.namespace != Namespaces.Peer.SecretChat, let maybePeer = peerMap[peerId], let peer = maybePeer { var subject: SendMessageIntentSubject? @@ -134,14 +133,14 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou return peers } } - |> mapToSignal { peers -> Signal<[(Peer, SendMessageIntentSubject, UIImage?)], NoError> in - var signals: [Signal<(Peer, SendMessageIntentSubject, UIImage?), NoError>] = [] + |> mapToSignal { peers -> Signal<[(EngineRawPeer, SendMessageIntentSubject, UIImage?)], NoError> in + var signals: [Signal<(EngineRawPeer, SendMessageIntentSubject, UIImage?), NoError>] = [] for (peer, subject) in peers { if peer.id == account.peerId { signals.append(.single((peer, subject, savedMessagesAvatar))) } else { let peerAndAvatar = (peerAvatarImage(account: account, peerReference: PeerReference(peer), authorOfMessage: nil, representation: peer.smallProfileImage, clipStyle: .none) ?? .single(nil)) - |> map { imageVersions -> (Peer, SendMessageIntentSubject, UIImage?) in + |> map { imageVersions -> (EngineRawPeer, SendMessageIntentSubject, UIImage?) in var avatarImage: UIImage? if let image = imageVersions?.0 { avatarImage = image @@ -214,7 +213,7 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou } } -public func deleteSendMessageIntents(peerId: PeerId) { +public func deleteSendMessageIntents(peerId: EnginePeer.Id) { if #available(iOS 10.0, *) { INInteraction.delete(with: "sendMessage_\(peerId.toInt64())") } diff --git a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift index 2d8cc47b63..23f3df50ec 100644 --- a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift +++ b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileController.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import LegacyComponents import TelegramPresentationData @@ -32,14 +31,14 @@ private final class AttachmentFileControllerArguments { let scanDocument: () -> Void let expandSavedMusic: () -> Void let expandRecentMusic: () -> Void - let send: (Message) -> Void - let toggleMediaPlayback: (Message) -> Void + let send: (EngineRawMessage) -> Void + let toggleMediaPlayback: (EngineRawMessage) -> Void let isSelectionActive: () -> Bool - let toggleMessageSelection: (Message) -> Void - let setMessageSelection: ([MessageId], Message?, Bool) -> Void + let toggleMessageSelection: (EngineRawMessage) -> Void + let setMessageSelection: ([EngineMessage.Id], EngineRawMessage?, Bool) -> Void let openMessageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void) - init(context: AccountContext, isAudio: Bool, isAttach: Bool, openGallery: @escaping () -> Void, openFiles: @escaping () -> Void, scanDocument: @escaping () -> Void, expandSavedMusic: @escaping () -> Void, expandRecentMusic: @escaping () -> Void, send: @escaping (Message) -> Void, toggleMediaPlayback: @escaping (Message) -> Void, isSelectionActive: @escaping () -> Bool, toggleMessageSelection: @escaping (Message) -> Void, setMessageSelection: @escaping ([MessageId], Message?, Bool) -> Void, openMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void)) { + init(context: AccountContext, isAudio: Bool, isAttach: Bool, openGallery: @escaping () -> Void, openFiles: @escaping () -> Void, scanDocument: @escaping () -> Void, expandSavedMusic: @escaping () -> Void, expandRecentMusic: @escaping () -> Void, send: @escaping (EngineRawMessage) -> Void, toggleMediaPlayback: @escaping (EngineRawMessage) -> Void, isSelectionActive: @escaping () -> Bool, toggleMessageSelection: @escaping (EngineRawMessage) -> Void, setMessageSelection: @escaping ([EngineMessage.Id], EngineRawMessage?, Bool) -> Void, openMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void)) { self.context = context self.isAudio = isAudio self.isAttach = isAttach @@ -64,7 +63,7 @@ private enum AttachmentFileSection: Int32 { case global } -private func areMessagesEqual(_ lhsMessage: Message?, _ rhsMessage: Message?) -> Bool { +private func areMessagesEqual(_ lhsMessage: EngineRawMessage?, _ rhsMessage: EngineRawMessage?) -> Bool { guard let lhsMessage = lhsMessage, let rhsMessage = rhsMessage else { return lhsMessage == nil && rhsMessage == nil } @@ -83,15 +82,15 @@ private enum AttachmentFileEntry: ItemListNodeEntry { case scanDocument(PresentationTheme, String) case savedHeader(PresentationTheme, String) - case savedFile(Int32, PresentationTheme, Message?, ChatHistoryMessageSelection) + case savedFile(Int32, PresentationTheme, EngineRawMessage?, ChatHistoryMessageSelection) case savedShowMore(PresentationTheme, String) case recentHeader(PresentationTheme, String) - case recentFile(Int32, PresentationTheme, Message?, ChatHistoryMessageSelection) + case recentFile(Int32, PresentationTheme, EngineRawMessage?, ChatHistoryMessageSelection) case recentShowMore(PresentationTheme, String) case globalHeader(PresentationTheme, String) - case globalFile(Int32, PresentationTheme, Message?, ChatHistoryMessageSelection) + case globalFile(Int32, PresentationTheme, EngineRawMessage?, ChatHistoryMessageSelection) case globalShowMore(PresentationTheme, String) var section: ItemListSectionId { @@ -277,7 +276,7 @@ private enum AttachmentFileEntry: ItemListNodeEntry { let dateTimeFormat = arguments.context.sharedContext.currentPresentationData.with({$0}).dateTimeFormat let chatPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: .color(0)), fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, disableAnimations: false, largeEmoji: false, chatBubbleCorners: PresentationChatBubbleCorners(mainRadius: 0, auxiliaryRadius: 0, mergeBubbleCorners: false)) - return ListMessageItem(presentationData: chatPresentationData, systemStyle: .glass, context: arguments.context, chatLocation: .peer(id: PeerId(0)), interaction: interaction, message: message, selection: selection, displayHeader: false, isDownloadList: arguments.isAudio, isStoryMusic: true, isAttachMusic: arguments.isAttach, displayFileInfo: true, displayBackground: true, style: .blocks, sectionId: self.section) + return ListMessageItem(presentationData: chatPresentationData, systemStyle: .glass, context: arguments.context, chatLocation: .peer(id: EnginePeer.Id(0)), interaction: interaction, message: message, selection: selection, displayHeader: false, isDownloadList: arguments.isAudio, isStoryMusic: true, isAttachMusic: arguments.isAttach, displayFileInfo: true, displayBackground: true, style: .blocks, sectionId: self.section) case let .recentShowMore(theme, text): return ItemListPeerActionItem(presentationData: presentationData, systemStyle: .glass, icon: PresentationResourcesItemList.downArrowImage(theme), title: text, sectionId: self.section, editing: false, action: { arguments.expandRecentMusic() @@ -302,7 +301,7 @@ private enum AttachmentFileEntry: ItemListNodeEntry { let dateTimeFormat = arguments.context.sharedContext.currentPresentationData.with({$0}).dateTimeFormat let chatPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: .color(0)), fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: .firstLast, disableAnimations: false, largeEmoji: false, chatBubbleCorners: PresentationChatBubbleCorners(mainRadius: 0, auxiliaryRadius: 0, mergeBubbleCorners: false)) - return ListMessageItem(presentationData: chatPresentationData, systemStyle: .glass, context: arguments.context, chatLocation: .peer(id: PeerId(0)), interaction: interaction, message: message, selection: selection, displayHeader: false, isDownloadList: arguments.isAudio, isStoryMusic: true, isAttachMusic: arguments.isAttach, displayFileInfo: true, displayBackground: true, style: .blocks, sectionId: self.section) + return ListMessageItem(presentationData: chatPresentationData, systemStyle: .glass, context: arguments.context, chatLocation: .peer(id: EnginePeer.Id(0)), interaction: interaction, message: message, selection: selection, displayHeader: false, isDownloadList: arguments.isAudio, isStoryMusic: true, isAttachMusic: arguments.isAttach, displayFileInfo: true, displayBackground: true, style: .blocks, sectionId: self.section) case let .globalShowMore(theme, text): return ItemListPeerActionItem(presentationData: presentationData, systemStyle: .glass, icon: PresentationResourcesItemList.downArrowImage(theme), title: text, sectionId: self.section, editing: false, action: { @@ -315,8 +314,8 @@ private func attachmentFileControllerEntries( presentationData: PresentationData, mode: AttachmentFileControllerMode, state: AttachmentFileControllerState, - savedMusic: [Message]?, - recentDocuments: [Message]?, + savedMusic: [EngineRawMessage]?, + recentDocuments: [EngineRawMessage]?, hasScan: Bool, empty: Bool ) -> [AttachmentFileEntry] { @@ -513,11 +512,11 @@ private struct AttachmentFileControllerState: Equatable { var searching: Bool var savedMusicExpanded: Bool var recentMusicExpanded: Bool - var selectedMessageIds: [MessageId]? - var messageMap: [MessageId: EngineMessage] + var selectedMessageIds: [EngineMessage.Id]? + var messageMap: [EngineMessage.Id: EngineMessage] } -private func messageSelectionState(state: AttachmentFileControllerState, message: Message?) -> ChatHistoryMessageSelection { +private func messageSelectionState(state: AttachmentFileControllerState, message: EngineRawMessage?) -> ChatHistoryMessageSelection { guard let message, let selectedMessageIds = state.selectedMessageIds else { return .none } @@ -641,7 +640,7 @@ public func makeAttachmentFileControllerImpl( |> `catch` { _ in return .single(.result([])) } - |> mapToSignal { result -> Signal<[Message], NoError> in + |> mapToSignal { result -> Signal<[EngineRawMessage], NoError> in guard case let .result(result) = result else { return .complete() } @@ -739,15 +738,15 @@ public func makeAttachmentFileControllerImpl( } ) - let recentDocuments: Signal<[Message]?, NoError> + let recentDocuments: Signal<[EngineRawMessage]?, NoError> let savedMusicContext: ProfileSavedMusicContext? - let savedMusic: Signal<[Message]?, NoError> + let savedMusic: Signal<[EngineRawMessage]?, NoError> switch mode { case .recent: recentDocuments = .single(nil) |> then( context.engine.messages.searchMessages(location: .sentMedia(tags: [.file]), query: "", state: nil) - |> map { result -> [Message]? in + |> map { result -> [EngineRawMessage]? in return result.0.messages } ) @@ -757,7 +756,7 @@ public func makeAttachmentFileControllerImpl( recentDocuments = .single(nil) |> then( context.engine.messages.searchMessages(location: .general(scope: .everywhere, groupId: nil, tags: [.music], minDate: nil, maxDate: nil, folderId: nil), query: "", state: nil) - |> map { result -> [Message]? in + |> map { result -> [EngineRawMessage]? in return result.0.messages } ) @@ -767,11 +766,11 @@ public func makeAttachmentFileControllerImpl( savedMusicContext!.state |> map { state in let peerId = context.account.peerId - var messages: [Message] = [] - let peers = SimpleDictionary() + var messages: [EngineRawMessage] = [] + let peers = EngineSimpleDictionary() for file in state.files { let stableId = UInt32(clamping: file.fileId.id % Int64(Int32.max)) - messages.append(Message(stableId: stableId, stableVersion: 0, id: MessageId(peerId: peerId, namespace: Namespaces.Message.Local, id: Int32(stableId)), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [.music], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])) + messages.append(EngineRawMessage(stableId: stableId, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: Namespaces.Message.Local, id: Int32(stableId)), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [.music], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file], peers: peers, associatedMessages: EngineSimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])) } return messages } @@ -783,7 +782,7 @@ public func makeAttachmentFileControllerImpl( let existingCloseButton = Atomic(value: nil) let existingSearchButton = Atomic(value: nil) - let previousRecentDocuments = Atomic<[Message]?>(value: nil) + let previousRecentDocuments = Atomic<[EngineRawMessage]?>(value: nil) let signal = combineLatest(queue: Queue.mainQueue(), presentationData, recentDocuments, @@ -960,7 +959,7 @@ public func makeAttachmentFileControllerImpl( controller.mulitpleCompletion = { sendMode, _, _, caption in let _ = stateValue.with({ state in if let selectedMessageIds = state.selectedMessageIds { - var remoteMessageIds: [MessageId] = [] + var remoteMessageIds: [EngineMessage.Id] = [] for id in selectedMessageIds { if let message = state.messageMap[id]?._asMessage() { if message.id.namespace == Namespaces.Message.Cloud { @@ -974,7 +973,7 @@ public func makeAttachmentFileControllerImpl( |> `catch` { _ in return .single(.result([])) } - |> mapToSignal { result -> Signal<[Message], NoError> in + |> mapToSignal { result -> Signal<[EngineRawMessage], NoError> in guard case let .result(result) = result else { return .complete() } @@ -984,7 +983,7 @@ public func makeAttachmentFileControllerImpl( guard let peer, let peerReference = PeerReference(peer) else { return } - var messageMap: [MessageId: Message] = [:] + var messageMap: [EngineMessage.Id: EngineRawMessage] = [:] for message in remoteMessages { messageMap[message.id] = message } diff --git a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift index 6784fce307..02494198e8 100644 --- a/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift +++ b/submodules/TelegramUI/Components/AttachmentFileController/Sources/AttachmentFileSearchItem.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import AsyncDisplayKit -import Postbox import TelegramCore import SwiftSignalKit import ItemListUI @@ -30,7 +29,7 @@ final class AttachmentFileSearchItem: ItemListControllerSearch { let presentationData: PresentationData let focus: () -> Void let cancel: () -> Void - let send: (Message) -> Void + let send: (EngineRawMessage) -> Void let dismissInput: () -> Void let didPreviewAudio: () -> Void @@ -38,7 +37,7 @@ final class AttachmentFileSearchItem: ItemListControllerSearch { private var activity: ValuePromise = ValuePromise(ignoreRepeated: false) private let activityDisposable = MetaDisposable() - init(context: AccountContext, mode: AttachmentFileControllerMode, presentationData: PresentationData, focus: @escaping () -> Void, cancel: @escaping () -> Void, send: @escaping (Message) -> Void, dismissInput: @escaping () -> Void, didPreviewAudio: @escaping () -> Void) { + init(context: AccountContext, mode: AttachmentFileControllerMode, presentationData: PresentationData, focus: @escaping () -> Void, cancel: @escaping () -> Void, send: @escaping (EngineRawMessage) -> Void, dismissInput: @escaping () -> Void, didPreviewAudio: @escaping () -> Void) { self.context = context self.mode = mode self.presentationData = presentationData @@ -108,7 +107,7 @@ private final class AttachmentFileSearchItemNode: ItemListControllerSearchNode { private var validLayout: ContainerViewLayout? - init(context: AccountContext, mode: AttachmentFileControllerMode, presentationData: PresentationData, focus: @escaping () -> Void, send: @escaping (Message) -> Void, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, dismissInput: @escaping () -> Void, didPreviewAudio: @escaping () -> Void) { + init(context: AccountContext, mode: AttachmentFileControllerMode, presentationData: PresentationData, focus: @escaping () -> Void, send: @escaping (EngineRawMessage) -> Void, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, dismissInput: @escaping () -> Void, didPreviewAudio: @escaping () -> Void) { self.context = context self.mode = mode self.presentationData = presentationData @@ -217,11 +216,11 @@ private final class AttachmentFileSearchItemNode: ItemListControllerSearchNode { private final class AttachmentFileSearchContainerInteraction { let context: AccountContext - let send: (Message) -> Void - let toggleMediaPlayback: (Message) -> Void + let send: (EngineRawMessage) -> Void + let toggleMediaPlayback: (EngineRawMessage) -> Void let expandSection: (Int32) -> Void - init(context: AccountContext, send: @escaping (Message) -> Void, toggleMediaPlayback: @escaping (Message) -> Void, expandSection: @escaping (Int32) -> Void) { + init(context: AccountContext, send: @escaping (EngineRawMessage) -> Void, toggleMediaPlayback: @escaping (EngineRawMessage) -> Void, expandSection: @escaping (Int32) -> Void) { self.context = context self.send = send self.toggleMediaPlayback = toggleMediaPlayback @@ -232,11 +231,11 @@ private final class AttachmentFileSearchContainerInteraction { private enum AttachmentFileSearchEntryId: Hashable { case header(Int32) case placeholder(Int32, Int32) - case message(Int32, MessageId) + case message(Int32, EngineMessage.Id) case showMore(Int32) } -private func areMessagesEqual(_ lhsMessage: Message?, _ rhsMessage: Message?) -> Bool { +private func areMessagesEqual(_ lhsMessage: EngineRawMessage?, _ rhsMessage: EngineRawMessage?) -> Bool { guard let lhsMessage = lhsMessage, let rhsMessage = rhsMessage else { return lhsMessage == nil && rhsMessage == nil } @@ -251,7 +250,7 @@ private func areMessagesEqual(_ lhsMessage: Message?, _ rhsMessage: Message?) -> private enum AttachmentFileSearchEntry: Comparable, Identifiable { case header(title: String, section: Int32) - case file(index: Int32, message: Message?, section: Int32) + case file(index: Int32, message: EngineRawMessage?, section: Int32) case showMore(text: String, section: Int32) var section: ItemListSectionId { @@ -334,7 +333,7 @@ private enum AttachmentFileSearchEntry: Comparable, Identifiable { let isStoryMusic = mode.isAudio let isDownloadList = mode.isAudio - return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), systemStyle: .glass, context: interaction.context, chatLocation: .peer(id: PeerId(0)), interaction: itemInteraction, message: message, selection: .none, displayHeader: false, isDownloadList: isDownloadList, isStoryMusic: isStoryMusic, isAttachMusic: true, displayFileInfo: displayFileInfo, displayBackground: true, style: .blocks, sectionId: section) + return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), systemStyle: .glass, context: interaction.context, chatLocation: .peer(id: EnginePeer.Id(0)), interaction: itemInteraction, message: message, selection: .none, displayHeader: false, isDownloadList: isDownloadList, isStoryMusic: isStoryMusic, isAttachMusic: true, displayFileInfo: displayFileInfo, displayBackground: true, style: .blocks, sectionId: section) case let .showMore(text, section): return ItemListPeerActionItem(presentationData: ItemListPresentationData(presentationData), style: .blocks, systemStyle: .glass, icon: PresentationResourcesItemList.downArrowImage(presentationData.theme), title: text, sectionId: section, editing: false, action: { interaction.expandSection(section) @@ -379,7 +378,7 @@ private func attachmentFileSearchContainerPreparedRecentTransition( public final class AttachmentFileSearchContainerNode: SearchDisplayControllerContentNode { private let context: AccountContext - private let send: (Message) -> Void + private let send: (EngineRawMessage) -> Void private let dimNode: ASDisplayNode private let backgroundNode: ASDisplayNode @@ -415,7 +414,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon return _hasDim } - public init(context: AccountContext, mode: AttachmentFileControllerMode, presentationData: PresentationData, send: @escaping (Message) -> Void, updateActivity: @escaping (Bool) -> Void, didPreviewAudio: @escaping () -> Void) { + public init(context: AccountContext, mode: AttachmentFileControllerMode, presentationData: PresentationData, send: @escaping (EngineRawMessage) -> Void, updateActivity: @escaping (Bool) -> Void, didPreviewAudio: @escaping () -> Void) { self.context = context self.send = send @@ -512,16 +511,16 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon let queryTokens = stringTokens(query.lowercased()) - let shared: Signal<[Message]?, NoError> - let savedMusic: Signal<[Message]?, NoError> - let globalMusic: Signal<[Message]?, NoError> + let shared: Signal<[EngineRawMessage]?, NoError> + let savedMusic: Signal<[EngineRawMessage]?, NoError> + let globalMusic: Signal<[EngineRawMessage]?, NoError> switch mode { case .recent: shared = .single(nil) |> then( context.engine.messages.searchMessages(location: .sentMedia(tags: [.file]), query: query, state: nil) |> delay(0.6, queue: Queue.mainQueue()) - |> map { result -> [Message]? in + |> map { result -> [EngineRawMessage]? in return result.0.messages } ) @@ -532,7 +531,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon |> then( context.engine.messages.searchMessages(location: .general(scope: .everywhere, groupId: nil, tags: [.music], minDate: nil, maxDate: nil, folderId: nil), query: query, state: nil) |> delay(0.6, queue: Queue.mainQueue()) - |> map { result -> [Message]? in + |> map { result -> [EngineRawMessage]? in return result.0.messages.filter { !$0.isRestricted(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) } } ) @@ -542,8 +541,8 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon |> delay(0.6, queue: Queue.mainQueue()) |> map { state in let peerId = context.account.peerId - var messages: [Message] = [] - let peers = SimpleDictionary() + var messages: [EngineRawMessage] = [] + let peers = EngineSimpleDictionary() for file in state.files { var indexString = "" for attribute in file.attributes { @@ -564,7 +563,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon continue } let stableId = UInt32(clamping: file.fileId.id % Int64(Int32.max)) - messages.append(Message(stableId: stableId, stableVersion: 0, id: MessageId(peerId: peerId, namespace: Namespaces.Message.Local, id: Int32(stableId)), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [.music], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])) + messages.append(EngineRawMessage(stableId: stableId, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: Namespaces.Message.Local, id: Int32(stableId)), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [.music], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file], peers: peers, associatedMessages: EngineSimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])) } return messages } @@ -598,14 +597,14 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon return [] } let peerId = context.account.peerId - var messages: [Message] = [] - let peers = SimpleDictionary() + var messages: [EngineRawMessage] = [] + let peers = EngineSimpleDictionary() for result in results { switch result { case let .internalReference(internalReference): if let file = internalReference.file { let stableId = UInt32(clamping: file.fileId.id % Int64(Int32.max)) - messages.append(Message(stableId: stableId, stableVersion: 0, id: MessageId(peerId: peerId, namespace: Namespaces.Message.Local, id: Int32(stableId)), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [.music], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])) + messages.append(EngineRawMessage(stableId: stableId, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: Namespaces.Message.Local, id: Int32(stableId)), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [.music], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file], peers: peers, associatedMessages: EngineSimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])) } default: break @@ -900,20 +899,20 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon } } -private func stringTokens(_ string: String) -> [ValueBoxKey] { +private func stringTokens(_ string: String) -> [EngineRawValueBoxKey] { let nsString = string.folding(options: .diacriticInsensitive, locale: .current).lowercased() as NSString let flag = UInt(kCFStringTokenizerUnitWord) let tokenizer = CFStringTokenizerCreate(kCFAllocatorDefault, nsString, CFRangeMake(0, nsString.length), flag, CFLocaleCopyCurrent()) var tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer) - var tokens: [ValueBoxKey] = [] + var tokens: [EngineRawValueBoxKey] = [] - var addedTokens = Set() + var addedTokens = Set() while tokenType != [] { let currentTokenRange = CFStringTokenizerGetCurrentTokenRange(tokenizer) if currentTokenRange.location >= 0 && currentTokenRange.length != 0 { - let token = ValueBoxKey(length: currentTokenRange.length * 2) + let token = EngineRawValueBoxKey(length: currentTokenRange.length * 2) nsString.getCharacters(token.memory.assumingMemoryBound(to: unichar.self), range: NSMakeRange(currentTokenRange.location, currentTokenRange.length)) if !addedTokens.contains(token) { tokens.append(token) @@ -926,7 +925,7 @@ private func stringTokens(_ string: String) -> [ValueBoxKey] { return tokens } -private func matchStringTokens(_ tokens: [ValueBoxKey], with other: [ValueBoxKey]) -> Bool { +private func matchStringTokens(_ tokens: [EngineRawValueBoxKey], with other: [EngineRawValueBoxKey]) -> Bool { if other.isEmpty { return false } else if other.count == 1 { diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/BUILD b/submodules/TelegramUI/Components/AvatarEditorScreen/BUILD index c8f00d99c9..e88140db3c 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/BUILD +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/ComponentFlow:ComponentFlow", diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift index 19df7c4f3d..1dde1fc55d 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift @@ -11,7 +11,6 @@ import AccountContext import TelegramCore import MultilineTextComponent import EmojiStatusComponent -import Postbox import TelegramStringFormatting import TelegramNotices import EntityKeyboard @@ -288,15 +287,15 @@ final class AvatarEditorScreenComponent: Component { } else { self.stickerSearchContext = nil - let emojiItemsSignal = context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000) + let emojiItemsSignal = context.engine.itemCollections.allItems(namespace: Namespaces.ItemCollection.CloudEmojiPacks) |> take(1) - - let buildGroups: (ItemCollectionsView, [String: String], StickerSearchContext.State, StickerSearchContext?) -> (groups: [EmojiPagerContentComponent.ItemGroup], canLoadMore: Bool, isSearching: Bool, searchContext: StickerSearchContext?) = { view, allEmoticons, stickerState, searchContext in + + let buildGroups: ([EngineRawItemCollectionItem], [String: String], StickerSearchContext.State, StickerSearchContext?) -> (groups: [EmojiPagerContentComponent.ItemGroup], canLoadMore: Bool, isSearching: Bool, searchContext: StickerSearchContext?) = { items, allEmoticons, stickerState, searchContext in let hasPremium = true - + var emoji: [(String, TelegramMediaFile.Accessor?, String)] = [] - for entry in view.entries { - guard let item = entry.item as? StickerPackItem else { + for rawItem in items { + guard let item = rawItem as? StickerPackItem else { continue } if let alt = item.file.customEmojiAlt { @@ -311,7 +310,7 @@ final class AvatarEditorScreenComponent: Component { } var emojiItems: [EmojiPagerContentComponent.Item] = [] - var existingIds = Set() + var existingIds = Set() for item in emoji { if let itemFile = item.1 { if existingIds.contains(itemFile.fileId) { @@ -402,8 +401,8 @@ final class AvatarEditorScreenComponent: Component { let allEmoticons = [query.basicEmoji.0: query.basicEmoji.0] let searchContext = context.engine.stickers.stickerSearchContext(query: nil, emoticon: [query.basicEmoji.0], inputLanguageCode: languageCode) resultSignal = combineLatest(emojiItemsSignal, searchContext.state) - |> map { view, stickerState in - return buildGroups(view, allEmoticons, stickerState, searchContext) + |> map { items, stickerState in + return buildGroups(items, allEmoticons, stickerState, searchContext) } } else { var keywordsSignal = context.engine.stickers.searchEmojiKeywords(inputLanguageCode: languageCode, query: query, completeMatch: false) @@ -432,15 +431,15 @@ final class AvatarEditorScreenComponent: Component { let emoticon = Array(allEmoticons.keys) guard !emoticon.isEmpty else { return combineLatest(emojiItemsSignal, .single(StickerSearchContext.State(items: [], canLoadMore: false, isLoadingMore: false))) - |> map { view, stickerState in - return buildGroups(view, allEmoticons, stickerState, nil) + |> map { items, stickerState in + return buildGroups(items, allEmoticons, stickerState, nil) } } - + let searchContext = context.engine.stickers.stickerSearchContext(query: query, emoticon: emoticon, inputLanguageCode: languageCode) return combineLatest(emojiItemsSignal, searchContext.state) - |> map { view, stickerState in - return buildGroups(view, allEmoticons, stickerState, searchContext) + |> map { items, stickerState in + return buildGroups(items, allEmoticons, stickerState, searchContext) } } } @@ -465,7 +464,7 @@ final class AvatarEditorScreenComponent: Component { |> mapToSignal { files, isFinalResult -> Signal<(items: [EmojiPagerContentComponent.ItemGroup], isFinalResult: Bool), NoError> in var items: [EmojiPagerContentComponent.Item] = [] - var existingIds = Set() + var existingIds = Set() for itemFile in files { if existingIds.contains(itemFile.fileId) { continue @@ -560,18 +559,14 @@ final class AvatarEditorScreenComponent: Component { openSearch: { }, addGroupAction: { [weak self] groupId, isPremiumLocked, _ in - guard let strongSelf = self, let controller = strongSelf.controller?(), let collectionId = groupId.base as? ItemCollectionId else { + guard let strongSelf = self, let controller = strongSelf.controller?(), let collectionId = groupId.base as? EngineItemCollectionId else { return } let context = controller.context - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks) - let _ = (context.account.postbox.combinedView(keys: [viewKey]) + let _ = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks)) |> take(1) - |> deliverOnMainQueue).start(next: { views in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return - } - for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + |> deliverOnMainQueue).start(next: { items in + for featuredStickerPack in items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { if featuredStickerPack.info.id == collectionId { let _ = (context.engine.stickers.loadedStickerPack(reference: .id(id: featuredStickerPack.info.id.id, accessHash: featuredStickerPack.info.accessHash), forceActualized: false) |> mapToSignal { result -> Signal in @@ -591,7 +586,7 @@ final class AvatarEditorScreenComponent: Component { } |> deliverOnMainQueue).start(completed: { }) - + break } } @@ -698,18 +693,14 @@ final class AvatarEditorScreenComponent: Component { openSearch: { }, addGroupAction: { [weak self] groupId, isPremiumLocked, _ in - guard let strongSelf = self, let controller = strongSelf.controller?(), let collectionId = groupId.base as? ItemCollectionId else { + guard let strongSelf = self, let controller = strongSelf.controller?(), let collectionId = groupId.base as? EngineItemCollectionId else { return } let context = controller.context - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedStickerPacks) - let _ = (context.account.postbox.combinedView(keys: [viewKey]) + let _ = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedStickerPacks)) |> take(1) - |> deliverOnMainQueue).start(next: { views in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return - } - for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + |> deliverOnMainQueue).start(next: { items in + for featuredStickerPack in items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { if featuredStickerPack.info.id == collectionId { let _ = (context.engine.stickers.loadedStickerPack(reference: .id(id: featuredStickerPack.info.id.id, accessHash: featuredStickerPack.info.accessHash), forceActualized: false) |> mapToSignal { result -> Signal in @@ -755,15 +746,11 @@ final class AvatarEditorScreenComponent: Component { ])]) context.sharedContext.mainWindow?.presentInGlobalOverlay(actionSheet) } else if groupId == AnyHashable("featuredTop") { - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedStickerPacks) - let _ = (context.account.postbox.combinedView(keys: [viewKey]) + let _ = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedStickerPacks)) |> take(1) - |> deliverOnMainQueue).start(next: { views in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return - } + |> deliverOnMainQueue).start(next: { items in var stickerPackIds: [Int64] = [] - for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + for featuredStickerPack in items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { stickerPackIds.append(featuredStickerPack.info.id.id) } let _ = ApplicationSpecificNotice.setDismissedTrendingStickerPacks(accountManager: context.sharedContext.accountManager, values: stickerPackIds).start() @@ -1535,7 +1522,7 @@ final class AvatarEditorScreenComponent: Component { } let values = MediaEditorValues( - peerId: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), + peerId: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), originalDimensions: PixelDimensions(size), cropOffset: .zero, cropRect: CGRect(origin: .zero, size: size), diff --git a/submodules/TelegramUI/Components/Chat/ChatHistoryEntry/Sources/ChatHistoryEntry.swift b/submodules/TelegramUI/Components/Chat/ChatHistoryEntry/Sources/ChatHistoryEntry.swift index ded214f775..4974eaedb1 100644 --- a/submodules/TelegramUI/Components/Chat/ChatHistoryEntry/Sources/ChatHistoryEntry.swift +++ b/submodules/TelegramUI/Components/Chat/ChatHistoryEntry/Sources/ChatHistoryEntry.swift @@ -1,4 +1,3 @@ -import Postbox import TelegramCore import TelegramPresentationData import MergeLists @@ -18,11 +17,11 @@ public struct ChatMessageEntryAttributes: Equatable { public var updatingMedia: ChatUpdatingMessageMedia? public var isPlaying: Bool public var isCentered: Bool - public var authorStoryStats: PeerStoryStats? + public var authorStoryStats: EnginePeerStoryStats? public var displayContinueThreadFooter: Bool public var pinToTop: Bool - public init(rank: CachedChannelAdminRank?, isContact: Bool, contentTypeHint: ChatMessageEntryContentType, updatingMedia: ChatUpdatingMessageMedia?, isPlaying: Bool, isCentered: Bool, authorStoryStats: PeerStoryStats?, displayContinueThreadFooter: Bool, pinToTop: Bool) { + public init(rank: CachedChannelAdminRank?, isContact: Bool, contentTypeHint: ChatMessageEntryContentType, updatingMedia: ChatUpdatingMessageMedia?, isPlaying: Bool, isCentered: Bool, authorStoryStats: EnginePeerStoryStats?, displayContinueThreadFooter: Bool, pinToTop: Bool) { self.rank = rank self.isContact = isContact self.contentTypeHint = contentTypeHint @@ -54,10 +53,10 @@ public enum ChatInfoData: Equatable { } public enum ChatHistoryEntry: Identifiable, Comparable { - case MessageEntry(Message, ChatPresentationData, Bool, MessageHistoryEntryLocation?, ChatHistoryMessageSelection, ChatMessageEntryAttributes) - case MessageGroupEntry(Int64, [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)], ChatPresentationData) - case UnreadEntry(MessageIndex, ChatPresentationData) - case ReplyCountEntry(MessageIndex, Bool, Int, ChatPresentationData) + case MessageEntry(EngineRawMessage, ChatPresentationData, Bool, EngineMessageHistoryEntryLocation?, ChatHistoryMessageSelection, ChatMessageEntryAttributes) + case MessageGroupEntry(Int64, [(EngineRawMessage, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, EngineMessageHistoryEntryLocation?)], ChatPresentationData) + case UnreadEntry(EngineMessage.Index, ChatPresentationData) + case ReplyCountEntry(EngineMessage.Index, Bool, Int, ChatPresentationData) case ChatInfoEntry(ChatInfoData, ChatPresentationData) public var stableId: UInt64 { @@ -89,7 +88,7 @@ public enum ChatHistoryEntry: Identifiable, Comparable { } } - public var index: MessageIndex { + public var index: EngineMessage.Index { switch self { case let .MessageEntry(message, _, _, _, _, _): return message.index @@ -102,14 +101,14 @@ public enum ChatHistoryEntry: Identifiable, Comparable { case let .ChatInfoEntry(infoData, _): switch infoData { case .newThreadInfo: - return MessageIndex.absoluteUpperBound() + return EngineMessage.Index.absoluteUpperBound() default: - return MessageIndex.absoluteLowerBound() + return EngineMessage.Index.absoluteLowerBound() } } } - public var firstIndex: MessageIndex { + public var firstIndex: EngineMessage.Index { switch self { case let .MessageEntry(message, _, _, _, _, _): return message.index @@ -122,9 +121,9 @@ public enum ChatHistoryEntry: Identifiable, Comparable { case let .ChatInfoEntry(infoData, _): switch infoData { case .newThreadInfo: - return MessageIndex.absoluteUpperBound() + return EngineMessage.Index.absoluteUpperBound() default: - return MessageIndex.absoluteLowerBound() + return EngineMessage.Index.absoluteLowerBound() } } } diff --git a/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift b/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift index e81d670733..2033456e3f 100644 --- a/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift +++ b/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift @@ -3,7 +3,6 @@ import ComponentFlow import Display import AsyncDisplayKit import TelegramCore -import Postbox import AccountContext import ChatListUI import MergeLists @@ -69,7 +68,7 @@ public final class ChatInlineSearchResultsListComponent: Component { public enum Contents: Equatable { case empty - case tag(MemoryBuffer) + case tag(EngineMemoryBuffer) case search(query: String, includeSavedPeers: Bool) case monoforumChats(query: String) } @@ -94,9 +93,9 @@ public final class ChatInlineSearchResultsListComponent: Component { public let initialScrollingState: ScrollingState? public let messageSelected: (EngineMessage) -> Void public let peerSelected: (EnginePeer) -> Void - public let loadTagMessages: (MemoryBuffer, MessageIndex?) -> Signal? + public let loadTagMessages: (EngineMemoryBuffer, EngineMessage.Index?) -> Signal? public let getSearchResult: () -> Signal? - public let getSavedPeers: (String) -> Signal<[(EnginePeer, MessageIndex?)], NoError>? + public let getSavedPeers: (String) -> Signal<[(EnginePeer, EngineMessage.Index?)], NoError>? public let getChats: (String) -> Signal? public let loadMoreSearchResults: () -> Void @@ -111,9 +110,9 @@ public final class ChatInlineSearchResultsListComponent: Component { initialScrollingState: ScrollingState?, messageSelected: @escaping (EngineMessage) -> Void, peerSelected: @escaping (EnginePeer) -> Void, - loadTagMessages: @escaping (MemoryBuffer, MessageIndex?) -> Signal?, + loadTagMessages: @escaping (EngineMemoryBuffer, EngineMessage.Index?) -> Signal?, getSearchResult: @escaping () -> Signal?, - getSavedPeers: @escaping (String) -> Signal<[(EnginePeer, MessageIndex?)], NoError>?, + getSavedPeers: @escaping (String) -> Signal<[(EnginePeer, EngineMessage.Index?)], NoError>?, getChats: @escaping (String) -> Signal?, loadMoreSearchResults: @escaping () -> Void ) { @@ -243,7 +242,7 @@ public final class ChatInlineSearchResultsListComponent: Component { private struct ContentsState: Equatable { enum ContentId: Equatable { case empty - case tag(MemoryBuffer) + case tag(EngineMemoryBuffer) case search(String) } @@ -274,8 +273,8 @@ public final class ChatInlineSearchResultsListComponent: Component { private let emptyResultsText = ComponentView() private let emptyResultsAnimation = ComponentView() - private var tagContents: (index: MessageIndex?, disposable: Disposable?)? - private var searchContents: (index: MessageIndex?, disposable: Disposable?)? + private var tagContents: (index: EngineMessage.Index?, disposable: Disposable?)? + private var searchContents: (index: EngineMessage.Index?, disposable: Disposable?)? private var nextContentsId: Int = 0 private var contentsState: ContentsState? @@ -453,7 +452,7 @@ public final class ChatInlineSearchResultsListComponent: Component { guard let visibleRange = displayedRange.visibleRange else { return } - var loadAroundIndex: MessageIndex? + var loadAroundIndex: EngineMessage.Index? if visibleRange.firstIndex <= 5 { if contentsState.hasLater { loadAroundIndex = contentsState.messages.first?.index @@ -615,7 +614,7 @@ public final class ChatInlineSearchResultsListComponent: Component { let disposable = MetaDisposable() self.searchContents = (nil, disposable) - let savedPeers: Signal<[(EnginePeer, MessageIndex?)], NoError> + let savedPeers: Signal<[(EnginePeer, EngineMessage.Index?)], NoError> if includeSavedPeers, !query.isEmpty, let savedPeersSignal = component.getSavedPeers(query) { savedPeers = savedPeersSignal } else { @@ -624,7 +623,7 @@ public final class ChatInlineSearchResultsListComponent: Component { if let historySignal = component.getSearchResult() { disposable.set((savedPeers - |> mapToSignal { savedPeers -> Signal<([(EnginePeer, MessageIndex?)], SearchMessagesResult?), NoError> in + |> mapToSignal { savedPeers -> Signal<([(EnginePeer, EngineMessage.Index?)], SearchMessagesResult?), NoError> in if savedPeers.isEmpty { return historySignal |> map { result in @@ -769,7 +768,7 @@ public final class ChatInlineSearchResultsListComponent: Component { /*if let historySignal = component.getSearchResult() { disposable.set((savedPeers - |> mapToSignal { savedPeers -> Signal<([(EnginePeer, MessageIndex?)], SearchMessagesResult?), NoError> in + |> mapToSignal { savedPeers -> Signal<([(EnginePeer, EngineMessage.Index?)], SearchMessagesResult?), NoError> in if savedPeers.isEmpty { return historySignal |> map { result in @@ -1030,14 +1029,14 @@ public final class ChatInlineSearchResultsListComponent: Component { if let forwardInfo = message.forwardInfo { effectiveAuthor = forwardInfo.author.flatMap(EnginePeer.init) if effectiveAuthor == nil, let authorSignature = forwardInfo.authorSignature { - effectiveAuthor = EnginePeer(TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + effectiveAuthor = EnginePeer(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.Empty, id: EnginePeer.Id.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) } } if let sourceAuthorInfo = message._asMessage().sourceAuthorInfo { if let originalAuthor = sourceAuthorInfo.originalAuthor, let peer = message.peers[originalAuthor] { effectiveAuthor = EnginePeer(peer) } else if let authorSignature = sourceAuthorInfo.originalAuthorName { - effectiveAuthor = EnginePeer(TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + effectiveAuthor = EnginePeer(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.Empty, id: EnginePeer.Id.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) } } if effectiveAuthor == nil { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/BUILD index 4b6113af11..368374b99a 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox", "//submodules/Display", "//submodules/AsyncDisplayKit", "//submodules/SSignalKit/SwiftSignalKit", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift index 4242a1cc39..6a190131c5 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import Display import AsyncDisplayKit import SwiftSignalKit @@ -61,7 +60,7 @@ public struct ChatMessageAttachedContentNodeMediaFlags: OptionSet { public final class ChatMessageAttachedContentNode: ASDisplayNode { private enum InlineMedia: Equatable { - case media(Media) + case media(EngineRawMedia) case peerAvatar(EnginePeer) static func ==(lhs: InlineMedia, rhs: InlineMedia) -> Bool { @@ -108,8 +107,8 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { private var linkHighlightingNode: LinkHighlightingNode? private var context: AccountContext? - private var message: Message? - private var media: Media? + private var message: EngineRawMessage? + private var media: EngineRawMedia? private var theme: ChatPresentationThemeData? private var mainColor: UIColor? @@ -168,7 +167,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { self.activateBadgeAction?() } - public typealias AsyncLayout = (_ presentationData: ChatPresentationData, _ automaticDownloadSettings: MediaAutoDownloadSettings, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ context: AccountContext, _ controllerInteraction: ChatControllerInteraction, _ message: Message, _ messageRead: Bool, _ chatLocation: ChatLocation, _ title: String?, _ titleBadge: String?, _ subtitle: NSAttributedString?, _ text: String?, _ entities: [MessageTextEntity]?, _ media: ([Media], ChatMessageAttachedContentNodeMediaFlags)?, _ mediaBadge: String?, _ actionIcon: ChatMessageAttachedContentActionIcon?, _ actionTitle: String?, _ displayLine: Bool, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ constrainedSize: CGSize, _ animationCache: AnimationCache, _ animationRenderer: MultiAnimationRenderer) -> (CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) + public typealias AsyncLayout = (_ presentationData: ChatPresentationData, _ automaticDownloadSettings: MediaAutoDownloadSettings, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ context: AccountContext, _ controllerInteraction: ChatControllerInteraction, _ message: EngineRawMessage, _ messageRead: Bool, _ chatLocation: ChatLocation, _ title: String?, _ titleBadge: String?, _ subtitle: NSAttributedString?, _ text: String?, _ entities: [MessageTextEntity]?, _ media: ([EngineRawMedia], ChatMessageAttachedContentNodeMediaFlags)?, _ mediaBadge: String?, _ actionIcon: ChatMessageAttachedContentActionIcon?, _ actionTitle: String?, _ displayLine: Bool, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ constrainedSize: CGSize, _ animationCache: AnimationCache, _ animationRenderer: MultiAnimationRenderer) -> (CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) public func makeProgress() -> Promise { let progress = Promise() @@ -236,7 +235,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { if let peer = forwardInfo.author { author = peer } else if let authorSignature = forwardInfo.authorSignature { - author = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) + author = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.Empty, id: EnginePeer.Id.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) } } @@ -314,7 +313,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { insets.right += 6.0 } - var contentMediaValue: Media? + var contentMediaValue: EngineRawMedia? var contentFileValue: TelegramMediaFile? var contentAnimatedFilesValue: [TelegramMediaFile] = [] @@ -1563,7 +1562,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { pattern = MessageInlineBlockBackgroundView.Pattern( context: context, fileId: backgroundEmojiId, - file: message.associatedMedia[MediaId( + file: message.associatedMedia[EngineMedia.Id( namespace: Namespaces.Media.CloudFile, id: backgroundEmojiId )] as? TelegramMediaFile @@ -1605,7 +1604,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { } } - public func updateHiddenMedia(_ media: [Media]?) -> Bool { + public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { if let currentMedia = self.media { if let media = media { var found = false @@ -1628,7 +1627,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { return false } - public func transitionNode(media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + public func transitionNode(media: EngineRawMedia) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if let contentImageNode = self.contentMedia, let image = self.media as? TelegramMediaImage, image.isEqual(to: media) { return (contentImageNode, contentImageNode.bounds, { [weak contentImageNode] in return (contentImageNode?.view.snapshotContentTree(unhide: true), nil) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift index c94fad0851..6be3c27576 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import AsyncDisplayKit -import Postbox import SwiftSignalKit import Display import TelegramCore @@ -47,8 +46,8 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { public let context: AccountContext public let presentationData: ChatPresentationData public let customTintColor: UIColor? - public let message: Message - public let topMessage: Message + public let message: EngineRawMessage + public let topMessage: EngineRawMessage public let associatedData: ChatMessageItemAssociatedData public let chatLocation: ChatLocation public let attributes: ChatMessageEntryAttributes @@ -71,8 +70,8 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { context: AccountContext, presentationData: ChatPresentationData, customTintColor: UIColor?, - message: Message, - topMessage: Message, + message: EngineRawMessage, + topMessage: EngineRawMessage, associatedData: ChatMessageItemAssociatedData, chatLocation: ChatLocation, attributes: ChatMessageEntryAttributes, @@ -181,7 +180,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { private let fetchControls = Atomic(value: nil) private var resourceStatus: FileMediaResourceStatus? - private var actualFetchStatus: MediaResourceStatus? + private var actualFetchStatus: EngineMediaResourceStatus? private let fetchDisposable = MetaDisposable() public var toggleSelection: (Bool) -> Void = { _ in } @@ -192,7 +191,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { public var updateTranscriptionExpanded: ((AudioTranscriptionButtonComponent.TranscriptionState) -> Void)? private var context: AccountContext? - private var message: Message? + private var message: EngineRawMessage? private var arguments: Arguments? private var presentationData: ChatPresentationData? private var file: TelegramMediaFile? @@ -445,7 +444,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { return .single(nil) } return convertOpusToAAC(sourcePath: result, allocateTempFile: { - return TempBox.shared.tempFile(fileName: "audio.m4a").path + return EngineTempBox.shared.tempFile(fileName: "audio.m4a").path }) } |> mapToSignal { result -> Signal in @@ -581,7 +580,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { let durationFont = Font.regular(floor(arguments.presentationData.fontSize.baseDisplaySize * 11.0 / 17.0)) var updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? - var updatedStatusSignal: Signal<(FileMediaResourceStatus, MediaResourceStatus?), NoError>? + var updatedStatusSignal: Signal<(FileMediaResourceStatus, EngineMediaResourceStatus?), NoError>? var updatedAudioLevelEventsSignal: Signal? var updatedPlaybackStatusSignal: Signal? var updatedFetchControls: FetchControls? @@ -622,13 +621,13 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { if statusUpdated { if arguments.message.flags.isSending { updatedStatusSignal = combineLatest(messageFileMediaResourceStatus(context: arguments.context, file: arguments.file, message: EngineMessage(arguments.message), isRecentActions: arguments.isRecentActions), messageMediaFileStatus(context: arguments.context, messageId: arguments.message.id, file: arguments.file)) - |> map { resourceStatus, actualFetchStatus -> (FileMediaResourceStatus, MediaResourceStatus?) in + |> map { resourceStatus, actualFetchStatus -> (FileMediaResourceStatus, EngineMediaResourceStatus?) in return (resourceStatus, actualFetchStatus) } updatedAudioLevelEventsSignal = messageFileMediaPlaybackAudioLevelEvents(context: arguments.context, file: arguments.file, message: EngineMessage(arguments.message), isRecentActions: arguments.isRecentActions, isGlobalSearch: false, isDownloadList: false, isSavedMusic: false) } else { updatedStatusSignal = messageFileMediaResourceStatus(context: arguments.context, file: arguments.file, message: EngineMessage(arguments.message), isRecentActions: arguments.isRecentActions) - |> map { resourceStatus -> (FileMediaResourceStatus, MediaResourceStatus?) in + |> map { resourceStatus -> (FileMediaResourceStatus, EngineMediaResourceStatus?) in return (resourceStatus, nil) } updatedAudioLevelEventsSignal = messageFileMediaPlaybackAudioLevelEvents(context: arguments.context, file: arguments.file, message: EngineMessage(arguments.message), isRecentActions: arguments.isRecentActions, isGlobalSearch: false, isDownloadList: false, isSavedMusic: false) @@ -1425,7 +1424,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { if var updatedStatusSignal = updatedStatusSignal { if strongSelf.file?.isInstantVideo == true { updatedStatusSignal = updatedStatusSignal - |> mapToThrottled { next -> Signal<(FileMediaResourceStatus, MediaResourceStatus?), NoError> in + |> mapToThrottled { next -> Signal<(FileMediaResourceStatus, EngineMediaResourceStatus?), NoError> in return .single(next) |> then(.complete() |> delay(0.1, queue: Queue.concurrentDefaultQueue())) } } @@ -1650,7 +1649,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { var playbackState: (position: Double, duration: Double, generationTimestamp: Double) = (0.0, 0.0, 0.0) if !isAudio { - var fetchStatus: MediaResourceStatus? + var fetchStatus: EngineMediaResourceStatus? if let actualFetchStatus = self.actualFetchStatus, message.forwardInfo != nil { fetchStatus = actualFetchStatus } else if case let .fetchStatus(status) = resourceStatus.mediaStatus { @@ -1813,7 +1812,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { } } - image = playerAlbumArt(postbox: context.account.postbox, engine: context.engine, fileReference: .message(message: MessageReference(message), media: file), albumArt: .init(thumbnailResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: false)), thumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3), drawPlaceholderWhenEmpty: false, attemptSynchronously: !animated) + image = playerAlbumArt(engine: context.engine, fileReference: .message(message: MessageReference(message), media: file), albumArt: .init(thumbnailResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(file: .message(message: MessageReference(message), media: file), title: title ?? "", performer: performer ?? "", isThumbnail: false)), thumbnail: true, overlayColor: UIColor(white: 0.0, alpha: 0.3), drawPlaceholderWhenEmpty: false, attemptSynchronously: !animated) } } let statusNode = SemanticStatusNode(backgroundNodeColor: backgroundNodeColor, foregroundNodeColor: foregroundNodeColor, image: image, overlayForegroundNodeColor: presentationData.theme.theme.chat.message.mediaOverlayControlColors.foregroundColor) @@ -2079,7 +2078,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { } } - public func transitionNode(media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + public func transitionNode(media: EngineRawMedia) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { if let iconNode = self.iconNode, let file = self.file, file.isEqual(to: media) { return (iconNode, iconNode.bounds, { [weak iconNode] in return (iconNode?.view.snapshotContentTree(unhide: true), nil) @@ -2089,7 +2088,7 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { } } - public func updateHiddenMedia(_ media: [Media]?) -> Bool { + public func updateHiddenMedia(_ media: [EngineRawMedia]?) -> Bool { var isHidden = false if let file = self.file, let media = media { for m in media { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift index 05c31d02ab..bad3a3a22d 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageDateHeader.swift @@ -1082,13 +1082,13 @@ public final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode, Chat } if peer.isPremium && context.sharedContext.energyUsageSettings.autoplayVideo { - self.cachedDataDisposable.set((context.account.postbox.peerView(id: peer.id) - |> deliverOnMainQueue).startStrict(next: { [weak self] peerView in + self.cachedDataDisposable.set((context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.CachedData(id: peer.id)) + |> deliverOnMainQueue).startStrict(next: { [weak self] cachedData in guard let strongSelf = self else { return } - - let cachedPeerData = peerView.cachedData as? CachedUserData + + let cachedPeerData = cachedData as? CachedUserData var personalPhoto: TelegramMediaImage? var profilePhoto: TelegramMediaImage? var isKnown = false diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/BUILD index 0b956ee90f..0b7384f174 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/AsyncDisplayKit", "//submodules/Display", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift b/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift index 466f3f0e1f..506dd18540 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import Display -import Postbox import TelegramCore import SwiftSignalKit import TelegramPresentationData @@ -24,8 +23,8 @@ public final class ChatMessageNotificationItem: NotificationItem { public let strings: PresentationStrings public let dateTimeFormat: PresentationDateTimeFormat public let nameDisplayOrder: PresentationPersonNameOrder - public let messages: [Message] - public let threadData: MessageHistoryThreadData? + public let messages: [EngineRawMessage] + public let threadData: EngineMessageHistoryThreadData? public let tapAction: () -> Bool public let expandAction: (@escaping () -> (ASDisplayNode?, () -> Void)) -> Void @@ -33,7 +32,7 @@ public final class ChatMessageNotificationItem: NotificationItem { return messages.first?.id.peerId } - public init(context: AccountContext, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, messages: [Message], threadData: MessageHistoryThreadData?, tapAction: @escaping () -> Bool, expandAction: @escaping (() -> (ASDisplayNode?, () -> Void)) -> Void) { + public init(context: AccountContext, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, messages: [EngineRawMessage], threadData: EngineMessageHistoryThreadData?, tapAction: @escaping () -> Bool, expandAction: @escaping (() -> (ASDisplayNode?, () -> Void)) -> Void) { self.context = context self.strings = strings self.dateTimeFormat = dateTimeFormat @@ -187,7 +186,7 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { self.avatarNode.setPeer(context: item.context, theme: presentationData.theme, peer: avatarPeer, overrideImage: peer.id == item.context.account.peerId ? .savedMessagesIcon : nil, emptyColor: presentationData.theme.list.mediaPlaceholderColor) } - var updatedMedia: Media? + var updatedMedia: EngineRawMedia? var imageDimensions: CGSize? var isRound = false var messageText: String diff --git a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift index 1e8c045d20..b15afc9f91 100644 --- a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift @@ -331,7 +331,7 @@ public final class ChatRecentActionsController: TelegramBaseController { func openFilterSetup() { if self.adminsPromise == nil { self.adminsPromise = Promise() - let (disposable, _) = self.context.peerChannelMemberCategoriesContextsManager.admins(engine: self.context.engine, postbox: self.context.account.postbox, network: self.context.account.network, accountPeerId: self.context.account.peerId, peerId: self.peer.id) { membersState in + let (disposable, _) = self.context.peerChannelMemberCategoriesContextsManager.admins(engine: self.context.engine, accountPeerId: self.context.account.peerId, peerId: self.peer.id) { membersState in if case .loading = membersState.loadingState, membersState.list.isEmpty { self.adminsPromise?.set(.single(nil)) } else { diff --git a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift index 40d13fac3e..82934145c6 100644 --- a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import TelegramCore -import Postbox import SwiftSignalKit import Display import TelegramPresentationData @@ -43,7 +42,7 @@ private final class ChatRecentActionsListOpaqueState { final class ChatRecentActionsControllerNode: ViewControllerTracingNode { private let context: AccountContext - private let peer: Peer + private let peer: EngineRawPeer private var presentationData: PresentationData private let pushController: (ViewController) -> Void @@ -95,20 +94,20 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { private let eventLogContext: ChannelAdminEventLogContext private var enqueuedTransitions: [(ChatRecentActionsHistoryTransition, Bool)] = [] - private var searchResultsState: (String, [MessageIndex])? + private var searchResultsState: (String, [EngineMessage.Index])? private var historyDisposable: Disposable? private let resolvePeerByNameDisposable = MetaDisposable() private var adminsDisposable: Disposable? private var adminsState: ChannelMemberListState? - private let banDisposables = DisposableDict() - private let reportFalsePositiveDisposables = DisposableDict() + private let banDisposables = DisposableDict() + private let reportFalsePositiveDisposables = DisposableDict() private weak var antiSpamTooltipController: UndoOverlayController? private weak var controller: ChatRecentActionsController? - init(context: AccountContext, controller: ChatRecentActionsController, peer: Peer, presentationData: PresentationData, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, PresentationContextType, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?) { + init(context: AccountContext, controller: ChatRecentActionsController, peer: EngineRawPeer, presentationData: PresentationData, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, PresentationContextType, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?) { self.context = context self.controller = controller self.peer = peer @@ -158,7 +157,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { self.panelButtonNode.addTarget(self, action: #selector(self.settingsButtonPressed), forControlEvents: .touchUpInside) self.panelInfoButtonNode.addTarget(self, action: #selector(self.infoButtonPressed), forControlEvents: .touchUpInside) - let (adminsDisposable, _) = self.context.peerChannelMemberCategoriesContextsManager.admins(engine: self.context.engine, postbox: self.context.account.postbox, network: self.context.account.network, accountPeerId: context.account.peerId, peerId: self.peer.id, searchQuery: nil, updated: { [weak self] state in + let (adminsDisposable, _) = self.context.peerChannelMemberCategoriesContextsManager.admins(engine: self.context.engine, accountPeerId: context.account.peerId, peerId: self.peer.id, searchQuery: nil, updated: { [weak self] state in self?.adminsState = state }) self.adminsDisposable = adminsDisposable @@ -270,7 +269,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { if let strongSelf = self { strongSelf.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).startStrict(next: { messageId in if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { - var messageIdAndMedia: [MessageId: [Media]] = [:] + var messageIdAndMedia: [EngineMessage.Id: [EngineRawMedia]] = [:] if let messageId = messageId { messageIdAndMedia[messageId] = [media] @@ -345,7 +344,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { guard let strongSelf = self else { return } - let resolveSignal: Signal + let resolveSignal: Signal if let peerName = peerName { resolveSignal = strongSelf.context.engine.peers.resolvePeerByName(name: peerName, referrer: nil) |> mapToSignal { result -> Signal in @@ -354,7 +353,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { } return .single(result) } - |> mapToSignal { peer -> Signal in + |> mapToSignal { peer -> Signal in return .single(peer?._asPeer()) } } else { @@ -730,10 +729,10 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { let toggledDeletedMessageIds = previousExpandedDeletedMessages.symmetricDifference(expandedDeletedMessages) - var searchResultsState: (String, [MessageIndex])? + var searchResultsState: (String, [EngineMessage.Index])? if update.3, let query = self?.filter.query { searchResultsState = (query, processedView.compactMap { entry in - return entry.entry.event.action.messageId.flatMap { MessageIndex(id: $0, timestamp: entry.entry.event.date) } + return entry.entry.event.action.messageId.flatMap { EngineMessage.Index(id: $0, timestamp: entry.entry.event.date) } }) } else { searchResultsState = nil @@ -754,7 +753,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { let mediaManager = self.context.sharedContext.mediaManager self.galleryHiddenMesageAndMediaDisposable.set(mediaManager.galleryHiddenMediaManager.hiddenIds().startStrict(next: { [weak self] ids in if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { - var messageIdAndMedia: [MessageId: [Media]] = [:] + var messageIdAndMedia: [EngineMessage.Id: [EngineRawMedia]] = [:] for id in ids { if case let .chat(accountId, messageId, media) = id, accountId == strongSelf.context.account.id { @@ -968,13 +967,13 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { func updateItemNodesSearchTextHighlightStates() { var searchString: String? - var resultsMessageIndices: [MessageIndex]? = nil + var resultsMessageIndices: [EngineMessage.Index]? = nil if let (query, indices) = self.searchResultsState { searchString = query resultsMessageIndices = indices } if searchString != self.controllerInteraction?.searchTextHighightState?.0 || resultsMessageIndices != self.controllerInteraction?.searchTextHighightState?.1 { - var searchTextHighightState: (String, [MessageIndex])? + var searchTextHighightState: (String, [EngineMessage.Index])? if let searchString = searchString, let resultsMessageIndices = resultsMessageIndices { searchTextHighightState = (searchString, resultsMessageIndices) } @@ -987,7 +986,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { } } - func updateFilter(events: AdminLogEventsFlags, adminPeerIds: [PeerId]?) { + func updateFilter(events: AdminLogEventsFlags, adminPeerIds: [EnginePeer.Id]?) { self.filter = self.filter.withEvents(events).withAdminPeerIds(adminPeerIds) self.eventLogContext.setFilter(self.filter) } @@ -1007,7 +1006,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { return false }), .window(.root), nil) } else { - let peerSignal: Signal = .single(peer._asPeer()) + let peerSignal: Signal = .single(peer._asPeer()) self.navigationActionDisposable.set((peerSignal |> take(1) |> deliverOnMainQueue).startStrict(next: { [weak self] peer in if let strongSelf = self, let peer = peer { if peer is TelegramChannel, let navigationController = strongSelf.getNavigationController() { @@ -1041,7 +1040,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { })) } - private func openMessageContextMenu(message: Message, selectAll: Bool, node: ASDisplayNode, frame: CGRect, recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil, location: CGPoint? = nil) { + private func openMessageContextMenu(message: EngineRawMessage, selectAll: Bool, node: ASDisplayNode, frame: CGRect, recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil, location: CGPoint? = nil) { guard let controller = self.controller else { return } @@ -1313,7 +1312,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { if let photoRepresentation = invite.photoRepresentation { photo.append(photoRepresentation) } - let channel = TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(0)), accessHash: .genericPublic(0), title: invite.title, username: nil, photo: photo, creationDate: 0, version: 0, participationStatus: .left, info: .broadcast(TelegramChannelBroadcastInfo(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: invite.nameColor, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil) + let channel = TelegramChannel(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudChannel, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: .genericPublic(0), title: invite.title, username: nil, photo: photo, creationDate: 0, version: 0, participationStatus: .left, info: .broadcast(TelegramChannelBroadcastInfo(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: invite.nameColor, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil) let invoice = TelegramMediaInvoice(title: "", description: "", photo: nil, receiptMessageId: nil, currency: "XTR", totalAmount: subscriptionPricing.amount.value, startParam: "", extendedMedia: nil, subscriptionPeriod: nil, flags: [], version: 0) inputData.set(.single(BotCheckoutController.InputData( @@ -1549,14 +1548,14 @@ final class ChatRecentActionsMessageContextExtractedContentSource: ContextExtrac let blurBackground: Bool = true private weak var controllerNode: ChatRecentActionsControllerNode? - private let message: Message + private let message: EngineRawMessage private let selectAll: Bool var shouldBeDismissed: Signal { return .single(false) } - init(controllerNode: ChatRecentActionsControllerNode, message: Message, selectAll: Bool) { + init(controllerNode: ChatRecentActionsControllerNode, message: EngineRawMessage, selectAll: Bool) { self.controllerNode = controllerNode self.message = message self.selectAll = selectAll @@ -1618,7 +1617,7 @@ final class ChatMessageContextLocationContentSource: ContextLocationContentSourc } extension AdminLogEventAction { - var messageId: MessageId? { + var messageId: EngineMessage.Id? { switch self { case let .editMessage(_, new): return new.id diff --git a/submodules/TelegramUI/Components/Chat/ForwardAccessoryPanelNode/BUILD b/submodules/TelegramUI/Components/Chat/ForwardAccessoryPanelNode/BUILD index 97ddeb8af6..6e77abca27 100644 --- a/submodules/TelegramUI/Components/Chat/ForwardAccessoryPanelNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ForwardAccessoryPanelNode/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/AsyncDisplayKit", "//submodules/TelegramCore", - "//submodules/Postbox", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/Display", "//submodules/TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/Chat/ForwardAccessoryPanelNode/Sources/ForwardAccessoryPanelNode.swift b/submodules/TelegramUI/Components/Chat/ForwardAccessoryPanelNode/Sources/ForwardAccessoryPanelNode.swift index 21ed1416f8..7e8ace96ef 100644 --- a/submodules/TelegramUI/Components/Chat/ForwardAccessoryPanelNode/Sources/ForwardAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ForwardAccessoryPanelNode/Sources/ForwardAccessoryPanelNode.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import TelegramCore -import Postbox import SwiftSignalKit import Display import TelegramPresentationData @@ -23,7 +22,7 @@ import AppBundle import ComponentFlow import AlertComponent -func textStringForForwardedMessage(_ message: Message, strings: PresentationStrings) -> (text: String, entities: [MessageTextEntity], isMedia: Bool) { +func textStringForForwardedMessage(_ message: EngineRawMessage, strings: PresentationStrings) -> (text: String, entities: [MessageTextEntity], isMedia: Bool) { for media in message.media { switch media { case _ as TelegramMediaImage: @@ -89,8 +88,8 @@ func textStringForForwardedMessage(_ message: Message, strings: PresentationStri public final class ForwardAccessoryPanelNode: AccessoryPanelNode { private let messageDisposable = MetaDisposable() - public let messageIds: [MessageId] - private var messages: [Message] = [] + public let messageIds: [EngineMessage.Id] + private var messages: [EngineRawMessage] = [] let closeButton: HighlightableButtonNode let lineNode: ASImageNode @@ -110,7 +109,7 @@ public final class ForwardAccessoryPanelNode: AccessoryPanelNode { private var validLayout: (size: CGSize, inset: CGFloat, interfaceState: ChatPresentationInterfaceState)? - public init(context: AccountContext, messageIds: [MessageId], theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, nameDisplayOrder: PresentationPersonNameOrder, forwardOptionsState: ChatInterfaceForwardOptionsState?, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) { + public init(context: AccountContext, messageIds: [EngineMessage.Id], theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, nameDisplayOrder: PresentationPersonNameOrder, forwardOptionsState: ChatInterfaceForwardOptionsState?, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) { self.context = context self.messageIds = messageIds self.theme = theme @@ -165,7 +164,10 @@ public final class ForwardAccessoryPanelNode: AccessoryPanelNode { ) } - self.messageDisposable.set((context.account.postbox.messagesAtIds(messageIds) + self.messageDisposable.set((context.engine.data.get(EngineDataMap(messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init))) + |> map { messageMap -> [EngineRawMessage] in + return messageIds.compactMap { messageMap[$0]??._asMessage() } + } |> deliverOnMainQueue).start(next: { [weak self] messages in if let strongSelf = self { if messages.isEmpty { @@ -295,7 +297,7 @@ public final class ForwardAccessoryPanelNode: AccessoryPanelNode { } var authors = "" - var uniquePeerIds = Set() + var uniquePeerIds = Set() var title = "" var text = NSMutableAttributedString(string: "") @@ -325,7 +327,7 @@ public final class ForwardAccessoryPanelNode: AccessoryPanelNode { case let .CustomEmoji(_, fileId): let range = NSRange(location: entity.range.lowerBound, length: entity.range.upperBound - entity.range.lowerBound) if range.lowerBound >= 0 && range.upperBound <= additionalText.length { - additionalText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: messages[0].associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile), range: range) + additionalText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: messages[0].associatedMedia[EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile), range: range) } default: break diff --git a/submodules/TelegramUI/Components/Chat/QuickShareScreen/BUILD b/submodules/TelegramUI/Components/Chat/QuickShareScreen/BUILD index 1822500c99..8bf1f0dd79 100644 --- a/submodules/TelegramUI/Components/Chat/QuickShareScreen/BUILD +++ b/submodules/TelegramUI/Components/Chat/QuickShareScreen/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/AsyncDisplayKit", "//submodules/Display", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/ComponentFlow", diff --git a/submodules/TelegramUI/Components/Chat/QuickShareScreen/Sources/QuickShareScreen.swift b/submodules/TelegramUI/Components/Chat/QuickShareScreen/Sources/QuickShareScreen.swift index d9043f109f..325da7d80c 100644 --- a/submodules/TelegramUI/Components/Chat/QuickShareScreen/Sources/QuickShareScreen.swift +++ b/submodules/TelegramUI/Components/Chat/QuickShareScreen/Sources/QuickShareScreen.swift @@ -4,7 +4,6 @@ import AsyncDisplayKit import Display import ComponentFlow import SwiftSignalKit -import Postbox import TelegramCore import TextFormat import TelegramPresentationData @@ -218,19 +217,13 @@ private final class QuickShareScreenComponent: Component { if case let .peers(peers) = recentPeers, !peers.isEmpty { return .single(peers.map(EnginePeer.init)) } else { - return component.context.account.stateManager.postbox.tailChatListView( - groupId: .root, - count: 20, - summaryComponents: ChatListEntrySummaryComponents() - ) + return component.context.engine.messages.chatList(group: .root, count: 20) |> take(1) - |> map { view -> [EnginePeer] in + |> map { chatList -> [EnginePeer] in var peers: [EnginePeer] = [] - for entry in view.0.entries.reversed() { - if case let .MessageEntry(entryData) = entry { - if let user = entryData.renderedPeer.chatMainPeer as? TelegramUser, user.isGenericUser && user.id != component.context.account.peerId && !user.id.isSecretChat { - peers.append(EnginePeer(user)) - } + for item in chatList.items.reversed() { + if case let .user(user) = item.renderedPeer.chatMainPeer, user.isGenericUser && user.id != component.context.account.peerId && !user.id.isSecretChat { + peers.append(.user(user)) } } return peers diff --git a/submodules/TelegramUI/Components/Chat/TopMessageReactions/BUILD b/submodules/TelegramUI/Components/Chat/TopMessageReactions/BUILD index 554275c6a9..29c6d108f4 100644 --- a/submodules/TelegramUI/Components/Chat/TopMessageReactions/BUILD +++ b/submodules/TelegramUI/Components/Chat/TopMessageReactions/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/SSignalKit/SwiftSignalKit", "//submodules/TelegramCore", - "//submodules/Postbox", "//submodules/AccountContext", "//submodules/ReactionSelectionNode", ], diff --git a/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift b/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift index bb3f83e615..5e99e36484 100644 --- a/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift +++ b/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift @@ -1,7 +1,6 @@ import Foundation import SwiftSignalKit import TelegramCore -import Postbox import AccountContext import ReactionSelectionNode @@ -10,7 +9,7 @@ public enum AllowedReactions { case all } -public func peerMessageAllowedReactions(context: AccountContext, message: Message, ignoreDefault: Bool = false) -> Signal<(allowedReactions: AllowedReactions?, areStarsEnabled: Bool), NoError> { +public func peerMessageAllowedReactions(context: AccountContext, message: EngineRawMessage, ignoreDefault: Bool = false) -> Signal<(allowedReactions: AllowedReactions?, areStarsEnabled: Bool), NoError> { if message.id.peerId == context.account.peerId { return .single((.all, false)) } @@ -106,18 +105,11 @@ public func tagMessageReactions(context: AccountContext, subPeerId: EnginePeer.I return combineLatest( context.engine.stickers.availableReactions(), - context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudDefaultTagReactions], namespaces: [ItemCollectionId.Namespace.max - 1], aroundIndex: nil, count: 10000000), + context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudDefaultTagReactions)), topTags ) |> take(1) - |> map { availableReactions, view, topTags -> [ReactionItem] in - var defaultTagReactions: OrderedItemListView? - for orderedView in view.orderedItemListsViews { - if orderedView.collectionId == Namespaces.OrderedItemList.CloudDefaultTagReactions { - defaultTagReactions = orderedView - } - } - + |> map { availableReactions, defaultTagReactionItems, topTags -> [ReactionItem] in var result: [ReactionItem] = [] var existingIds = Set() @@ -176,8 +168,8 @@ public func tagMessageReactions(context: AccountContext, subPeerId: EnginePeer.I } } - if let defaultTagReactions { - for item in defaultTagReactions.items { + do { + for item in defaultTagReactionItems { guard let topReaction = item.contents.get(RecentReactionItem.self) else { continue } @@ -260,7 +252,7 @@ public func tagMessageReactions(context: AccountContext, subPeerId: EnginePeer.I } } -public func topMessageReactions(context: AccountContext, message: Message, subPeerId: EnginePeer.Id?, ignoreDefault: Bool = false) -> Signal<[ReactionItem], NoError> { +public func topMessageReactions(context: AccountContext, message: EngineRawMessage, subPeerId: EnginePeer.Id?, ignoreDefault: Bool = false) -> Signal<[ReactionItem], NoError> { if message.id.peerId == context.account.peerId { var loadTags = false if let effectiveReactionsAttribute = message.effectiveReactionsAttribute(isTags: message.areReactionsTags(accountPeerId: context.account.peerId)) { @@ -279,13 +271,9 @@ public func topMessageReactions(context: AccountContext, message: Message, subPe } } - let viewKey: PostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudTopReactions) - let topReactions = context.account.postbox.combinedView(keys: [viewKey]) - |> map { views -> [RecentReactionItem] in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return [] - } - return view.items.compactMap { item -> RecentReactionItem? in + let topReactions = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudTopReactions)) + |> map { items -> [RecentReactionItem] in + return items.compactMap { item -> RecentReactionItem? in return item.contents.get(RecentReactionItem.self) } } diff --git a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/StickerPaneSearchContentNode.swift b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/StickerPaneSearchContentNode.swift index bb5eeb9b62..4f2841b2f4 100644 --- a/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/StickerPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Components/ChatEntityKeyboardInputNode/Sources/StickerPaneSearchContentNode.swift @@ -6,7 +6,6 @@ import ButtonComponent import ComponentFlow import EdgeEffect import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import PresentationDataUtils @@ -132,7 +131,7 @@ private final class StickerSearchPackTopPanelItemComponent: Component { final class View: UIView { private var itemLayer: InlineStickerItemLayer? - private var itemFileId: MediaId? + private var itemFileId: EngineMedia.Id? private var titleView: ComponentView? private var component: StickerSearchPackTopPanelItemComponent? @@ -317,7 +316,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { private var searchIsActive: Bool = false private var selectedPack: StickerPaneSearchPack? private var isPackPanelExpanded: Bool = true - private var installedPackIds = Set() + private var installedPackIds = Set() private var stickerSearchContext: StickerSearchContext? private var currentSearchStickerCount: Int = 0 private var currentStickerCount: Int = 0 @@ -597,15 +596,11 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { ) } - let installedPackIds = context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])]) - |> map { view -> Set in - var installedPacks = Set() - if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionInfosView { - if let packsEntries = stickerPacksView.entriesByNamespace[Namespaces.ItemCollection.CloudStickerPacks] { - for entry in packsEntries { - installedPacks.insert(entry.id) - } - } + let installedPackIds = context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCollections.InstalledPackInfos(namespace: Namespaces.ItemCollection.CloudStickerPacks)) + |> map { entries -> Set in + var installedPacks = Set() + for entry in entries { + installedPacks.insert(entry.id) } return installedPacks } @@ -713,7 +708,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { private func entries(stickers: [FoundStickerItem]) -> [StickerSearchEntry] { var entries: [StickerSearchEntry] = [] var index = 0 - var existingStickerIds = Set() + var existingStickerIds = Set() for sticker in stickers { if let id = sticker.file.id, !existingStickerIds.contains(id) { entries.append(.sticker(index: index, code: nil, stickerItem: sticker, theme: self.theme)) @@ -727,7 +722,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { private func packs(from packs: FoundStickerSets) -> [StickerPaneSearchPack] { var result: [StickerPaneSearchPack] = [] - var existingIds = Set() + var existingIds = Set() for (collectionId, info, _, installed) in packs.infos { guard !existingIds.contains(collectionId), let info = info as? StickerPackCollectionInfo else { continue @@ -748,7 +743,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { private func entries(packItems: [StickerPackItem]) -> [StickerSearchEntry] { var entries: [StickerSearchEntry] = [] - var existingStickerIds = Set() + var existingStickerIds = Set() var index = 0 for item in packItems { let file = item.file._parse() @@ -786,7 +781,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { return !selectedPack.installed && !self.installedPackIds.contains(selectedPack.info.id) } - func setPackInstalledState(id: ItemCollectionId, installed: Bool, transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut)) { + func setPackInstalledState(id: EngineItemCollectionId, installed: Bool, transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut)) { if installed { self.installedPackIds.insert(id) } else { diff --git a/submodules/TelegramUI/Components/ChatTitleView/BUILD b/submodules/TelegramUI/Components/ChatTitleView/BUILD index aafb2e9ff0..4d9fc0c009 100644 --- a/submodules/TelegramUI/Components/ChatTitleView/BUILD +++ b/submodules/TelegramUI/Components/ChatTitleView/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/LegacyComponents:LegacyComponents", "//submodules/TelegramPresentationData:TelegramPresentationData", diff --git a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift index 283fc51bd4..f45f442812 100644 --- a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift +++ b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import AsyncDisplayKit import Display -import Postbox import TelegramCore import SwiftSignalKit import LegacyComponents @@ -29,15 +28,15 @@ private let subtitleFont = Font.regular(13.0) public enum ChatTitleContent: Equatable { public struct PeerData: Equatable { - public var peerId: PeerId - public var peer: Peer? + public var peerId: EnginePeer.Id + public var peer: EngineRawPeer? public var isContact: Bool public var isSavedMessages: Bool public var notificationSettings: TelegramPeerNotificationSettings? - public var peerPresences: [PeerId: PeerPresence] - public var cachedData: CachedPeerData? - - public init(peerId: PeerId, peer: Peer?, isContact: Bool, isSavedMessages: Bool, notificationSettings: TelegramPeerNotificationSettings?, peerPresences: [PeerId: PeerPresence], cachedData: CachedPeerData?) { + public var peerPresences: [EnginePeer.Id: EngineRawPeerPresence] + public var cachedData: EngineCachedPeerData? + + public init(peerId: EnginePeer.Id, peer: EngineRawPeer?, isContact: Bool, isSavedMessages: Bool, notificationSettings: TelegramPeerNotificationSettings?, peerPresences: [EnginePeer.Id: EngineRawPeerPresence], cachedData: EngineCachedPeerData?) { self.peerId = peerId self.peer = peer self.isContact = isContact @@ -47,7 +46,7 @@ public enum ChatTitleContent: Equatable { self.cachedData = cachedData } - public init(peerView: PeerView) { + public init(peerView: EngineRawPeerView) { self.init(peerId: peerView.peerId, peer: peerViewMainPeer(peerView), isContact: peerView.peerIsContact, isSavedMessages: false, notificationSettings: peerView.notificationSettings as? TelegramPeerNotificationSettings, peerPresences: peerView.peerPresences, cachedData: peerView.cachedData) } diff --git a/submodules/TelegramUI/Components/ComposePollScreen/Sources/StickerAttachmentScreen.swift b/submodules/TelegramUI/Components/ComposePollScreen/Sources/StickerAttachmentScreen.swift index 7ea3af3a22..45a131ec30 100644 --- a/submodules/TelegramUI/Components/ComposePollScreen/Sources/StickerAttachmentScreen.swift +++ b/submodules/TelegramUI/Components/ComposePollScreen/Sources/StickerAttachmentScreen.swift @@ -3,7 +3,6 @@ import UIKit import Display import AccountContext import TelegramCore -import Postbox import SwiftSignalKit import TelegramPresentationData import ComponentFlow @@ -238,26 +237,19 @@ final class StickerAttachmentScreenComponent: Component { return } - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks) let _ = (combineLatest( - context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), - context.account.postbox.combinedView(keys: [viewKey]) + context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCollections.InstalledPackIds(namespace: Namespaces.ItemCollection.CloudEmojiPacks)), + context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks)) ) |> take(1) - |> deliverOnMainQueue).start(next: { [weak self] emojiPacksView, views in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return - } + |> deliverOnMainQueue).start(next: { [weak self] installedIds, items in guard let self else { return } - - var installedCollectionIds = Set() - for (id, _, _) in emojiPacksView.collectionInfos { - installedCollectionIds.insert(id) - } - - let stickerPacks = view.items.map({ $0.contents.get(FeaturedStickerPackItem.self)! }).filter({ + + let installedCollectionIds = Set(installedIds) + + let stickerPacks = items.map({ $0.contents.get(FeaturedStickerPackItem.self)! }).filter({ !installedCollectionIds.contains($0.info.id) }) @@ -289,18 +281,14 @@ final class StickerAttachmentScreenComponent: Component { openSearch: { }, addGroupAction: { [weak self] groupId, isPremiumLocked, _ in - guard let self, let component = self.component, let collectionId = groupId.base as? ItemCollectionId else { + guard let self, let component = self.component, let collectionId = groupId.base as? EngineItemCollectionId else { return } let context = component.context - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks) - let _ = (context.account.postbox.combinedView(keys: [viewKey]) + let _ = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks)) |> take(1) - |> deliverOnMainQueue).start(next: { views in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return - } - for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + |> deliverOnMainQueue).start(next: { items in + for featuredStickerPack in items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { if featuredStickerPack.info.id == collectionId { let _ = (context.engine.stickers.loadedStickerPack(reference: .id(id: featuredStickerPack.info.id.id, accessHash: featuredStickerPack.info.accessHash), forceActualized: false) |> mapToSignal { result -> Signal in @@ -466,7 +454,7 @@ final class StickerAttachmentScreenComponent: Component { appendUnicodeEmoji() } - var existingIds = Set() + var existingIds = Set() for itemFile in foundEmoji.items { if existingIds.contains(itemFile.fileId) { continue @@ -532,7 +520,7 @@ final class StickerAttachmentScreenComponent: Component { |> mapToSignal { files, isFinalResult -> Signal<(items: [EmojiPagerContentComponent.ItemGroup], isFinalResult: Bool), NoError> in var items: [EmojiPagerContentComponent.Item] = [] - var existingIds = Set() + var existingIds = Set() for itemFile in files { if existingIds.contains(itemFile.fileId) { continue @@ -649,14 +637,13 @@ final class StickerAttachmentScreenComponent: Component { let context = component.context let presentationData = context.sharedContext.currentPresentationData.with { $0 } if groupId == AnyHashable("featuredTop") { - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedStickerPacks) - let _ = (context.account.postbox.combinedView(keys: [viewKey]) + let _ = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedStickerPacks)) |> take(1) - |> deliverOnMainQueue).start(next: { [weak self] views in - guard let self, let controller = self.environment?.controller(), let view = views.views[viewKey] as? OrderedItemListView else { + |> deliverOnMainQueue).start(next: { [weak self] items in + guard let self, let controller = self.environment?.controller() else { return } - for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + for featuredStickerPack in items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { if featuredStickerPack.topItems.contains(where: { $0.file.fileId == file.fileId }) { controller.push(FeaturedStickersScreen( context: context, @@ -670,7 +657,7 @@ final class StickerAttachmentScreenComponent: Component { return true } )) - + break } } @@ -699,18 +686,14 @@ final class StickerAttachmentScreenComponent: Component { } }, addGroupAction: { [weak self] groupId, isPremiumLocked, _ in - guard let strongSelf = self, let component = strongSelf.component, let collectionId = groupId.base as? ItemCollectionId else { + guard let strongSelf = self, let component = strongSelf.component, let collectionId = groupId.base as? EngineItemCollectionId else { return } let context = component.context - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedStickerPacks) - let _ = (context.account.postbox.combinedView(keys: [viewKey]) + let _ = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedStickerPacks)) |> take(1) - |> deliverOnMainQueue).start(next: { views in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return - } - for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + |> deliverOnMainQueue).start(next: { items in + for featuredStickerPack in items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { if featuredStickerPack.info.id == collectionId { let _ = (context.engine.stickers.loadedStickerPack(reference: .id(id: featuredStickerPack.info.id.id, accessHash: featuredStickerPack.info.accessHash), forceActualized: false) |> mapToSignal { result -> Signal in @@ -756,15 +739,11 @@ final class StickerAttachmentScreenComponent: Component { ])]) context.sharedContext.mainWindow?.presentInGlobalOverlay(actionSheet) } else if groupId == AnyHashable("featuredTop") { - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedStickerPacks) - let _ = (context.account.postbox.combinedView(keys: [viewKey]) + let _ = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedStickerPacks)) |> take(1) - |> deliverOnMainQueue).start(next: { views in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return - } + |> deliverOnMainQueue).start(next: { items in var stickerPackIds: [Int64] = [] - for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + for featuredStickerPack in items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { stickerPackIds.append(featuredStickerPack.info.id.id) } let _ = ApplicationSpecificNotice.setDismissedTrendingStickerPacks(accountManager: context.sharedContext.accountManager, values: stickerPackIds).start() @@ -808,7 +787,7 @@ final class StickerAttachmentScreenComponent: Component { |> mapToSignal { files -> Signal<(items: [EmojiPagerContentComponent.ItemGroup], isFinalResult: Bool), NoError> in var items: [EmojiPagerContentComponent.Item] = [] - var existingIds = Set() + var existingIds = Set() for item in files.items { let itemFile = item.file if existingIds.contains(itemFile.fileId) { diff --git a/submodules/TelegramUI/Components/ForumCreateTopicScreen/Sources/ForumCreateTopicScreen.swift b/submodules/TelegramUI/Components/ForumCreateTopicScreen/Sources/ForumCreateTopicScreen.swift index 56160337cd..4eecc29534 100644 --- a/submodules/TelegramUI/Components/ForumCreateTopicScreen/Sources/ForumCreateTopicScreen.swift +++ b/submodules/TelegramUI/Components/ForumCreateTopicScreen/Sources/ForumCreateTopicScreen.swift @@ -15,7 +15,6 @@ import MultilineTextComponent import EmojiStatusComponent import PremiumUI import ProgressNavigationButtonNode -import Postbox import SwitchComponent private final class TitleFieldComponent: Component { @@ -898,21 +897,17 @@ private final class ForumCreateTopicScreenComponent: CombinedComponent { openSearch: { }, addGroupAction: { groupId, isPremiumLocked, _ in - guard let collectionId = groupId.base as? ItemCollectionId else { + guard let collectionId = groupId.base as? EngineItemCollectionId else { return } - - let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks) - let _ = (accountContext.account.postbox.combinedView(keys: [viewKey]) + + let _ = (accountContext.engine.data.subscribe(TelegramEngine.EngineData.Item.Collections.FeaturedEmojiPacks()) |> take(1) - |> deliverOnMainQueue).start(next: { views in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return - } - for featuredEmojiPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + |> deliverOnMainQueue).start(next: { items in + for featuredEmojiPack in items { if featuredEmojiPack.info.id == collectionId { let _ = accountContext.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info._parse(), items: featuredEmojiPack.topItems).start() - + break } } diff --git a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/ChatGiftPreviewItem.swift b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/ChatGiftPreviewItem.swift index 56467283cd..a155663706 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/ChatGiftPreviewItem.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftSetupScreen/Sources/ChatGiftPreviewItem.swift @@ -4,7 +4,6 @@ import Display import AsyncDisplayKit import SwiftSignalKit import TelegramCore -import Postbox import TelegramPresentationData import TelegramUIPreferences import ItemListUI @@ -220,21 +219,21 @@ final class ChatGiftPreviewItemNode: ListViewItemNode { var insets: UIEdgeInsets let separatorHeight = UIScreenPixel - let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(1)) + let peerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudChannel, id: EnginePeer.Id.Id._internalFromInt64Value(1)) let chatPeerId = item.chatPeerId ?? peerId var items: [ListViewItem] = [] for _ in 0 ..< 1 { let authorPeerId = item.context.account.peerId - var peers = SimpleDictionary() - let messages = SimpleDictionary() + var peers = EngineSimpleDictionary() + let messages = EngineSimpleDictionary() for peer in item.peers { peers[peer.id] = peer._asPeer() } - let media: [Media] + let media: [EngineRawMedia] switch item.subject { case let .premium(months, amount, currency): media = [ @@ -250,7 +249,7 @@ final class ChatGiftPreviewItemNode: ListViewItemNode { ] } - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: "", attributes: [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message = EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: "", attributes: [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) } diff --git a/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackSetupController.swift b/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackSetupController.swift index 9c4eff3f94..d01e72792f 100644 --- a/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackSetupController.swift +++ b/submodules/TelegramUI/Components/GroupStickerPackSetupController/Sources/GroupStickerPackSetupController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -37,7 +36,7 @@ private enum GroupStickerPackSection: Int32 { private enum GroupStickerPackEntryId: Hashable { case index(Int32) - case pack(ItemCollectionId) + case pack(EngineItemCollectionId) static func ==(lhs: GroupStickerPackEntryId, rhs: GroupStickerPackEntryId) -> Bool { switch lhs { @@ -265,7 +264,7 @@ private struct GroupStickerPackSetupControllerState: Equatable { var searchingPacks: Bool } -private func groupStickerPackSetupControllerEntries(context: AccountContext, presentationData: PresentationData, searchText: String, view: CombinedView, initialData: InitialStickerPackData?, searchState: GroupStickerPackSearchState, stickerSettings: StickerSettings, isEmoji: Bool) -> [GroupStickerPackEntry] { +private func groupStickerPackSetupControllerEntries(context: AccountContext, presentationData: PresentationData, searchText: String, packsEntries: [EngineRawItemCollectionInfoEntry], initialData: InitialStickerPackData?, searchState: GroupStickerPackSearchState, stickerSettings: StickerSettings, isEmoji: Bool) -> [GroupStickerPackEntry] { if initialData == nil { return [] } @@ -284,39 +283,34 @@ private func groupStickerPackSetupControllerEntries(context: AccountContext, pre } entries.append(.searchInfo(presentationData.theme, isEmoji ? presentationData.strings.Group_Emoji_Info : presentationData.strings.Channel_Stickers_CreateYourOwn)) - let namespace = isEmoji ? Namespaces.ItemCollection.CloudEmojiPacks : Namespaces.ItemCollection.CloudStickerPacks - if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespace])] as? ItemCollectionInfosView { - if let packsEntries = stickerPacksView.entriesByNamespace[namespace] { - if !packsEntries.isEmpty { - entries.append(.packsTitle(presentationData.theme, isEmoji ? presentationData.strings.Group_Emoji_YourEmoji : presentationData.strings.Channel_Stickers_YourStickers)) + if !packsEntries.isEmpty { + entries.append(.packsTitle(presentationData.theme, isEmoji ? presentationData.strings.Group_Emoji_YourEmoji : presentationData.strings.Channel_Stickers_YourStickers)) + } + + var index: Int32 = 0 + for entry in packsEntries { + if let info = entry.info as? StickerPackCollectionInfo { + var selected = false + if case let .found(found) = searchState { + selected = found.info.id == info.id } - - var index: Int32 = 0 - for entry in packsEntries { - if let info = entry.info as? StickerPackCollectionInfo { - var selected = false - if case let .found(found) = searchState { - selected = found.info.id == info.id - } - let count = info.count == 0 ? entry.count : info.count - - let thumbnail: StickerPackItem? - if let thumbnailRep = info.thumbnail { - thumbnail = StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: 0), file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: thumbnailRep.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: info.immediateThumbnailData, mimeType: "", size: nil, attributes: [], alternativeRepresentations: []), indexKeys: []) - } else { - thumbnail = entry.firstItem as? StickerPackItem - } - entries.append(.pack(index, presentationData.theme, presentationData.strings, info, thumbnail, isEmoji ? presentationData.strings.StickerPack_EmojiCount(count) : presentationData.strings.StickerPack_StickerCount(count), context.sharedContext.energyUsageSettings.loopStickers, selected)) - index += 1 - } + let count = info.count == 0 ? entry.count : info.count + + let thumbnail: StickerPackItem? + if let thumbnailRep = info.thumbnail { + thumbnail = StickerPackItem(index: EngineItemCollectionItemIndex(index: 0, id: 0), file: TelegramMediaFile(fileId: EngineMedia.Id(namespace: 0, id: 0), partialReference: nil, resource: thumbnailRep.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: info.immediateThumbnailData, mimeType: "", size: nil, attributes: [], alternativeRepresentations: []), indexKeys: []) + } else { + thumbnail = entry.firstItem as? StickerPackItem } + entries.append(.pack(index, presentationData.theme, presentationData.strings, info, thumbnail, isEmoji ? presentationData.strings.StickerPack_EmojiCount(count) : presentationData.strings.StickerPack_StickerCount(count), context.sharedContext.energyUsageSettings.loopStickers, selected)) + index += 1 } } return entries } -public func groupStickerPackSetupController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: PeerId, isEmoji: Bool = false, currentPackInfo: StickerPackCollectionInfo?, completion: ((StickerPackCollectionInfo?) -> Void)? = nil) -> ViewController { +public func groupStickerPackSetupController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: EnginePeer.Id, isEmoji: Bool = false, currentPackInfo: StickerPackCollectionInfo?, completion: ((StickerPackCollectionInfo?) -> Void)? = nil) -> ViewController { let initialState = GroupStickerPackSetupControllerState(isSaving: false, searchingPacks: false) let statePromise = ValuePromise(initialState, ignoreRepeated: true) @@ -353,12 +347,12 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres } } - let stickerPacks = Promise() - stickerPacks.set(context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [isEmoji ? Namespaces.ItemCollection.CloudEmojiPacks : Namespaces.ItemCollection.CloudStickerPacks])])) + let stickerPacks = Promise<[EngineRawItemCollectionInfoEntry]>() + stickerPacks.set(context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCollections.InstalledPackInfos(namespace: isEmoji ? Namespaces.ItemCollection.CloudEmojiPacks : Namespaces.ItemCollection.CloudStickerPacks))) let searchState = Promise<(String, GroupStickerPackSearchState)>() searchState.set(combineLatest(searchText.get(), initialData.get(), stickerPacks.get()) - |> mapToSignal { searchText, initialData, view -> Signal<(String, GroupStickerPackSearchState), NoError> in + |> mapToSignal { searchText, initialData, packsEntries -> Signal<(String, GroupStickerPackSearchState), NoError> in if let initialData = initialData { if searchText.isEmpty { return .single((searchText, .none)) @@ -368,15 +362,10 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres } return .single((searchText, .found(StickerPackData(info: data.info, item: data.item)))) } else { - let namespace = isEmoji ? Namespaces.ItemCollection.CloudEmojiPacks : Namespaces.ItemCollection.CloudStickerPacks - if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespace])] as? ItemCollectionInfosView { - if let packsEntries = stickerPacksView.entriesByNamespace[namespace] { - for entry in packsEntries { - if let info = entry.info as? StickerPackCollectionInfo { - if info.shortName.lowercased() == searchText.lowercased() { - return .single((searchText, .found(StickerPackData(info: info, item: entry.firstItem as? StickerPackItem)))) - } - } + for entry in packsEntries { + if let info = entry.info as? StickerPackCollectionInfo { + if info.shortName.lowercased() == searchText.lowercased() { + return .single((searchText, .found(StickerPackData(info: info, item: entry.firstItem as? StickerPackItem)))) } } } @@ -405,7 +394,7 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres } }) - var navigateToChatControllerImpl: ((PeerId) -> Void)? + var navigateToChatControllerImpl: ((EnginePeer.Id) -> Void)? var dismissInputImpl: (() -> Void)? var dismissImpl: (() -> Void)? @@ -449,7 +438,7 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData let signal = combineLatest(presentationData, statePromise.get() |> deliverOnMainQueue, initialData.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, searchState.get() |> deliverOnMainQueue, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]) |> deliverOnMainQueue) - |> map { presentationData, state, initialData, view, searchState, sharedData -> (ItemListControllerState, (ItemListNodeState, Any)) in + |> map { presentationData, state, initialData, packsEntries, searchState, sharedData -> (ItemListControllerState, (ItemListNodeState, Any)) in var stickerSettings = StickerSettings.defaultSettings if let value = sharedData.entries[ApplicationSpecificSharedDataKeys.stickerSettings]?.get(StickerSettings.self) { stickerSettings = value @@ -539,7 +528,7 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme) } - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: groupStickerPackSetupControllerEntries(context: context, presentationData: presentationData, searchText: searchState.0, view: view, initialData: initialData, searchState: searchState.1, stickerSettings: stickerSettings, isEmoji: isEmoji), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: hasData && hadData) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: groupStickerPackSetupControllerEntries(context: context, presentationData: presentationData, searchText: searchState.0, packsEntries: packsEntries, initialData: initialData, searchState: searchState.1, stickerSettings: stickerSettings, isEmoji: isEmoji), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: hasData && hadData) return (controllerState, (listState, arguments)) } |> afterDisposed { actionsDisposable.dispose() diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/CreateLinkScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/CreateLinkScreen.swift index 30dc339a9a..84788e3fc0 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/CreateLinkScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/CreateLinkScreen.swift @@ -4,7 +4,6 @@ import AsyncDisplayKit import Display import ComponentFlow import SwiftSignalKit -import Postbox import TelegramCore import Markdown import TextFormat @@ -486,14 +485,14 @@ private final class CreateLinkSheetComponent: CombinedComponent { } } - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] attributes.append(TextEntitiesMessageAttribute(entities: [.init(range: 0 ..< (text as NSString).length, type: .Url)])) if !self.dismissed { attributes.append(WebpagePreviewMessageAttribute(leadingPreview: !self.positionBelowText, forceLargeMedia: self.largeMedia ?? webpageHasLargeMedia, isManuallyAdded: false, isSafe: true)) } - - let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: text, attributes: attributes, media: effectiveMedia.flatMap { [$0] } ?? [], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + + let peerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)) + let message = EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: text, attributes: attributes, media: effectiveMedia.flatMap { [$0] } ?? [], peers: EngineSimpleDictionary(), associatedMessages: EngineSimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) let completion = controller.completion diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 1a30ad00b4..5a77bf9af7 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -9044,13 +9044,9 @@ func hasFirstResponder(_ view: UIView) -> Bool { } private func allowedStoryReactions(context: AccountContext) -> Signal<[ReactionItem], NoError> { - let viewKey: PostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudTopReactions) - let topReactions = context.account.postbox.combinedView(keys: [viewKey]) - |> map { views -> [RecentReactionItem] in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return [] - } - return view.items.compactMap { item -> RecentReactionItem? in + let topReactions = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudTopReactions)) + |> map { items -> [RecentReactionItem] in + return items.compactMap { item -> RecentReactionItem? in return item.contents.get(RecentReactionItem.self) } } diff --git a/submodules/TelegramUI/Components/MediaManager/PeerMessagesMediaPlaylist/Sources/PeerMessagesMediaPlaylist.swift b/submodules/TelegramUI/Components/MediaManager/PeerMessagesMediaPlaylist/Sources/PeerMessagesMediaPlaylist.swift index 00da2e081c..16d7df1a56 100644 --- a/submodules/TelegramUI/Components/MediaManager/PeerMessagesMediaPlaylist/Sources/PeerMessagesMediaPlaylist.swift +++ b/submodules/TelegramUI/Components/MediaManager/PeerMessagesMediaPlaylist/Sources/PeerMessagesMediaPlaylist.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramUIPreferences import AccountContext @@ -10,10 +9,10 @@ import MusicAlbumArtResources import TextFormat private enum PeerMessagesMediaPlaylistLoadAnchor { - case messageId(MessageId) - case index(MessageIndex) - - var id: MessageId { + case messageId(EngineMessage.Id) + case index(EngineMessage.Index) + + var id: EngineMessage.Id { switch self { case let .messageId(id): return id @@ -33,7 +32,7 @@ struct MessageMediaPlaylistItemStableId: Hashable { let stableId: UInt32 } -private func extractFileMedia(_ message: Message) -> TelegramMediaFile? { +private func extractFileMedia(_ message: EngineRawMessage) -> TelegramMediaFile? { var file: TelegramMediaFile? for media in message.media { if let media = media as? TelegramMediaFile { @@ -52,10 +51,10 @@ private func extractFileMedia(_ message: Message) -> TelegramMediaFile? { public final class MessageMediaPlaylistItem: SharedMediaPlaylistItem { public let id: SharedMediaPlaylistItemId - public let message: Message + public let message: EngineRawMessage public let isSavedMusic: Bool - - public init(message: Message, isSavedMusic: Bool) { + + public init(message: EngineRawMessage, isSavedMusic: Bool) { self.id = PeerMessagesMediaPlaylistItemId(messageId: message.id, messageIndex: message.index) self.message = message self.isSavedMusic = isSavedMusic @@ -162,11 +161,11 @@ private enum NavigatedMessageFromViewPosition { case exact } -private func aroundMessagesFromMessages(_ messages: [Message], centralIndex: MessageIndex) -> [Message] { +private func aroundMessagesFromMessages(_ messages: [EngineRawMessage], centralIndex: EngineMessage.Index) -> [EngineRawMessage] { guard let index = messages.firstIndex(where: { $0.index.id == centralIndex.id }) else { return [] } - var result: [Message] = [] + var result: [EngineRawMessage] = [] if index != 0 { for i in (0 ..< index).reversed() { result.append(messages[i]) @@ -182,7 +181,7 @@ private func aroundMessagesFromMessages(_ messages: [Message], centralIndex: Mes return result } -private func aroundMessagesFromView(view: MessageHistoryView, centralIndex: MessageIndex) -> [Message] { +private func aroundMessagesFromView(view: EngineRawMessageHistoryView, centralIndex: EngineMessage.Index) -> [EngineRawMessage] { let filteredEntries = view.entries.filter { entry in if entry.message.minAutoremoveOrClearTimeout == viewOnceTimeout { return false @@ -194,7 +193,7 @@ private func aroundMessagesFromView(view: MessageHistoryView, centralIndex: Mess guard let index = filteredEntries.firstIndex(where: { $0.index.id == centralIndex.id }) else { return [] } - var result: [Message] = [] + var result: [EngineRawMessage] = [] if index != 0 { for i in (0 ..< index).reversed() { result.append(filteredEntries[i].message) @@ -210,7 +209,7 @@ private func aroundMessagesFromView(view: MessageHistoryView, centralIndex: Mess return result } -private func navigatedMessageFromMessages(_ messages: [Message], anchorIndex: MessageIndex, position: NavigatedMessageFromViewPosition) -> (message: Message, around: [Message], exact: Bool)? { +private func navigatedMessageFromMessages(_ messages: [EngineRawMessage], anchorIndex: EngineMessage.Index, position: NavigatedMessageFromViewPosition) -> (message: EngineRawMessage, around: [EngineRawMessage], exact: Bool)? { var index = 0 for message in messages { if message.index.id == anchorIndex.id { @@ -249,7 +248,7 @@ private func navigatedMessageFromMessages(_ messages: [Message], anchorIndex: Me } } -private func navigatedMessageFromView(_ view: MessageHistoryView, anchorIndex: MessageIndex, position: NavigatedMessageFromViewPosition, reversed: Bool) -> (message: Message, around: [Message], exact: Bool)? { +private func navigatedMessageFromView(_ view: EngineRawMessageHistoryView, anchorIndex: EngineMessage.Index, position: NavigatedMessageFromViewPosition, reversed: Bool) -> (message: EngineRawMessage, around: [EngineRawMessage], exact: Bool)? { var index = 0 let filteredEntries = view.entries.filter { entry in @@ -348,10 +347,10 @@ private func navigatedMessageFromView(_ view: MessageHistoryView, anchorIndex: M } private struct PlaybackStack { - var ids: [MessageId] = [] - var set: Set = [] + var ids: [EngineMessage.Id] = [] + var set: Set = [] - mutating func resetToId(_ id: MessageId) { + mutating func resetToId(_ id: EngineMessage.Id) { if self.set.contains(id) { if let index = self.ids.firstIndex(of: id) { for i in (index + 1) ..< self.ids.count { @@ -369,7 +368,7 @@ private struct PlaybackStack { } } - mutating func push(_ id: MessageId) { + mutating func push(_ id: EngineMessage.Id) { if self.set.contains(id) { if let index = self.ids.firstIndex(of: id) { self.ids.remove(at: index) @@ -379,7 +378,7 @@ private struct PlaybackStack { self.set.insert(id) } - mutating func pop() -> MessageId? { + mutating func pop() -> EngineMessage.Id? { if !self.ids.isEmpty { let id = self.ids.removeLast() self.set.remove(id) @@ -411,8 +410,8 @@ public final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { private var playbackStack = PlaybackStack() - private var currentItem: (current: Message, around: [Message])? - private var currentlyObservedMessageId: MessageId? + private var currentItem: (current: EngineRawMessage, around: [EngineRawMessage])? + private var currentlyObservedMessageId: EngineMessage.Id? private let currentlyObservedMessageDisposable = MetaDisposable() private var loadingItem: Bool = false private var loadingMore: Bool = false @@ -564,7 +563,7 @@ public final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { self.loadingItem = true self.updateState() - let namespaces: MessageIdNamespaces + let namespaces: EngineMessageIdNamespaces if Namespaces.Message.allScheduled.contains(anchor.id.namespace) { namespaces = .just(Namespaces.Message.allScheduled) } else if Namespaces.Message.allQuickReply.contains(anchor.id.namespace) { @@ -579,13 +578,13 @@ public final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { case let .messages(chatLocation, tagMask, _): let historySignal = self.context.account.postbox.messageAtId(messageId) |> take(1) - |> mapToSignal { message -> Signal<(Message, [Message])?, NoError> in + |> mapToSignal { message -> Signal<(EngineRawMessage, [EngineRawMessage])?, NoError> in guard let message = message else { return .single(nil) } return self.context.account.postbox.aroundMessageHistoryViewForLocation(self.context.chatLocationInput(for: chatLocation, contextHolder: self.chatLocationContextHolder ?? Atomic(value: nil)), anchor: .index(message.index), ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: .tag(tagMask), appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: []) - |> mapToSignal { view -> Signal<(Message, [Message])?, NoError> in + |> mapToSignal { view -> Signal<(EngineRawMessage, [EngineRawMessage])?, NoError> in if let (message, aroundMessages, _) = navigatedMessageFromView(view.0, anchorIndex: message.index, position: .exact, reversed: reversed) { return .single((message, aroundMessages)) } else { @@ -658,7 +657,7 @@ public final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { case let .index(index): switch self.messagesLocation.effectiveLocation(context: self.context) { case let .messages(chatLocation, tagMask, _): - var inputIndex: Signal? + var inputIndex: Signal? let looping = self.looping switch self.order { case .regular, .reversed: @@ -693,12 +692,12 @@ public final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { } } let historySignal = (inputIndex ?? .single(nil)) - |> mapToSignal { inputIndex -> Signal<(Message, [Message])?, NoError> in + |> mapToSignal { inputIndex -> Signal<(EngineRawMessage, [EngineRawMessage])?, NoError> in guard let inputIndex = inputIndex else { return .single(nil) } return self.context.account.postbox.aroundMessageHistoryViewForLocation(self.context.chatLocationInput(for: chatLocation, contextHolder: self.chatLocationContextHolder ?? Atomic(value: nil)), anchor: .index(inputIndex), ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: .tag(tagMask), appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: []) - |> mapToSignal { view -> Signal<(Message, [Message])?, NoError> in + |> mapToSignal { view -> Signal<(EngineRawMessage, [EngineRawMessage])?, NoError> in let position: NavigatedMessageFromViewPosition switch navigation { case .later: @@ -721,14 +720,14 @@ public final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { } if case .all = looping { - let viewIndex: HistoryViewInputAnchor + let viewIndex: EngineHistoryViewInputAnchor if case .earlier = navigation { viewIndex = .upperBound } else { viewIndex = .lowerBound } return self.context.account.postbox.aroundMessageHistoryViewForLocation(self.context.chatLocationInput(for: chatLocation, contextHolder: self.chatLocationContextHolder ?? Atomic(value: nil)), anchor: viewIndex, ignoreMessagesInTimestampRange: nil, ignoreMessageIds: Set(), count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tag: .tag(tagMask), appendMessagesFromTheSameGroup: false, namespaces: namespaces, orderStatistics: []) - |> mapToSignal { view -> Signal<(Message, [Message])?, NoError> in + |> mapToSignal { view -> Signal<(EngineRawMessage, [EngineRawMessage])?, NoError> in let position: NavigatedMessageFromViewPosition switch navigation { case .later, .random: @@ -736,7 +735,7 @@ public final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { case .earlier: position = .later } - if let (message, aroundMessages, _) = navigatedMessageFromView(view.0, anchorIndex: MessageIndex.absoluteLowerBound(), position: position, reversed: reversed) { + if let (message, aroundMessages, _) = navigatedMessageFromView(view.0, anchorIndex: EngineMessage.Index.absoluteLowerBound(), position: position, reversed: reversed) { return .single((message, aroundMessages)) } else { return .single(nil) @@ -791,7 +790,7 @@ public final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { case .savedMusic: fatalError() case let .custom(messages, _, _, loadMore, _): - let inputIndex: Signal + let inputIndex: Signal let looping = self.looping switch self.order { case .regular, .reversed: @@ -800,7 +799,7 @@ public final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { var playbackStack = self.playbackStack inputIndex = messages |> take(1) - |> map { messages, _, _ -> MessageIndex in + |> map { messages, _, _ -> EngineMessage.Index in if case let .random(previous) = navigation, previous { let _ = playbackStack.pop() while true { @@ -817,10 +816,10 @@ public final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { } } let historySignal = inputIndex - |> mapToSignal { inputIndex -> Signal<((Message, [Message])?, Int, Bool), NoError> in + |> mapToSignal { inputIndex -> Signal<((EngineRawMessage, [EngineRawMessage])?, Int, Bool), NoError> in return messages |> take(1) - |> mapToSignal { messages, _, hasMore -> Signal<((Message, [Message])?, Int, Bool), NoError> in + |> mapToSignal { messages, _, hasMore -> Signal<((EngineRawMessage, [EngineRawMessage])?, Int, Bool), NoError> in let position: NavigatedMessageFromViewPosition switch navigation { case .later: diff --git a/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/BUILD b/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/BUILD index 12a157c72b..0f5f193a9a 100644 --- a/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/BUILD +++ b/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/BUILD @@ -18,7 +18,6 @@ swift_library( "//submodules/Components/ViewControllerComponent", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/TelegramCore", - "//submodules/Postbox", "//submodules/AccountContext", "//submodules/TelegramUI/Components/EntityKeyboard", "//submodules/TelegramUI/Components/SwitchComponent", diff --git a/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift b/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift index b15f8aa782..52985f43f6 100644 --- a/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift +++ b/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift @@ -8,7 +8,6 @@ import AppBundle import ViewControllerComponent import AccountContext import TelegramCore -import Postbox import SwiftSignalKit import EntityKeyboard import MultilineTextComponent @@ -698,14 +697,14 @@ final class PeerAllowedReactionsScreenComponent: Component { let remoteSignal = emojiSearchContext.state return combineLatest( - context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000) |> take(1), + context.engine.itemCollections.allItems(namespace: Namespaces.ItemCollection.CloudEmojiPacks) |> take(1), context.engine.stickers.availableReactions() |> take(1), hasPremium |> take(1), remotePacksSignal, remoteSignal, localPacksSignal ) - |> map { view, availableReactions, hasPremium, foundPacks, foundEmoji, foundLocalPacks -> (groups: [EmojiPagerContentComponent.ItemGroup], canLoadMore: Bool, isSearching: Bool, searchContext: EmojiSearchContext?) in + |> map { rawItems, availableReactions, hasPremium, foundPacks, foundEmoji, foundLocalPacks -> (groups: [EmojiPagerContentComponent.ItemGroup], canLoadMore: Bool, isSearching: Bool, searchContext: EmojiSearchContext?) in var result: [(String, TelegramMediaFile.Accessor?, String)] = [] var allEmoticons: [String: String] = [:] @@ -730,8 +729,8 @@ final class PeerAllowedReactionsScreenComponent: Component { } } - for entry in view.entries { - guard let item = entry.item as? StickerPackItem else { + for rawItem in rawItems { + guard let item = rawItem as? StickerPackItem else { continue } if !item.file.isPremiumEmoji { @@ -747,7 +746,7 @@ final class PeerAllowedReactionsScreenComponent: Component { var items: [EmojiPagerContentComponent.Item] = [] - var existingIds = Set() + var existingIds = Set() for item in result { if let itemFile = item.1 { if existingIds.contains(itemFile.fileId) { @@ -790,7 +789,7 @@ final class PeerAllowedReactionsScreenComponent: Component { combinedSets = foundLocalPacks combinedSets = combinedSets.merge(with: foundPacks.sets) - var existingCollectionIds = Set() + var existingCollectionIds = Set() for (collectionId, info, _, _) in combinedSets.infos { if !existingCollectionIds.contains(collectionId) { existingCollectionIds.insert(collectionId) @@ -876,7 +875,7 @@ final class PeerAllowedReactionsScreenComponent: Component { |> mapToSignal { files, isFinalResult -> Signal<(items: [EmojiPagerContentComponent.ItemGroup], isFinalResult: Bool), NoError> in var items: [EmojiPagerContentComponent.Item] = [] - var existingIds = Set() + var existingIds = Set() for itemFile in files { if existingIds.contains(itemFile.fileId) { continue @@ -1818,10 +1817,10 @@ public class PeerAllowedReactionsScreen: ViewControllerComponentContainer { public static func content(context: AccountContext, peerId: EnginePeer.Id) -> Signal { return combineLatest( context.engine.stickers.availableReactions(), - context.account.postbox.combinedView(keys: [.cachedPeerData(peerId: peerId)]) + context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.CachedData(id: peerId)) ) - |> mapToSignal { availableReactions, combinedView -> Signal in - guard let cachedDataView = combinedView.views[.cachedPeerData(peerId: peerId)] as? CachedPeerDataView, let cachedData = cachedDataView.cachedPeerData as? CachedChannelData else { + |> mapToSignal { availableReactions, cachedPeerData -> Signal in + guard let cachedData = cachedPeerData as? CachedChannelData else { return .complete() } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGifPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGifPaneNode.swift index c4fa7bddf6..339eb595d4 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGifPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGifPaneNode.swift @@ -3,7 +3,6 @@ import UIKit import Display import TelegramCore import SwiftSignalKit -import Postbox import TelegramPresentationData import AccountContext import ContextUI @@ -25,17 +24,17 @@ private let mediaBadgeBackgroundColor = UIColor(white: 0.0, alpha: 0.6) private let mediaBadgeTextColor = UIColor.white private final class VisualMediaItemInteraction { - let openMessage: (Message) -> Void - let openMessageContextActions: (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void - let toggleSelection: (MessageId, Bool) -> Void - - var hiddenMedia: [MessageId: [Media]] = [:] - var selectedMessageIds: Set? - + let openMessage: (EngineRawMessage) -> Void + let openMessageContextActions: (EngineRawMessage, ASDisplayNode, CGRect, ContextGesture?) -> Void + let toggleSelection: (EngineMessage.Id, Bool) -> Void + + var hiddenMedia: [EngineMessage.Id: [EngineRawMedia]] = [:] + var selectedMessageIds: Set? + init( - openMessage: @escaping (Message) -> Void, - openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, - toggleSelection: @escaping (MessageId, Bool) -> Void + openMessage: @escaping (EngineRawMessage) -> Void, + openMessageContextActions: @escaping (EngineRawMessage, ASDisplayNode, CGRect, ContextGesture?) -> Void, + toggleSelection: @escaping (EngineMessage.Id, Bool) -> Void ) { self.openMessage = openMessage self.openMessageContextActions = openMessageContextActions @@ -58,9 +57,9 @@ private final class VisualMediaItemNode: ASDisplayNode { private let fetchStatusDisposable = MetaDisposable() private let fetchDisposable = MetaDisposable() - private var resourceStatus: MediaResourceStatus? - - private var item: (VisualMediaItem, Media?, CGSize, CGSize?)? + private var resourceStatus: EngineMediaResourceStatus? + + private var item: (VisualMediaItem, EngineRawMedia?, CGSize, CGSize?)? private var theme: PresentationTheme? private var hasVisibility: Bool = false @@ -118,7 +117,7 @@ private final class VisualMediaItemNode: ASDisplayNode { if let (gesture, _) = recognizer.lastRecognizedGestureAndLocation { if case .tap = gesture { if let (item, _, _, _) = self.item { - var media: Media? + var media: EngineRawMedia? for value in item.message.media { if let image = value as? TelegramMediaImage { media = image @@ -150,8 +149,8 @@ private final class VisualMediaItemNode: ASDisplayNode { guard let message = self.item?.0.message else { return } - - var media: Media? + + var media: EngineRawMedia? for value in message.media { if let image = value as? TelegramMediaImage { media = image @@ -183,7 +182,7 @@ private final class VisualMediaItemNode: ASDisplayNode { return } self.theme = theme - var media: Media? + var media: EngineRawMedia? for value in item.message.media { if let image = value as? TelegramMediaImage { media = image @@ -417,11 +416,11 @@ private final class VisualMediaItemNode: ASDisplayNode { } private final class VisualMediaItem { - let message: Message + let message: EngineRawMessage let dimensions: CGSize let aspectRatio: CGFloat - - init(message: Message) { + + init(message: EngineRawMessage) { self.message = message var aspectRatio: CGFloat = 1.0 @@ -488,7 +487,7 @@ private final class FloatingHeaderNode: ASDisplayNode { } } -private func tagMaskForType(_ type: PeerInfoGifPaneNode.ContentType) -> MessageTags { +private func tagMaskForType(_ type: PeerInfoGifPaneNode.ContentType) -> EngineMessage.Tags { switch type { case .photoOrVideo: return .photoOrVideo @@ -616,7 +615,7 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDe } private let context: AccountContext - private let peerId: PeerId + private let peerId: EnginePeer.Id private let chatLocation: ChatLocation private let chatLocationContextHolder: Atomic private let chatControllerInteraction: ChatControllerInteraction @@ -651,7 +650,7 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDe private var visibleMediaItems: [UInt32: VisualMediaItemNode] = [:] private var numberOfItemsToRequest: Int = 50 - private var currentView: MessageHistoryView? + private var currentView: EngineRawMessageHistoryView? private var isRequestingView: Bool = false private var isFirstHistoryView: Bool = true @@ -667,7 +666,7 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDe return 0.0 } - init(context: AccountContext, chatControllerInteraction: ChatControllerInteraction, peerId: PeerId, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, contentType: ContentType) { + init(context: AccountContext, chatControllerInteraction: ChatControllerInteraction, peerId: EnginePeer.Id, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, contentType: ContentType) { self.context = context self.peerId = peerId self.chatLocation = chatLocation @@ -714,7 +713,7 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDe guard let strongSelf = self else { return } - var hiddenMedia: [MessageId: [Media]] = [:] + var hiddenMedia: [EngineMessage.Id: [EngineRawMedia]] = [:] for id in ids { if case let .chat(accountId, messageId, media) = id, accountId == strongSelf.context.account.id { hiddenMedia[messageId] = [media] @@ -781,7 +780,7 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDe })) } - private func updateHistory(view: MessageHistoryView, updateType: ViewUpdateType) { + private func updateHistory(view: EngineRawMessageHistoryView, updateType: EngineViewUpdateType) { self.currentView = view switch updateType { @@ -988,7 +987,7 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDe let (minVisibleIndex, maxVisibleIndex) = itemsLayout.visibleRange(rect: visibleRect) - var headerItem: Message? + var headerItem: EngineRawMessage? var validIds = Set() if minVisibleIndex <= maxVisibleIndex { diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift index dea0dfbc1c..b884a5cfee 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift @@ -1936,7 +1936,7 @@ func peerInfoScreenData( return (nil, value) } } else { - return context.peerChannelMemberCategoriesContextsManager.recentOnlineSmall(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) + return context.peerChannelMemberCategoriesContextsManager.recentOnlineSmall(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId) |> map { value -> (total: Int32?, recent: Int32?) in return (value.total, value.recent) } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoMembers.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoMembers.swift index 67d2a2d875..d19e07f18f 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoMembers.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoMembers.swift @@ -162,7 +162,7 @@ private final class PeerInfoMembersContextImpl { self.pushState() if peerId.namespace == Namespaces.Peer.CloudChannel { - let (disposable, control) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, requestUpdate: true, updated: { [weak self] state in + let (disposable, control) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, requestUpdate: true, updated: { [weak self] state in queue.async { guard let strongSelf = self else { return diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift index 997fd23427..367f40270f 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift @@ -4,7 +4,6 @@ import UIKit import Display import TelegramCore import SwiftSignalKit -import Postbox import TelegramPresentationData import PresentationDataUtils import AccountContext @@ -56,7 +55,7 @@ private final class VisualMediaItemInteraction { let openItemContextActions: (EngineStoryItem, ASDisplayNode, CGRect, ContextGesture?) -> Void let toggleSelection: (Int32, Bool) -> Void - var hiddenStories = Set() + var hiddenStories = Set() var selectedIds: Set? init( @@ -71,7 +70,7 @@ private final class VisualMediaItemInteraction { } private final class VisualMediaHoleAnchor: SparseItemGrid.HoleAnchor { - let storyId: StoryId + let storyId: EngineStoryId override var id: AnyHashable { return AnyHashable(self.storyId) } @@ -86,7 +85,7 @@ private final class VisualMediaHoleAnchor: SparseItemGrid.HoleAnchor { return self.localMonthTimestamp } - init(index: Int, storyId: StoryId, localMonthTimestamp: Int32) { + init(index: Int, storyId: EngineStoryId, localMonthTimestamp: Int32) { self.indexValue = index self.storyId = storyId self.localMonthTimestamp = localMonthTimestamp @@ -103,7 +102,7 @@ private final class VisualMediaItem: SparseItemGrid.Item { } let localMonthTimestamp: Int32 let peer: PeerReference - let storyId: StoryId + let storyId: EngineStoryId let story: EngineStoryItem let authorPeer: EnginePeer? let isPinned: Bool @@ -122,7 +121,7 @@ private final class VisualMediaItem: SparseItemGrid.Item { return VisualMediaHoleAnchor(index: self.index, storyId: self.storyId, localMonthTimestamp: self.localMonthTimestamp) } - init(index: Int, peer: PeerReference, storyId: StoryId, story: EngineStoryItem, authorPeer: EnginePeer?, isPinned: Bool, localMonthTimestamp: Int32, isReorderable: Bool, isEnabled: Bool) { + init(index: Int, peer: PeerReference, storyId: EngineStoryId, story: EngineStoryItem, authorPeer: EnginePeer?, isPinned: Bool, localMonthTimestamp: Int32, isReorderable: Bool, isEnabled: Bool) { self.indexValue = index self.peer = peer self.storyId = storyId @@ -855,7 +854,7 @@ private final class ItemLayer: CALayer, SparseItemGridLayer { binding.bindLayers(items: [item], layers: [displayItem], size: size, insets: insets, synchronous: .none) } else { if let layer = displayItem.layer as? ItemLayer { - var selectedMedia: Media? + var selectedMedia: EngineRawMedia? if let image = item.story.media._asMedia() as? TelegramMediaImage { selectedMedia = image } else if let file = item.story.media._asMedia() as? TelegramMediaFile { @@ -1124,7 +1123,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding { var updateShimmerLayersImpl: ((SparseItemGridDisplayItem) -> Void)? var reorderIfPossibleImpl: ((SparseItemGrid.Item, Int) -> Void)? - var revealedSpoilerMessageIds = Set() + var revealedSpoilerMessageIds = Set() private var shimmerImages: [CGFloat: UIImage] = [:] @@ -1211,7 +1210,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding { let hasSpoiler = false layer.updateHasSpoiler(hasSpoiler: hasSpoiler) - var selectedMedia: Media? + var selectedMedia: EngineRawMedia? if let image = story.media._asMedia() as? TelegramMediaImage { selectedMedia = image } else if let file = story.media._asMedia() as? TelegramMediaFile { @@ -1322,7 +1321,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding { } } - func updateLayerData(story: EngineStoryItem, item: VisualMediaItem, selectedMedia: Media, layer: ItemLayer, synchronous: SparseItemGrid.Synchronous) { + func updateLayerData(story: EngineStoryItem, item: VisualMediaItem, selectedMedia: EngineRawMedia, layer: ItemLayer, synchronous: SparseItemGrid.Synchronous) { var viewCount: Int32? if let value = story.views?.seenCount { viewCount = Int32(value) @@ -1587,7 +1586,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr private let directMediaImageCache: DirectMediaImageCache private var items: SparseItemGrid.Items? private var pinnedIds: Set = Set() - private var reorderedIds: [StoryId]? + private var reorderedIds: [EngineStoryId]? private var itemCount: Int? private var didUpdateItemsOnce: Bool = false private var itemTabId: AnyHashable? @@ -2556,7 +2555,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr if let story = folderPreview.item { var imageSignal: Signal? - var selectedMedia: Media? + var selectedMedia: EngineRawMedia? if let image = story.media._asMedia() as? TelegramMediaImage { selectedMedia = image } else if let file = story.media._asMedia() as? TelegramMediaFile { @@ -2771,7 +2770,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr } let shareController = self.context.sharedContext.makeShareController(context: self.context, params: ShareControllerParams( - subject: .media(.story(peer: peerReference, id: item.id, media: TelegramMediaStory(storyId: StoryId(peerId: peer.id, id: item.id), isMention: false)), nil), + subject: .media(.story(peer: peerReference, id: item.id, media: TelegramMediaStory(storyId: EngineStoryId(peerId: peer.id, id: item.id), isMention: false)), nil), externalShare: false )) self.parentController?.present(shareController, in: .window(.root)) @@ -3038,7 +3037,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr if let reorderedIds = self.reorderedIds { var fixedStateItems: [StoryListContext.State.Item] = [] - var seenIds = Set() + var seenIds = Set() for id in reorderedIds { if let index = stateItems.firstIndex(where: { $0.id == id }) { seenIds.insert(id) @@ -3100,7 +3099,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr )) } if mappedItems.count < state.totalCount, let lastItem = state.items.last, let _ = state.loadMoreToken { - mappedHoles.append(VisualMediaHoleAnchor(index: mappedItems.count, storyId: StoryId(peerId: context.account.peerId, id: Int32.max), localMonthTimestamp: Month(localTimestamp: lastItem.storyItem.timestamp + timezoneOffset).packedValue)) + mappedHoles.append(VisualMediaHoleAnchor(index: mappedItems.count, storyId: EngineStoryId(peerId: context.account.peerId, id: Int32.max), localMonthTimestamp: Month(localTimestamp: lastItem.storyItem.timestamp + timezoneOffset).packedValue)) } totalCount = state.totalCount totalCount = max(mappedItems.count, totalCount) @@ -3262,7 +3261,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr return } - var ids = items.items.compactMap { item -> StoryId? in + var ids = items.items.compactMap { item -> EngineStoryId? in return (item as? VisualMediaItem)?.storyId } @@ -3605,9 +3604,9 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr controller?.dismissAnimated() } - var mappedMedia: [Media] = [] + var mappedMedia: [EngineRawMedia] = [] if let items = self.items { - mappedMedia = items.items.compactMap { item -> Media? in + mappedMedia = items.items.compactMap { item -> EngineRawMedia? in guard let item = item as? VisualMediaItem else { return nil } @@ -5223,9 +5222,9 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr return } - var mappedMedia: [Media] = [] + var mappedMedia: [EngineRawMedia] = [] if let items = self.items { - mappedMedia = items.items.compactMap { item -> Media? in + mappedMedia = items.items.compactMap { item -> EngineRawMedia? in guard let item = item as? VisualMediaItem else { return nil } @@ -5321,7 +5320,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr self.reorderedIds = nil if case .botPreview = self.scope, let listSource = self.listSource as? BotPreviewStoryListContext { if let items = self.items { - var reorderedMedia: [Media] = [] + var reorderedMedia: [EngineRawMedia] = [] for id in reorderedIds { if let item = items.items.first(where: { ($0 as? VisualMediaItem)?.storyId == id }) as? VisualMediaItem { diff --git a/submodules/TelegramUI/Components/RankChatPreviewItem/Sources/RankChatPreviewItem.swift b/submodules/TelegramUI/Components/RankChatPreviewItem/Sources/RankChatPreviewItem.swift index 4f917066be..19c0f7c10a 100644 --- a/submodules/TelegramUI/Components/RankChatPreviewItem/Sources/RankChatPreviewItem.swift +++ b/submodules/TelegramUI/Components/RankChatPreviewItem/Sources/RankChatPreviewItem.swift @@ -4,7 +4,6 @@ import Display import AsyncDisplayKit import SwiftSignalKit import TelegramCore -import Postbox import TelegramPresentationData import TelegramUIPreferences import ItemListUI @@ -20,9 +19,14 @@ public final class RankChatPreviewItem: ListViewItem, ItemListItem, ListItemComp if lhs.text != rhs.text { return false } - if areMediaArraysEqual(lhs.media, rhs.media) { + if lhs.media.count != rhs.media.count { return false } + for i in 0 ..< lhs.media.count { + if !lhs.media[i].isEqual(to: rhs.media[i]) { + return false + } + } if lhs.rank != rhs.rank { return false } @@ -32,11 +36,11 @@ public final class RankChatPreviewItem: ListViewItem, ItemListItem, ListItemComp let peer: EnginePeer let text: String let entities: TextEntitiesMessageAttribute? - let media: [Media] + let media: [EngineRawMedia] let rank: String let rankRole: ChatRankInfoScreenRole - public init(peer: EnginePeer, text: String, entities: TextEntitiesMessageAttribute?, media: [Media], rank: String, rankRole: ChatRankInfoScreenRole) { + public init(peer: EnginePeer, text: String, entities: TextEntitiesMessageAttribute?, media: [EngineRawMedia], rank: String, rankRole: ChatRankInfoScreenRole) { self.peer = peer self.text = text self.entities = entities @@ -234,29 +238,29 @@ final class RankChatPreviewItemNode: ListViewItemNode { for messageItem in item.messageItems.reversed() { var userPeer = messageItem.peer._asPeer() - let updatedId = PeerId.Id._internalFromInt64Value(userPeer.id.id._internalGetInt64Value() - 7) - let authorPeerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: updatedId) - let groupPeerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(0)) - let groupPeer = TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, title: "", username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil) + let updatedId = EnginePeer.Id.Id._internalFromInt64Value(userPeer.id.id._internalGetInt64Value() - 7) + let authorPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: updatedId) + let groupPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudChannel, id: EnginePeer.Id.Id._internalFromInt64Value(0)) + let groupPeer = TelegramChannel(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudChannel, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, title: "", username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil) if let user = userPeer as? TelegramUser { userPeer = TelegramUser(id: authorPeerId, accessHash: user.accessHash, firstName: user.firstName, lastName: user.lastName, username: "", phone: user.phone, photo: user.photo, botInfo: user.botInfo, restrictionInfo: user.restrictionInfo, flags: user.flags, emojiStatus: user.emojiStatus, usernames: user.usernames, storiesHidden: user.storiesHidden, nameColor: user.nameColor, backgroundEmojiId: user.backgroundEmojiId, profileColor: user.profileColor, profileBackgroundEmojiId: user.profileBackgroundEmojiId, subscriberCount: user.subscriberCount, verificationIconFileId: user.verificationIconFileId) } - var peers = SimpleDictionary() - let messages = SimpleDictionary() + var peers = EngineSimpleDictionary() + let messages = EngineSimpleDictionary() peers[authorPeerId] = userPeer peers[groupPeerId] = groupPeer let media = messageItem.media - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] if let entities = messageItem.entities { attributes.append(entities) } - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: groupPeerId, namespace: Namespaces.Message.Local, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 20460, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: attributes, media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message = EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: groupPeerId, namespace: Namespaces.Message.Local, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 20460, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: attributes, media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: item.containerWidth != nil, isPreview: true, isStandalone: false, rank: messageItem.rank, rankRole: messageItem.rankRole)) } diff --git a/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageSetupChatContents.swift b/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageSetupChatContents.swift index c8c10bdc99..4d15e5e1da 100644 --- a/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageSetupChatContents.swift +++ b/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageSetupChatContents.swift @@ -1,14 +1,13 @@ import Foundation import UIKit import SwiftSignalKit -import Postbox import TelegramCore import AccountContext final class AutomaticBusinessMessageSetupChatContents: ChatCustomContentsProtocol { private final class PendingMessageContext { let disposable = MetaDisposable() - var message: Message? + var message: EngineRawMessage? init() { } @@ -21,13 +20,13 @@ final class AutomaticBusinessMessageSetupChatContents: ChatCustomContentsProtoco private var shortcut: String private var shortcutId: Int32? - private(set) var mergedHistoryView: MessageHistoryView? - private var sourceHistoryView: MessageHistoryView? - + private(set) var mergedHistoryView: EngineRawMessageHistoryView? + private var sourceHistoryView: EngineRawMessageHistoryView? + private var pendingMessages: [PendingMessageContext] = [] private var historyViewDisposable: Disposable? private var pendingHistoryViewDisposable: Disposable? - let historyViewStream = ValuePipe<(MessageHistoryView, ViewUpdateType)>() + let historyViewStream = ValuePipe<(EngineRawMessageHistoryView, EngineViewUpdateType)>() private var nextUpdateIsHoleFill: Bool = false init(queue: Queue, context: AccountContext, shortcut: String, shortcutId: Int32?) { @@ -98,17 +97,17 @@ final class AutomaticBusinessMessageSetupChatContents: ChatCustomContentsProtoco } } - private func updateHistoryView(updateType: ViewUpdateType) { + private func updateHistoryView(updateType: EngineViewUpdateType) { var entries = self.sourceHistoryView?.entries ?? [] for pendingMessage in self.pendingMessages { if let message = pendingMessage.message { if !entries.contains(where: { $0.message.stableId == message.stableId }) { - entries.append(MessageHistoryEntry( + entries.append(EngineRawMessageHistoryEntry( message: message, isRead: true, location: nil, monthLocation: nil, - attributes: MutableMessageHistoryEntryAttributes( + attributes: EngineRawMutableMessageHistoryEntryAttributes( authorIsContact: false ) )) @@ -116,8 +115,8 @@ final class AutomaticBusinessMessageSetupChatContents: ChatCustomContentsProtoco } } entries.sort(by: { $0.message.index < $1.message.index }) - - let mergedHistoryView = MessageHistoryView(tag: nil, namespaces: .just(Namespaces.Message.allQuickReply), entries: entries, holeEarlier: false, holeLater: false, isLoading: false) + + let mergedHistoryView = EngineRawMessageHistoryView(tag: nil, namespaces: .just(Namespaces.Message.allQuickReply), entries: entries, holeEarlier: false, holeLater: false, isLoading: false) self.mergedHistoryView = mergedHistoryView self.historyViewStream.putNext((mergedHistoryView, updateType)) @@ -184,7 +183,7 @@ final class AutomaticBusinessMessageSetupChatContents: ChatCustomContentsProtoco var kind: ChatCustomContentsKind - var historyView: Signal<(MessageHistoryView, ViewUpdateType), NoError> { + var historyView: Signal<(EngineRawMessageHistoryView, EngineViewUpdateType), NoError> { return self.impl.signalWith({ impl, subscriber in if let mergedHistoryView = impl.mergedHistoryView { subscriber.putNext((mergedHistoryView, .Initial)) diff --git a/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/BusinessLinkChatContents.swift b/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/BusinessLinkChatContents.swift index 13f07d581f..2cf3abe444 100644 --- a/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/BusinessLinkChatContents.swift +++ b/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/BusinessLinkChatContents.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import SwiftSignalKit -import Postbox import TelegramCore import AccountContext @@ -30,8 +29,8 @@ final class BusinessLinkChatContents: ChatCustomContentsProtocol { var kind: ChatCustomContentsKind - var historyView: Signal<(MessageHistoryView, ViewUpdateType), NoError> { - let view = MessageHistoryView(tag: nil, namespaces: .just(Namespaces.Message.allQuickReply), entries: [], holeEarlier: false, holeLater: false, isLoading: false) + var historyView: Signal<(EngineRawMessageHistoryView, EngineViewUpdateType), NoError> { + let view = EngineRawMessageHistoryView(tag: nil, namespaces: .just(Namespaces.Message.allQuickReply), entries: [], holeEarlier: false, holeLater: false, isLoading: false) return .single((view, .Initial)) } diff --git a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift index e19b2c5d51..86cc6ae0c0 100644 --- a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift +++ b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift @@ -3,7 +3,6 @@ import UIKit import Display import AsyncDisplayKit import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -429,15 +428,11 @@ final class BusinessIntroSetupScreenComponent: Component { ) } - let installedPackIds = context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])]) - |> map { view -> Set in - var installedPacks = Set() - if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])] as? ItemCollectionInfosView { - if let packsEntries = stickerPacksView.entriesByNamespace[Namespaces.ItemCollection.CloudStickerPacks] { - for entry in packsEntries { - installedPacks.insert(entry.id) - } - } + let installedPackIds = context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCollections.InstalledPackInfos(namespace: Namespaces.ItemCollection.CloudStickerPacks)) + |> map { entries -> Set in + var installedPacks = Set() + for entry in entries { + installedPacks.insert(entry.id) } return installedPacks } @@ -473,7 +468,7 @@ final class BusinessIntroSetupScreenComponent: Component { var items: [EmojiPagerContentComponent.Item] = [] - var existingIds = Set() + var existingIds = Set() for (_, entry) in foundItems { let itemFile = entry.file @@ -565,7 +560,7 @@ final class BusinessIntroSetupScreenComponent: Component { |> mapToSignal { files -> Signal<(items: [EmojiPagerContentComponent.ItemGroup], isFinalResult: Bool), NoError> in var items: [EmojiPagerContentComponent.Item] = [] - var existingIds = Set() + var existingIds = Set() for item in files.items { let itemFile = item.file if existingIds.contains(itemFile.fileId) { @@ -1020,7 +1015,7 @@ final class BusinessIntroSetupScreenComponent: Component { stickerSelectionControl = ComponentView() self.stickerSelectionControl = stickerSelectionControl } - var selectedItems = Set() + var selectedItems = Set() if let stickerFile = self.stickerFile { selectedItems.insert(stickerFile.fileId) } diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift index 1758ade1a1..1e923dfeee 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift @@ -4,7 +4,6 @@ import Display import AsyncDisplayKit import SwiftSignalKit import TelegramCore -import Postbox import TelegramPresentationData import TelegramUIPreferences import ItemListUI @@ -215,32 +214,32 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode { var insets: UIEdgeInsets let separatorHeight = UIScreenPixel - let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(1)) + let peerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudChannel, id: EnginePeer.Id.Id._internalFromInt64Value(1)) var items: [ListViewItem] = [] for messageItem in item.messageItems.reversed() { let authorPeerId = messageItem.peerId - let replyAuthorPeerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(10)) + let replyAuthorPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(10)) - var peers = SimpleDictionary() - var messages = SimpleDictionary() + var peers = EngineSimpleDictionary() + var messages = EngineSimpleDictionary() peers[authorPeerId] = TelegramUser(id: authorPeerId, accessHash: nil, firstName: messageItem.author, lastName: "", username: nil, phone: nil, photo: messageItem.photo, botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: messageItem.nameColor, backgroundEmojiId: messageItem.backgroundEmojiId, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) - let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) + let replyMessageId = EngineMessage.Id(peerId: peerId, namespace: 0, id: 3) if let (replyAuthor, text, replyColor) = messageItem.reply { peers[replyAuthorPeerId] = TelegramUser(id: authorPeerId, accessHash: nil, firstName: replyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: replyColor, backgroundEmojiId: messageItem.backgroundEmojiId, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) - messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[replyAuthorPeerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + messages[replyMessageId] = EngineRawMessage(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[replyAuthorPeerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: EngineSimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) } - var media: [Media] = [] + var media: [EngineRawMedia] = [] if let (site, title, text) = messageItem.linkPreview, params.width > 320.0 { - media.append(TelegramMediaWebpage(webpageId: MediaId(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "", displayUrl: "", hash: 0, type: nil, websiteName: site, title: title, text: text, embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, imageIsVideoCover: false, image: nil, file: nil, story: nil, attributes: [], instantPage: nil)))) + media.append(TelegramMediaWebpage(webpageId: EngineMedia.Id(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "", displayUrl: "", hash: 0, type: nil, websiteName: site, title: title, text: text, embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, imageIsVideoCover: false, image: nil, file: nil, story: nil, attributes: [], instantPage: nil)))) } - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)] : [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message = EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)] : [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) } diff --git a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift index 48eb6f1d4d..b4a5c4fe28 100644 --- a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift +++ b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift @@ -4,7 +4,6 @@ import Display import AsyncDisplayKit import SwiftSignalKit import TelegramCore -import Postbox import TelegramPresentationData import TelegramUIPreferences import ItemListUI @@ -27,10 +26,10 @@ class ReactionChatPreviewItem: ListViewItem, ItemListItem { let nameDisplayOrder: PresentationPersonNameOrder let availableReactions: AvailableReactions? let reaction: MessageReaction.Reaction? - let accountPeer: Peer? + let accountPeer: EngineRawPeer? let toggleReaction: () -> Void - init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, systemStyle: ItemListSystemStyle = .legacy, sectionId: ItemListSectionId, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, wallpaper: TelegramWallpaper, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, availableReactions: AvailableReactions?, reaction: MessageReaction.Reaction?, accountPeer: Peer?, toggleReaction: @escaping () -> Void) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, systemStyle: ItemListSystemStyle = .legacy, sectionId: ItemListSectionId, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, wallpaper: TelegramWallpaper, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, availableReactions: AvailableReactions?, reaction: MessageReaction.Reaction?, accountPeer: EngineRawPeer?, toggleReaction: @escaping () -> Void) { self.context = context self.theme = theme self.strings = strings @@ -301,17 +300,17 @@ class ReactionChatPreviewItemNode: ListViewItemNode { let separatorHeight = UIScreenPixel let separatorRightInset: CGFloat = item.systemStyle == .glass ? 16.0 : 0.0 - let userPeerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)) + let userPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(2)) let chatPeerId = userPeerId - var peers = SimpleDictionary() - let messages = SimpleDictionary() + var peers = EngineSimpleDictionary() + let messages = EngineSimpleDictionary() peers[userPeerId] = TelegramUser(id: userPeerId, accessHash: nil, firstName: item.strings.Settings_QuickReactionSetup_DemoMessageAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) let messageText = item.strings.Settings_QuickReactionSetup_DemoMessageText - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] if let reaction = item.reaction { var recentPeers: [ReactionsMessageAttribute.RecentPeer] = [] if let accountPeer = item.accountPeer { @@ -321,7 +320,7 @@ class ReactionChatPreviewItemNode: ListViewItemNode { attributes.append(ReactionsMessageAttribute(canViewList: false, isTags: false, reactions: [MessageReaction(value: reaction, count: 1, chosenOrder: 0)], recentPeers: recentPeers, topPeers: [])) } - let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[userPeerId], text: messageText, attributes: attributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: item.availableReactions, accountPeer: item.accountPeer, isCentered: true, isPreview: true, isStandalone: false, rank: nil, rankRole: nil) + let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[userPeerId], text: messageText, attributes: attributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: item.availableReactions, accountPeer: item.accountPeer, isCentered: true, isPreview: true, isStandalone: false, rank: nil, rankRole: nil) var node: ListViewItemNode? if let current = currentNode { diff --git a/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift b/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift index 75b2184144..198d9b12b1 100644 --- a/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift +++ b/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift @@ -1,7 +1,6 @@ import Foundation import UIKit import Display -import Postbox import SwiftSignalKit import AsyncDisplayKit import TelegramCore @@ -895,7 +894,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, ASScrollViewDelegate context: self.context, chatListLocation: .chatList(groupId: .root), filterData: nil, - index: .chatList(ChatListIndex(pinningIndex: isPinned ? 0 : nil, messageIndex: MessageIndex(id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), timestamp: timestamp))), + index: .chatList(EngineChatListIndex(pinningIndex: isPinned ? 0 : nil, messageIndex: EngineMessage.Index(id: EngineMessage.Id(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), timestamp: timestamp))), content: .peer(ChatListItemContent.PeerData( messages: [ EngineMessage( @@ -961,11 +960,11 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, ASScrollViewDelegate } let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)) - let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) - let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer2: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer3: EnginePeer = .channel(TelegramChannel(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudChannel, id: EnginePeer.Id.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, emojiStatus: nil, approximateBoostLevel: nil, subscriptionUntilDate: nil, verificationIconFileId: nil, sendPaidMessageStars: nil, linkedMonoforumId: nil)) + let peer3Author: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) + let peer4: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil)) let timestamp = self.referenceTimestamp @@ -1049,43 +1048,43 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, ASScrollViewDelegate let headerItem = self.context.sharedContext.makeChatMessageDateHeaderItem(context: self.context, timestamp: self.referenceTimestamp, theme: self.theme, strings: self.presentationData.strings, wallpaper: self.wallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder) var items: [ListViewItem] = [] - let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) + let peerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)) let otherPeerId = self.context.account.peerId - var peers = SimpleDictionary() - var messages = SimpleDictionary() + var peers = EngineSimpleDictionary() + var messages = EngineSimpleDictionary() peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) - var sampleMessages: [Message] = [] + var sampleMessages: [EngineRawMessage] = [] - let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message1 = EngineRawMessage(stableId:1, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id:1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message1) - let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message2 = EngineRawMessage(stableId:2, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id:2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message2) - let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message3 = EngineRawMessage(stableId:3, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id:3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message3) - let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message4 = EngineRawMessage(stableId:4, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id:4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) messages[message4.id] = message4 sampleMessages.append(message4) - let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message5 = EngineRawMessage(stableId:5, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id:5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) messages[message5.id] = message5 sampleMessages.append(message5) let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA=" let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)] - let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes, alternativeRepresentations: []) + let voiceMedia = TelegramMediaFile(fileId: EngineMedia.Id(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes, alternativeRepresentations: []) - let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message6 = EngineRawMessage(stableId:6, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id:6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message6) - let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message7 = EngineRawMessage(stableId:7, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id:7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message7) - let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message8 = EngineRawMessage(stableId:8, stableVersion: 0, id: EngineMessage.Id(peerId: otherPeerId, namespace: 0, id:8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) sampleMessages.append(message8) items = sampleMessages.reversed().map { message in diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryController.swift b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryController.swift index d77f6325ba..6bd88ad0cd 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryController.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryController.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import QuickLook -import Postbox import SwiftSignalKit import AsyncDisplayKit import TelegramCore @@ -25,14 +24,14 @@ public enum WallpaperListType { public enum WallpaperListSource { case list(wallpapers: [TelegramWallpaper], central: TelegramWallpaper, type: WallpaperListType) - case wallpaper(TelegramWallpaper, WallpaperPresentationOptions?, [UInt32], Int32?, Int32?, Message?) - case slug(String, TelegramMediaFile?, WallpaperPresentationOptions?, [UInt32], Int32?, Int32?, Message?) + case wallpaper(TelegramWallpaper, WallpaperPresentationOptions?, [UInt32], Int32?, Int32?, EngineRawMessage?) + case slug(String, TelegramMediaFile?, WallpaperPresentationOptions?, [UInt32], Int32?, Int32?, EngineRawMessage?) case asset(PHAsset) case contextResult(ChatContextResult) case customColor(UInt32?) } -private func areMessagesEqual(_ lhsMessage: Message?, _ rhsMessage: Message?) -> Bool { +private func areMessagesEqual(_ lhsMessage: EngineRawMessage?, _ rhsMessage: EngineRawMessage?) -> Bool { if lhsMessage == nil && rhsMessage == nil { return true } @@ -49,7 +48,7 @@ private func areMessagesEqual(_ lhsMessage: Message?, _ rhsMessage: Message?) -> } public enum WallpaperGalleryEntry: Equatable { - case wallpaper(TelegramWallpaper, Message?) + case wallpaper(TelegramWallpaper, EngineRawMessage?) case asset(PHAsset) case contextResult(ChatContextResult) @@ -551,7 +550,7 @@ public class WallpaperGalleryController: ViewController { let apply = strongSelf.apply if case .peer = strongSelf.mode { if case let .wallpaper(wallpaper, _) = entry, options.contains(.blur) { - var resource: MediaResource? + var resource: TelegramMediaResource? switch wallpaper { case let .file(file): resource = file.file.resource @@ -589,7 +588,7 @@ public class WallpaperGalleryController: ViewController { switch entry { case let .wallpaper(wallpaper, _): - var resource: MediaResource? + var resource: TelegramMediaResource? switch wallpaper { case let .file(file): resource = file.file.resource diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift index b7888119d0..cc1c15d67d 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift @@ -3,7 +3,6 @@ import UIKit import Display import AsyncDisplayKit import SwiftSignalKit -import Postbox import TelegramCore import LegacyComponents import TelegramPresentationData @@ -78,7 +77,7 @@ class WallpaperGalleryItem: GalleryItem { private let progressDiameter: CGFloat = 50.0 private let motionAmount: CGFloat = 32.0 -private func reference(for resource: MediaResource, media: Media, message: Message?, slug: String?) -> MediaResourceReference { +private func reference(for resource: TelegramMediaResource, media: EngineRawMedia, message: EngineRawMessage?, slug: String?) -> MediaResourceReference { if let message = message { return .media(media: .message(message: MessageReference(message), media: media), resource: resource) } @@ -614,7 +613,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode { let imagePromise = Promise() let signal: Signal<(TransformImageArguments) -> DrawingContext?, NoError> - let fetchSignal: Signal + let fetchSignal: Signal let statusSignal: Signal let subtitleSignal: Signal var actionSignal: Signal = .single(nil) @@ -923,7 +922,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode { representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(thumbnailDimensions), resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)) } representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(imageDimensions), resource: imageResource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)) - let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []) + let tmpImage = TelegramMediaImage(imageId: EngineMedia.Id(namespace: 0, id: 0), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []) signal = chatMessagePhoto(postbox: context.account.postbox, userLocation: .other, photoReference: .standalone(media: tmpImage)) fetchSignal = context.engine.resources.fetch(reference: .media(media: .standalone(media: tmpImage), resource: imageResource), userLocation: .other, userContentType: .other) @@ -1506,24 +1505,24 @@ final class WallpaperGalleryItemNode: GalleryItemNode { } var items: [ListViewItem] = [] - var peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) + var peerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)) let otherPeerId = self.context.account.peerId - var peers = SimpleDictionary() - var messages = SimpleDictionary() + var peers = EngineSimpleDictionary() + var messages = EngineSimpleDictionary() let replyAuthor = self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName - var messageAuthor: Peer = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) + var messageAuthor: EngineRawPeer = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) let otherAuthor = TelegramUser(id: otherPeerId, accessHash: nil, firstName: replyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .preset(.blue), backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) peers[otherPeerId] = otherAuthor - var messageAttributes: [MessageAttribute] = [] + var messageAttributes: [EngineMessage.Attribute] = [] if let mode = self.mode, case let .peer(peer, _) = mode, case .channel = peer { peerId = peer.id messageAuthor = peer._asPeer() - let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) - messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: messageAuthor, text: self.presentationData.strings.WallpaperPreview_ChannelReplyText, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let replyMessageId = EngineMessage.Id(peerId: peerId, namespace: 0, id: 3) + messages[replyMessageId] = EngineRawMessage(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: messageAuthor, text: self.presentationData.strings.WallpaperPreview_ChannelReplyText, attributes: [], media: [], peers: peers, associatedMessages: EngineSimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) messageAttributes = [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, innerSubject: nil)] } @@ -1626,19 +1625,19 @@ final class WallpaperGalleryItemNode: GalleryItemNode { let theme = self.presentationData.theme if !bottomMessageText.isEmpty { - let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message1 = EngineRawMessage(stableId: 2, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) } - let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: messageAttributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message2 = EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: messageAttributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) if let serviceMessageText { let attributedText = convertMarkdownToAttributes(NSAttributedString(string: serviceMessageText)) let entities = generateChatInputTextEntities(attributedText) - let message3 = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: attributedText.string, entities: entities, additionalAttributes: nil))], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message3 = EngineRawMessage(stableId: 0, stableVersion: 0, id: EngineMessage.Id(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: attributedText.string, entities: entities, additionalAttributes: nil))], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) } diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridSearchContentNode.swift b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridSearchContentNode.swift index 17074511e3..19b3e8a5c2 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridSearchContentNode.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/ThemeGridSearchContentNode.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import MergeLists @@ -464,7 +463,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode { return .single(([], true)) |> then( configuration - |> mapToSignal { configuration -> Signal in + |> mapToSignal { configuration -> Signal in guard let name = configuration.imageBotUsername else { return .single(nil) } @@ -475,7 +474,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode { } return .single(result) } - |> mapToSignal { peer -> Signal in + |> mapToSignal { peer -> Signal in if let peer = peer { return .single(peer._asPeer()) } else { diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/WallpaperUtils.swift b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/WallpaperUtils.swift index 04af498c4c..b60bd7f395 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/WallpaperUtils.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGridScreen/Sources/WallpaperUtils.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import MediaResources import LocalMediaResources @@ -111,7 +110,7 @@ public func uploadCustomWallpaper(context: AccountContext, wallpaper: WallpaperG let accountManager = context.sharedContext.accountManager let account = context.account let updateWallpaper: (TelegramWallpaper) -> Void = { wallpaper in - var resource: MediaResource? + var resource: TelegramMediaResource? if case let .image(representations, _) = wallpaper, let representation = largestImageRepresentation(representations) { resource = representation.resource } else if case let .file(file) = wallpaper { @@ -257,7 +256,7 @@ public func getTemporaryCustomPeerWallpaper(context: AccountContext, wallpaper: } } -public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: WallpaperGalleryEntry, mode: WallpaperPresentationOptions, editedImage: UIImage?, cropRect: CGRect?, brightness: CGFloat?, peerId: PeerId, forBoth: Bool, completion: @escaping () -> Void) { +public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: WallpaperGalleryEntry, mode: WallpaperPresentationOptions, editedImage: UIImage?, cropRect: CGRect?, brightness: CGFloat?, peerId: EnginePeer.Id, forBoth: Bool, completion: @escaping () -> Void) { var imageSignal: Signal switch wallpaper { case let .wallpaper(wallpaper, _): diff --git a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift index 32161ebabb..a9c17a2fa4 100644 --- a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift +++ b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift @@ -768,7 +768,7 @@ final class ShareWithPeersScreenComponent: Component { }) } else if peer.id.namespace == Namespaces.Peer.CloudChannel { let participants: Signal<[EnginePeer], NoError> = Signal { subscriber in - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peer.id, requestUpdate: true, count: 200, updated: { list in + let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peer.id, requestUpdate: true, count: 200, updated: { list in var peers: [EnginePeer] = [] for item in list.list { if item.peer.id == context.account.peerId { diff --git a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreenState.swift b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreenState.swift index 26748749b2..3c9f8ed80b 100644 --- a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreenState.swift +++ b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreenState.swift @@ -523,11 +523,11 @@ public extension ShareWithPeersScreen { let contactsState = Promise() let disposableAndLoadMoreControl: (Disposable, PeerChannelMemberCategoryControl?) - disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: searchQuery, updated: { state in + disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: searchQuery, updated: { state in membersState.set(.single(state)) }) - let contactsDisposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: searchQuery, updated: { state in + let contactsDisposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: searchQuery, updated: { state in contactsState.set(.single(state)) }) diff --git a/submodules/TelegramUI/Components/Stars/StarsAvatarComponent/BUILD b/submodules/TelegramUI/Components/Stars/StarsAvatarComponent/BUILD index 8e587337b5..9938b25de3 100644 --- a/submodules/TelegramUI/Components/Stars/StarsAvatarComponent/BUILD +++ b/submodules/TelegramUI/Components/Stars/StarsAvatarComponent/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/AsyncDisplayKit", "//submodules/Display", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/ComponentFlow", diff --git a/submodules/TelegramUI/Components/Stars/StarsAvatarComponent/Sources/StarsAvatarComponent.swift b/submodules/TelegramUI/Components/Stars/StarsAvatarComponent/Sources/StarsAvatarComponent.swift index ab62c323c2..225a6e2e3d 100644 --- a/submodules/TelegramUI/Components/Stars/StarsAvatarComponent/Sources/StarsAvatarComponent.swift +++ b/submodules/TelegramUI/Components/Stars/StarsAvatarComponent/Sources/StarsAvatarComponent.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import ComponentFlow import TelegramPresentationData @@ -23,7 +22,7 @@ public final class StarsAvatarComponent: Component { let theme: PresentationTheme let peer: StarsAvatarComponent.Peer? let photo: TelegramMediaWebFile? - let media: [Media] + let media: [EngineRawMedia] let gift: StarGift? let backgroundColor: UIColor let size: CGSize? @@ -33,7 +32,7 @@ public final class StarsAvatarComponent: Component { theme: PresentationTheme, peer: StarsAvatarComponent.Peer?, photo: TelegramMediaWebFile?, - media: [Media], + media: [EngineRawMedia], gift: StarGift?, backgroundColor: UIColor, size: CGSize? = nil @@ -61,7 +60,7 @@ public final class StarsAvatarComponent: Component { if lhs.photo != rhs.photo { return false } - if !areMediaArraysEqual(lhs.media, rhs.media) { + if !engineAreMediaArraysEqual(lhs.media, rhs.media) { return false } if lhs.gift != rhs.gift { diff --git a/submodules/TelegramUI/Components/Stars/StarsImageComponent/BUILD b/submodules/TelegramUI/Components/Stars/StarsImageComponent/BUILD index b71d4ed3c0..33526bb75c 100644 --- a/submodules/TelegramUI/Components/Stars/StarsImageComponent/BUILD +++ b/submodules/TelegramUI/Components/Stars/StarsImageComponent/BUILD @@ -12,7 +12,6 @@ swift_library( deps = [ "//submodules/AsyncDisplayKit", "//submodules/Display", - "//submodules/Postbox", "//submodules/TelegramCore", "//submodules/SSignalKit/SwiftSignalKit", "//submodules/ComponentFlow", diff --git a/submodules/TelegramUI/Components/Stars/StarsImageComponent/Sources/StarsImageComponent.swift b/submodules/TelegramUI/Components/Stars/StarsImageComponent/Sources/StarsImageComponent.swift index 1aea568c66..13d3ae0af9 100644 --- a/submodules/TelegramUI/Components/Stars/StarsImageComponent/Sources/StarsImageComponent.swift +++ b/submodules/TelegramUI/Components/Stars/StarsImageComponent/Sources/StarsImageComponent.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import ComponentFlow import TelegramPresentationData @@ -272,7 +271,7 @@ public final class StarsImageComponent: Component { return false } case let .media(lhsMedia): - if case let .media(rhsMedia) = rhs, areMediaArraysEqual(lhsMedia.map { $0.media }, rhsMedia.map { $0.media }) { + if case let .media(rhsMedia) = rhs, engineAreMediaArraysEqual(lhsMedia.map { $0.media }, rhsMedia.map { $0.media }) { return true } else { return false @@ -323,7 +322,7 @@ public final class StarsImageComponent: Component { public let backgroundColor: UIColor public let icon: Icon? public let value: Int64? - public let action: ((@escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)? + public let action: ((@escaping (EngineRawMedia) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)? public init( context: AccountContext, @@ -333,7 +332,7 @@ public final class StarsImageComponent: Component { backgroundColor: UIColor, icon: Icon? = nil, value: Int64? = nil, - action: ((@escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)? = nil + action: ((@escaping (EngineRawMedia) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)? = nil ) { self.context = context self.subject = subject @@ -401,7 +400,7 @@ public final class StarsImageComponent: Component { private let fetchDisposable = MetaDisposable() private var hiddenMediaDisposable: Disposable? - private var hiddenMedia: [Media] = [] + private var hiddenMedia: [EngineRawMedia] = [] public override init(frame: CGRect) { super.init(frame: frame) @@ -432,7 +431,7 @@ public final class StarsImageComponent: Component { }) } - public func transitionNode(_ transitionMedia: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { + public func transitionNode(_ transitionMedia: EngineRawMedia) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? { guard let component = self.component, let containerNode = self.containerNode else { return nil } @@ -644,7 +643,7 @@ public final class StarsImageComponent: Component { let media: TelegramMediaImage switch extendedMedia.first { case let .preview(imageDimensions, immediateThumbnailData, _): - let thumbnailMedia = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: [], immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) + let thumbnailMedia = TelegramMediaImage(imageId: EngineMedia.Id(namespace: 0, id: 0), representations: [], immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) media = thumbnailMedia if let imageDimensions { dimensions = imageDimensions.cgSize.aspectFilled(imageSize) @@ -686,7 +685,7 @@ public final class StarsImageComponent: Component { let media: TelegramMediaImage switch extendedMedia[1] { case let .preview(imageDimensions, immediateThumbnailData, _): - let thumbnailMedia = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: [], immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) + let thumbnailMedia = TelegramMediaImage(imageId: EngineMedia.Id(namespace: 0, id: 0), representations: [], immediateThumbnailData: immediateThumbnailData, reference: nil, partialReference: nil, flags: []) media = thumbnailMedia if let imageDimensions { secondDimensions = imageDimensions.cgSize.aspectFilled(imageSize) @@ -1038,7 +1037,7 @@ public final class StarsImageComponent: Component { guard let self, let component = self.component else { return } - var hiddenMedia: [Media] = [] + var hiddenMedia: [EngineRawMedia] = [] for id in ids { if case let .chat(accountId, _, media) = id, accountId == component.context.account.id { hiddenMedia.append(media) diff --git a/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift b/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift index 22f8fc3cfa..82bb8586e2 100644 --- a/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift +++ b/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift @@ -7,7 +7,6 @@ import ComponentFlow import SwiftSignalKit import AccountContext import TelegramCore -import Postbox import MultilineTextComponent import AvatarNode import TelegramPresentationData @@ -229,7 +228,7 @@ public final class PeerListItemComponent: Component { let avatar: Avatar? let avatarComponent: AnyComponent? let peer: EnginePeer? - let storyStats: PeerStoryStats? + let storyStats: EnginePeerStoryStats? let subtitle: Subtitle? let subtitleComponent: AnyComponent? let subtitleAccessory: SubtitleAccessory @@ -260,7 +259,7 @@ public final class PeerListItemComponent: Component { avatar: Avatar? = nil, avatarComponent: AnyComponent? = nil, peer: EnginePeer?, - storyStats: PeerStoryStats? = nil, + storyStats: EnginePeerStoryStats? = nil, subtitle: Subtitle?, subtitleComponent: AnyComponent? = nil, subtitleAccessory: SubtitleAccessory, @@ -1324,7 +1323,7 @@ public final class PeerListItemComponent: Component { if let story = component.story { mediaReference = .story(peer: peerReference, id: story.id, media: story.media._asMedia()) } else if let message = component.message { - var selectedMedia: Media? + var selectedMedia: EngineRawMedia? for media in message.media { if let image = media as? TelegramMediaImage { selectedMedia = image diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift index 8b09a8053c..314cc72cc6 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift @@ -8,7 +8,6 @@ import SwiftSignalKit import AppBundle import MessageInputPanelComponent import TelegramCore -import Postbox import UndoUI import ReactionSelectionNode import EntityKeyboard @@ -276,14 +275,14 @@ private final class StoryContainerScreenComponent: Component { let context: AccountContext let content: StoryContentContext - let focusedItemPromise: Promise + let focusedItemPromise: Promise let transitionIn: StoryContainerScreen.TransitionIn? let transitionOut: (EnginePeer.Id, Int32) -> StoryContainerScreen.TransitionOut? init( context: AccountContext, content: StoryContentContext, - focusedItemPromise: Promise, + focusedItemPromise: Promise, transitionIn: StoryContainerScreen.TransitionIn?, transitionOut: @escaping (EnginePeer.Id, Int32) -> StoryContainerScreen.TransitionOut? ) { @@ -370,7 +369,7 @@ private final class StoryContainerScreenComponent: Component { private let backgroundLayer: SimpleLayer private let backgroundEffectView: BlurredBackgroundView - private let focusedItem = ValuePromise(nil, ignoreRepeated: true) + private let focusedItem = ValuePromise(nil, ignoreRepeated: true) private var stateValue: StoryContentContextState? private var contentUpdatedDisposable: Disposable? @@ -424,7 +423,7 @@ private final class StoryContainerScreenComponent: Component { var longPressRecognizer: StoryLongPressRecognizer? - private var pendingNavigationToItemId: StoryId? + private var pendingNavigationToItemId: EngineStoryId? private let interactionGuide = ComponentView() private var isDisplayingInteractionGuide: Bool = false @@ -1232,7 +1231,7 @@ private final class StoryContainerScreenComponent: Component { self.commitHorizontalPan(velocity: CGPoint(x: 200.0, y: 0.0)) } } else { - var mappedId: StoryId? + var mappedId: EngineStoryId? switch direction { case .previous: mappedId = slice.previousItemId @@ -1377,10 +1376,10 @@ private final class StoryContainerScreenComponent: Component { let stateValue = component.content.stateValue - var focusedItemId: StoryId? + var focusedItemId: EngineStoryId? var isVideo = false if let slice = stateValue?.slice { - focusedItemId = StoryId(peerId: slice.peer.id, id: slice.item.storyItem.id) + focusedItemId = EngineStoryId(peerId: slice.peer.id, id: slice.item.storyItem.id) if case .file = slice.item.storyItem.media { isVideo = true } @@ -2103,8 +2102,8 @@ public class StoryContainerScreen: ViewControllerComponentContainer, KeyShortcut private var didAnimateIn: Bool = false private var isDismissed: Bool = false - private let focusedItemPromise = Promise() - public var focusedItem: Signal { + private let focusedItemPromise = Promise() + public var focusedItem: Signal { return self.focusedItemPromise.get() } @@ -2292,13 +2291,9 @@ public class StoryContainerScreen: ViewControllerComponentContainer, KeyShortcut } func allowedStoryReactions(context: AccountContext) -> Signal<[ReactionItem], NoError> { - let viewKey: PostboxViewKey = .orderedItemList(id: Namespaces.OrderedItemList.CloudTopReactions) - let topReactions = context.account.postbox.combinedView(keys: [viewKey]) - |> map { views -> [RecentReactionItem] in - guard let view = views.views[viewKey] as? OrderedItemListView else { - return [] - } - return view.items.compactMap { item -> RecentReactionItem? in + let topReactions = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudTopReactions)) + |> map { items -> [RecentReactionItem] in + return items.compactMap { item -> RecentReactionItem? in return item.contents.get(RecentReactionItem.self) } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 242dc1e3d3..a09afd7f9d 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -14,7 +14,6 @@ import LegacyInstantVideoController import UndoUI import ContextUI import TelegramCore -import Postbox import AvatarNode import MediaEditorScreen import ImageCompression @@ -80,7 +79,7 @@ public final class StoryItemSetContainerComponent: Component { public enum NavigationDirection { case previous case next - case id(StoryId) + case id(EngineStoryId) } public struct PinchState: Equatable { @@ -122,7 +121,7 @@ public final class StoryItemSetContainerComponent: Component { public let close: () -> Void public let navigate: (NavigationDirection) -> Void public let delete: () -> Void - public let markAsSeen: (StoryId) -> Void + public let markAsSeen: (EngineStoryId) -> Void public let reorder: () -> Void public let createToFolder: (String, [EngineStoryItem]) -> Void public let addToFolder: (Int64) -> Void @@ -163,7 +162,7 @@ public final class StoryItemSetContainerComponent: Component { close: @escaping () -> Void, navigate: @escaping (NavigationDirection) -> Void, delete: @escaping () -> Void, - markAsSeen: @escaping (StoryId) -> Void, + markAsSeen: @escaping (EngineStoryId) -> Void, reorder: @escaping () -> Void, createToFolder: @escaping (String, [EngineStoryItem]) -> Void, addToFolder: @escaping (Int64) -> Void, @@ -363,11 +362,11 @@ public final class StoryItemSetContainerComponent: Component { } final class CaptionItem { - let itemId: StoryId + let itemId: EngineStoryId let externalState = StoryContentCaptionComponent.ExternalState() let view = ComponentView() - init(itemId: StoryId) { + init(itemId: EngineStoryId) { self.itemId = itemId } } @@ -471,7 +470,7 @@ public final class StoryItemSetContainerComponent: Component { var isSearchActive: Bool = false - var viewLists: [StoryId: ViewList] = [:] + var viewLists: [EngineStoryId: ViewList] = [:] let viewListsContainer: UIView var isEditingStory: Bool = false @@ -479,8 +478,8 @@ public final class StoryItemSetContainerComponent: Component { var itemLayout: ItemLayout? var ignoreScrolling: Bool = false - var visibleItems: [StoryId: VisibleItem] = [:] - var trulyValidIds: [StoryId] = [] + var visibleItems: [EngineStoryId: VisibleItem] = [:] + var trulyValidIds: [EngineStoryId] = [] var reactionContextNode: ReactionContextNode? weak var disappearingReactionContextNode: ReactionContextNode? @@ -506,8 +505,8 @@ public final class StoryItemSetContainerComponent: Component { let transitionCloneContainerView: UIView - private var awaitingSwitchToId: (from: StoryId, to: StoryId)? - private var animateNextNavigationId: StoryId? + private var awaitingSwitchToId: (from: EngineStoryId, to: EngineStoryId)? + private var animateNextNavigationId: EngineStoryId? private var initializedOffset: Bool = false private var viewListPanState: PanState? @@ -1498,8 +1497,8 @@ public final class StoryItemSetContainerComponent: Component { hintAllowSynchronousLoads = hint.allowSynchronousLoads } - var validIds: [StoryId] = [] - var trulyValidIds: [StoryId] = [] + var validIds: [EngineStoryId] = [] + var trulyValidIds: [EngineStoryId] = [] let centralItemX = itemLayout.contentFrame.center.x @@ -1980,7 +1979,7 @@ public final class StoryItemSetContainerComponent: Component { self.trulyValidIds = trulyValidIds - var removeIds: [StoryId] = [] + var removeIds: [EngineStoryId] = [] for (id, visibleItem) in self.visibleItems { if !validIds.contains(id) { removeIds.append(id) @@ -2001,7 +2000,7 @@ public final class StoryItemSetContainerComponent: Component { return } let progressMode = self.itemProgressMode() - var centralId: StoryId? + var centralId: EngineStoryId? if let component = self.component { centralId = component.slice.item.id } @@ -3442,7 +3441,7 @@ public final class StoryItemSetContainerComponent: Component { let minimizedHeight = max(100.0, availableSize.height - (325.0 + 12.0)) let defaultHeight = 60.0 + component.safeInsets.bottom + 1.0 - var validViewListIds: [StoryId] = [] + var validViewListIds: [EngineStoryId] = [] var displayViewLists = false if case .liveStream = component.slice.item.storyItem.media { @@ -3455,7 +3454,7 @@ public final class StoryItemSetContainerComponent: Component { var viewListHeightMidFraction: CGFloat = 0.0 if displayViewLists, let currentIndex = component.slice.allItems.firstIndex(where: { $0.id == component.slice.item.id }) { - var visibleViewListIds: [StoryId] = [component.slice.item.id] + var visibleViewListIds: [EngineStoryId] = [component.slice.item.id] if self.viewListDisplayState != .hidden, let viewListPanState = self.viewListPanState { if currentIndex != 0 { if viewListPanState.fraction > 0.0 { @@ -3469,7 +3468,7 @@ public final class StoryItemSetContainerComponent: Component { } } - var preloadViewListIds: [(StoryId, EngineStoryItem.Views)] = [] + var preloadViewListIds: [(EngineStoryId, EngineStoryItem.Views)] = [] if let views = component.slice.item.storyItem.views { preloadViewListIds.append((component.slice.item.id, views)) } @@ -3507,7 +3506,7 @@ public final class StoryItemSetContainerComponent: Component { } var fixedAnimationOffset: CGFloat = 0.0 - var applyFixedAnimationOffsetIds: [StoryId] = [] + var applyFixedAnimationOffsetIds: [EngineStoryId] = [] let normalCollapsedContentAreaHeight: CGFloat = availableSize.height - minimizedHeight @@ -3929,7 +3928,7 @@ public final class StoryItemSetContainerComponent: Component { } else { self.viewListMetrics = nil } - var removeViewListIds: [StoryId] = [] + var removeViewListIds: [EngineStoryId] = [] for (id, viewList) in self.viewLists { if !validViewListIds.contains(id) { removeViewListIds.append(id) @@ -4544,7 +4543,7 @@ public final class StoryItemSetContainerComponent: Component { } var forwardInfoStory: Signal? = nil if let forwardInfo = component.slice.item.storyItem.forwardInfo, case let .known(peer, id, _) = forwardInfo { - forwardInfoStory = component.slice.forwardInfoStories[StoryId(peerId: peer.id, id: id)]?.get() + forwardInfoStory = component.slice.forwardInfoStories[EngineStoryId(peerId: peer.id, id: id)]?.get() } let captionSize = captionItem.view.update( transition: captionItemTransition, @@ -4830,7 +4829,7 @@ public final class StoryItemSetContainerComponent: Component { } } case let .custom(fileId): - selectedItems.insert(AnyHashable(MediaId(namespace: Namespaces.Media.CloudFile, id: fileId))) + selectedItems.insert(AnyHashable(EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: fileId))) } } @@ -4969,8 +4968,8 @@ public final class StoryItemSetContainerComponent: Component { self.state?.updated(transition: ComponentTransition(animation: .curve(duration: 0.25, curve: .easeInOut))) var text = "" - var messageAttributes: [MessageAttribute] = [] - var inlineStickers: [MediaId : Media] = [:] + var messageAttributes: [EngineMessage.Attribute] = [] + var inlineStickers: [EngineMedia.Id : EngineRawMedia] = [:] switch updateReaction { case let .builtin(textValue): text = textValue @@ -5654,7 +5653,7 @@ public final class StoryItemSetContainerComponent: Component { return } - let storyId = StoryId(peerId: peer.id, id: id) + let storyId = EngineStoryId(peerId: peer.id, id: id) guard let viewList = self.viewLists[component.slice.item.id], let viewListView = viewList.view.view as? StoryItemSetViewListComponent.View, let viewListContext = viewListView.currentViewList else { return @@ -5681,7 +5680,7 @@ public final class StoryItemSetContainerComponent: Component { transitionIn: transitionIn, transitionOut: { [weak sourceView, weak viewListView] peerId, storyIdValue in var destinationView: UIView? - if let view = viewListView?.sourceView(storyId: StoryId(peerId: peerId, id: storyIdValue as? Int32 ?? 0)) { + if let view = viewListView?.sourceView(storyId: EngineStoryId(peerId: peerId, id: storyIdValue as? Int32 ?? 0)) { destinationView = view } else { destinationView = sourceView @@ -6478,7 +6477,7 @@ public final class StoryItemSetContainerComponent: Component { if let story = folderPreview.item { var imageSignal: Signal? - var selectedMedia: Media? + var selectedMedia: EngineRawMedia? if let image = story.media._asMedia() as? TelegramMediaImage { selectedMedia = image } else if let file = story.media._asMedia() as? TelegramMediaFile { diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerPaste.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerPaste.swift index 6e8d0ca603..c55fc79bda 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerPaste.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerPaste.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramUIPreferences import AccountContext @@ -113,7 +112,7 @@ extension ChatControllerImpl { fileAttributes.append(.Sticker(displayText: "", packReference: nil, maskData: nil)) fileAttributes.append(.ImageSize(size: PixelDimensions(size))) - let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "image/webp", size: Int64(data.count), attributes: fileAttributes, alternativeRepresentations: []) + let media = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "image/webp", size: Int64(data.count), attributes: fileAttributes, alternativeRepresentations: []) let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), threadId: strongSelf.chatLocation.threadId, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) strongSelf.presentPaidMessageAlertIfNeeded(completion: { [weak self] postpone in @@ -256,7 +255,7 @@ extension ChatControllerImpl { let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max)) self.context.engine.resources.copyResourceData(id: EngineMediaResource.Id(resource.id), fromTempPath: path) - let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/webm", size: 0, attributes: fileAttributes, alternativeRepresentations: []) + let file = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/webm", size: 0, attributes: fileAttributes, alternativeRepresentations: []) self.enqueueStickerFile(file) default: break diff --git a/submodules/TelegramUI/Sources/ChatControllerContentData.swift b/submodules/TelegramUI/Sources/ChatControllerContentData.swift index 8e30ccc23b..c6ce9faa0b 100644 --- a/submodules/TelegramUI/Sources/ChatControllerContentData.swift +++ b/submodules/TelegramUI/Sources/ChatControllerContentData.swift @@ -320,7 +320,7 @@ extension ChatControllerImpl { return (nil, value) } } else { - return context.peerChannelMemberCategoriesContextsManager.recentOnlineSmall(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) + return context.peerChannelMemberCategoriesContextsManager.recentOnlineSmall(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId) |> map { value -> (total: Int32?, recent: Int32?) in return (value.total, value.recent) } @@ -811,8 +811,8 @@ extension ChatControllerImpl { strongSelf.state.threadInfo = threadInfo if wasGroupChannel != isGroupChannel { if let isGroupChannel = isGroupChannel, isGroupChannel { - let (recentDisposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { _ in }) - let (adminsDisposable, _) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { _ in }) + let (recentDisposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { _ in }) + let (adminsDisposable, _) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { _ in }) let disposable = DisposableSet() disposable.add(recentDisposable) disposable.add(adminsDisposable) @@ -1380,7 +1380,7 @@ extension ChatControllerImpl { return (nil, value) } } else { - return context.peerChannelMemberCategoriesContextsManager.recentOnlineSmall(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) + return context.peerChannelMemberCategoriesContextsManager.recentOnlineSmall(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerId) |> map { value -> (total: Int32?, recent: Int32?) in return (value.total, value.recent) } @@ -1694,8 +1694,8 @@ extension ChatControllerImpl { if wasGroupChannel != isGroupChannel { if let isGroupChannel = isGroupChannel, isGroupChannel { - let (recentDisposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { _ in }) - let (adminsDisposable, _) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { _ in }) + let (recentDisposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { _ in }) + let (adminsDisposable, _) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { _ in }) let disposable = DisposableSet() disposable.add(recentDisposable) disposable.add(adminsDisposable) diff --git a/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift b/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift index 71c92156fb..ededfd221f 100644 --- a/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift +++ b/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift @@ -1,7 +1,6 @@ import Foundation import TelegramPresentationData import AccountContext -import Postbox import TelegramCore import SwiftSignalKit import Display @@ -16,7 +15,7 @@ import TopMessageReactions import ChatMessagePaymentAlertController extension ChatControllerImpl { - func forwardMessages(messageIds: [MessageId], options: ChatInterfaceForwardOptionsState? = nil, resetCurrent: Bool = false) { + func forwardMessages(messageIds: [EngineMessage.Id], options: ChatInterfaceForwardOptionsState? = nil, resetCurrent: Bool = false) { let _ = (self.context.engine.data.get(EngineDataMap( messageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init) )) @@ -28,7 +27,7 @@ extension ChatControllerImpl { }) } - func forwardMessages(messages: [Message], options: ChatInterfaceForwardOptionsState? = nil, resetCurrent: Bool) { + func forwardMessages(messages: [EngineRawMessage], options: ChatInterfaceForwardOptionsState? = nil, resetCurrent: Bool) { let _ = self.presentVoiceMessageDiscardAlert(action: { var filter: ChatListNodePeersFilter = [.onlyWriteable, .excludeDisabled, .doNotSearchMessages] var hasPublicPolls = false @@ -143,7 +142,7 @@ extension ChatControllerImpl { let inputText = convertMarkdownToAttributes(messageText) for text in breakChatInputText(trimChatInputText(inputText)) { if text.length != 0 { - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text)) if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) @@ -153,7 +152,7 @@ extension ChatControllerImpl { } } - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] attributes.append(ForwardOptionsMessageAttribute(hideNames: forwardOptions?.hideNames == true, hideCaptions: forwardOptions?.hideCaptions == true)) result.append(contentsOf: messages.map { message -> EnqueueMessage in diff --git a/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift b/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift index 14c12e7075..65bd61e2bf 100644 --- a/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift +++ b/submodules/TelegramUI/Sources/ChatControllerOpenAttachmentMenu.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import Display import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -42,7 +41,7 @@ extension ChatControllerImpl { enum AttachMenuSubject { case `default` case edit(mediaOptions: MessageMediaEditingOptions, mediaReference: AnyMediaReference) - case bot(id: PeerId, payload: String?, justInstalled: Bool) + case bot(id: EnginePeer.Id, payload: String?, justInstalled: Bool) case gift } @@ -386,7 +385,7 @@ extension ChatControllerImpl { groupingKey = Int64.random(in: .min ..< .max) } - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] var text = "" if let caption { text = caption.string @@ -436,7 +435,7 @@ extension ChatControllerImpl { groupingKey = Int64.random(in: .min ..< .max) } - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] var text = "" if let caption { text = caption.string @@ -472,7 +471,7 @@ extension ChatControllerImpl { controller.prepareForReuse() return true } - let selfPeerId: PeerId + let selfPeerId: EnginePeer.Id if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer { if let peer = peer as? TelegramChannel, case .broadcast = peer.info { selfPeerId = peer.id @@ -540,7 +539,7 @@ extension ChatControllerImpl { if let strongSelf = self, let (peers, _, silent, scheduleTime, text, parameters) = peers { var textEnqueueMessage: EnqueueMessage? if let text = text, text.length > 0 { - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text)) if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) @@ -606,7 +605,7 @@ extension ChatControllerImpl { strongSelf.sendMessages(strongSelf.transformEnqueueMessages(enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime)) }) } else if let peer = peers.first { - let dataSignal: Signal<(Peer?, DeviceContactExtendedData?), NoError> + let dataSignal: Signal<(EngineRawPeer?, DeviceContactExtendedData?), NoError> switch peer { case let .peer(contact, _, _): guard case let .user(contact) = contact, let phoneNumber = contact.phone else { @@ -616,7 +615,7 @@ extension ChatControllerImpl { let context = strongSelf.context dataSignal = (strongSelf.context.sharedContext.contactDataManager?.basicData() ?? .single([:])) |> take(1) - |> mapToSignal { basicData -> Signal<(Peer?, DeviceContactExtendedData?), NoError> in + |> mapToSignal { basicData -> Signal<(EngineRawPeer?, DeviceContactExtendedData?), NoError> in var stableId: String? let queryPhoneNumber = formatPhoneNumber(context: context, number: phoneNumber) outer: for (id, data) in basicData { @@ -631,7 +630,7 @@ extension ChatControllerImpl { if let stableId = stableId { return (context.sharedContext.contactDataManager?.extendedData(stableId: stableId) ?? .single(nil)) |> take(1) - |> map { extendedData -> (Peer?, DeviceContactExtendedData?) in + |> map { extendedData -> (EngineRawPeer?, DeviceContactExtendedData?) in return (contact, extendedData) } } else { @@ -641,7 +640,7 @@ extension ChatControllerImpl { case let .deviceContact(id, _): dataSignal = (strongSelf.context.sharedContext.contactDataManager?.extendedData(stableId: id) ?? .single(nil)) |> take(1) - |> map { extendedData -> (Peer?, DeviceContactExtendedData?) in + |> map { extendedData -> (EngineRawPeer?, DeviceContactExtendedData?) in return (nil, extendedData) } } @@ -666,7 +665,7 @@ extension ChatControllerImpl { if let textEnqueueMessage = textEnqueueMessage { enqueueMessages.append(textEnqueueMessage) } - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] if let parameters { if let effect = parameters.effect { attributes.append(EffectMessageAttribute(id: effect.id)) @@ -1267,7 +1266,7 @@ extension ChatControllerImpl { attributes.append(.Audio(isVoice: false, duration: audioMetadata.duration, title: audioMetadata.title, performer: audioMetadata.performer, waveform: nil)) } - let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(item.fileSize), attributes: attributes, alternativeRepresentations: []) + let file = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(item.fileSize), attributes: attributes, alternativeRepresentations: []) let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), threadId: strongSelf.chatLocation.threadId, replyToMessageId: replyMessageSubject?.subjectModel, replyToStoryId: nil, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: []) messages.append(message) } @@ -1691,7 +1690,7 @@ extension ChatControllerImpl { guard let peer = self.presentationInterfaceState.renderedPeer?.peer else { return } - let selfPeerId: PeerId + let selfPeerId: EnginePeer.Id if let peer = peer as? TelegramChannel, case .broadcast = peer.info { selfPeerId = peer.id } else if let peer = peer as? TelegramChannel, case .group = peer.info, peer.hasPermission(.canBeAnonymous) { @@ -1785,7 +1784,7 @@ extension ChatControllerImpl { strongSelf.sendMessages(enqueueMessages, postpone: postpone) }) } else if let peer = peers.first { - let dataSignal: Signal<(Peer?, DeviceContactExtendedData?), NoError> + let dataSignal: Signal<(EngineRawPeer?, DeviceContactExtendedData?), NoError> switch peer { case let .peer(contact, _, _): guard case let .user(contact) = contact, let phoneNumber = contact.phone else { @@ -1795,7 +1794,7 @@ extension ChatControllerImpl { let context = strongSelf.context dataSignal = (strongSelf.context.sharedContext.contactDataManager?.basicData() ?? .single([:])) |> take(1) - |> mapToSignal { basicData -> Signal<(Peer?, DeviceContactExtendedData?), NoError> in + |> mapToSignal { basicData -> Signal<(EngineRawPeer?, DeviceContactExtendedData?), NoError> in var stableId: String? let queryPhoneNumber = formatPhoneNumber(context: context, number: phoneNumber) outer: for (id, data) in basicData { @@ -1810,7 +1809,7 @@ extension ChatControllerImpl { if let stableId = stableId { return (context.sharedContext.contactDataManager?.extendedData(stableId: stableId) ?? .single(nil)) |> take(1) - |> map { extendedData -> (Peer?, DeviceContactExtendedData?) in + |> map { extendedData -> (EngineRawPeer?, DeviceContactExtendedData?) in return (contact, extendedData) } } else { @@ -1820,7 +1819,7 @@ extension ChatControllerImpl { case let .deviceContact(id, _): dataSignal = (strongSelf.context.sharedContext.contactDataManager?.extendedData(stableId: id) ?? .single(nil)) |> take(1) - |> map { extendedData -> (Peer?, DeviceContactExtendedData?) in + |> map { extendedData -> (EngineRawPeer?, DeviceContactExtendedData?) in return (nil, extendedData) } } @@ -2112,7 +2111,7 @@ extension ChatControllerImpl { } }, nil) - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] if !poll.description.entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: poll.description.entities)) } @@ -2122,7 +2121,7 @@ extension ChatControllerImpl { attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaPoll( - pollId: MediaId(namespace: Namespaces.Media.LocalPoll, id: Int64.random(in: Int64.min...Int64.max)), + pollId: EngineMedia.Id(namespace: Namespaces.Media.LocalPoll, id: Int64.random(in: Int64.min...Int64.max)), publicity: poll.publicity, kind: poll.kind, text: poll.text.string, diff --git a/submodules/TelegramUI/Sources/ChatControllerOpenMessageShareMenu.swift b/submodules/TelegramUI/Sources/ChatControllerOpenMessageShareMenu.swift index 992b1807ae..01c28ff53b 100644 --- a/submodules/TelegramUI/Sources/ChatControllerOpenMessageShareMenu.swift +++ b/submodules/TelegramUI/Sources/ChatControllerOpenMessageShareMenu.swift @@ -1,7 +1,6 @@ import Foundation import TelegramPresentationData import AccountContext -import Postbox import TelegramCore import SwiftSignalKit import ContextUI diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index 2025847615..30de107397 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import TelegramCore import AsyncDisplayKit import Display @@ -48,11 +47,11 @@ private struct MessageContextMenuData { let messageActions: ChatAvailableMessageActions } -func canEditMessage(context: AccountContext, limitsConfiguration: EngineConfiguration.Limits, message: Message) -> Bool { +func canEditMessage(context: AccountContext, limitsConfiguration: EngineConfiguration.Limits, message: EngineRawMessage) -> Bool { return canEditMessage(accountPeerId: context.account.peerId, limitsConfiguration: limitsConfiguration, message: message) } -private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: EngineConfiguration.Limits, message: Message, reschedule: Bool = false) -> Bool { +private func canEditMessage(accountPeerId: EnginePeer.Id, limitsConfiguration: EngineConfiguration.Limits, message: EngineRawMessage, reschedule: Bool = false) -> Bool { var hasEditRights = false var unlimitedInterval = reschedule @@ -190,7 +189,7 @@ private func canEditFactCheck(appConfig: AppConfiguration) -> Bool { return false } -private func canViewReadStats(message: Message, participantCount: Int?, isMessageRead: Bool, isPremium: Bool, appConfig: AppConfiguration) -> Bool { +private func canViewReadStats(message: EngineRawMessage, participantCount: Int?, isMessageRead: Bool, isPremium: Bool, appConfig: AppConfiguration) -> Bool { guard let peer = message.peers[message.id.peerId] else { return false } @@ -285,7 +284,7 @@ private func canViewReadStats(message: Message, participantCount: Int?, isMessag return true } -func canReplyInChat(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, accountPeerId: PeerId) -> Bool { +func canReplyInChat(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, accountPeerId: EnginePeer.Id) -> Bool { if case let .customChatContents(contents) = chatPresentationInterfaceState.subject, case .hashTagSearch = contents.kind { return true } @@ -383,7 +382,7 @@ enum ChatMessageContextMenuAction { case sheet(ChatMessageContextMenuSheetAction) } -func messageMediaEditingOptions(message: Message) -> MessageMediaEditingOptions { +func messageMediaEditingOptions(message: EngineRawMessage) -> MessageMediaEditingOptions { if message.id.peerId.namespace == Namespaces.Peer.SecretChat { return [] } @@ -436,7 +435,7 @@ func messageMediaEditingOptions(message: Message) -> MessageMediaEditingOptions return options } -func updatedChatEditInterfaceMessageState(context: AccountContext, state: ChatPresentationInterfaceState, message: Message) -> (ChatPresentationInterfaceState, (UrlPreviewState?, Disposable)?) { +func updatedChatEditInterfaceMessageState(context: AccountContext, state: ChatPresentationInterfaceState, message: EngineRawMessage) -> (ChatPresentationInterfaceState, (UrlPreviewState?, Disposable)?) { var updated = state for media in message.media { if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content { @@ -480,7 +479,7 @@ func updatedChatEditInterfaceMessageState(context: AccountContext, state: ChatPr ) } -func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, messages: [Message], controllerInteraction: ChatControllerInteraction?, selectAll: Bool, interfaceInteraction: ChatPanelInterfaceInteraction?, readStats: MessageReadStats? = nil, messageNode: ChatMessageItemView? = nil) -> Signal { +func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, messages: [EngineRawMessage], controllerInteraction: ChatControllerInteraction?, selectAll: Bool, interfaceInteraction: ChatPanelInterfaceInteraction?, readStats: MessageReadStats? = nil, messageNode: ChatMessageItemView? = nil) -> Signal { guard let interfaceInteraction = interfaceInteraction, let controllerInteraction = controllerInteraction else { return .single(ContextController.Items(content: .list([]))) } @@ -695,8 +694,8 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState return .single(ContextController.Items(content: .list(actions))) } - var loadStickerSaveStatus: MediaId? - var loadCopyMediaResource: MediaResource? + var loadStickerSaveStatus: EngineMedia.Id? + var loadCopyMediaResource: TelegramMediaResource? var isAction = false var isGiveawayServiceMessage = false var diceEmoji: String? @@ -872,7 +871,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState let isScheduled = chatPresentationInterfaceState.subject == .scheduledMessages - let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?, EnginePeer?), NoError> = combineLatest( + let dataSignal: Signal<(MessageContextMenuData, [EngineMessage.Id: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?, EnginePeer?), NoError> = combineLatest( loadLimits, loadStickerSaveStatusSignal, loadResourceStatusSignal, @@ -887,7 +886,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState context.engine.peers.notificationSoundList() |> take(1), context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) ) - |> map { limitsAndAppConfig, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, infoSummaryData, isMessageRead, messageViewsPrivacyTips, availableReactions, sharedData, notificationSoundList, accountPeer -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?, EnginePeer?) in + |> map { limitsAndAppConfig, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, infoSummaryData, isMessageRead, messageViewsPrivacyTips, availableReactions, sharedData, notificationSoundList, accountPeer -> (MessageContextMenuData, [EngineMessage.Id: ChatUpdatingMessageMedia], InfoSummaryData, AppConfiguration, Bool, Int32, AvailableReactions?, TranslationSettings, LoggingSettings, NotificationSoundList?, EnginePeer?) in let (limitsConfiguration, appConfig) = limitsAndAppConfig var canEdit = false if !isAction { @@ -1003,7 +1002,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState strongController.dismiss() let id = Int64.random(in: Int64.min ... Int64.max) - let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: logPath, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: "CallStats.log")], alternativeRepresentations: []) + let file = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: logPath, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: "CallStats.log")], alternativeRepresentations: []) let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).startStandalone() @@ -1640,7 +1639,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState } if canPin { - var pinnedSelectedMessageId: MessageId? + var pinnedSelectedMessageId: EngineMessage.Id? for message in messages { if message.tags.contains(.pinned) { pinnedSelectedMessageId = message.id @@ -1709,7 +1708,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuCopyLink, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.actionSheet.primaryTextColor) }, action: { _, f in - var threadMessageId: MessageId? + var threadMessageId: EngineMessage.Id? if case let .replyThread(replyThreadMessage) = chatPresentationInterfaceState.chatLocation { threadMessageId = replyThreadMessage.effectiveMessageId } @@ -2355,7 +2354,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState } } -func canPerformEditingActions(limits: LimitsConfiguration, accountPeerId: PeerId, message: Message, unlimitedInterval: Bool) -> Bool { +func canPerformEditingActions(limits: LimitsConfiguration, accountPeerId: EnginePeer.Id, message: EngineRawMessage, unlimitedInterval: Bool) -> Bool { if message.id.peerId == accountPeerId { return true } @@ -2372,7 +2371,7 @@ func canPerformEditingActions(limits: LimitsConfiguration, accountPeerId: PeerId return false } -private func canPerformDeleteActions(limits: LimitsConfiguration, accountPeerId: PeerId, message: Message) -> Bool { +private func canPerformDeleteActions(limits: LimitsConfiguration, accountPeerId: EnginePeer.Id, message: EngineRawMessage) -> Bool { if message.id.peerId == accountPeerId { return true } @@ -2396,7 +2395,7 @@ private func canPerformDeleteActions(limits: LimitsConfiguration, accountPeerId: return false } -func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: PeerId, messageIds: Set, messages: [MessageId: Message] = [:], peers: [PeerId: Peer] = [:], keepUpdated: Bool) -> Signal { +func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set, messages: [EngineMessage.Id: EngineRawMessage] = [:], peers: [EnginePeer.Id: EngineRawPeer] = [:], keepUpdated: Bool) -> Signal { return engine.data.subscribe( TelegramEngine.EngineData.Item.Configuration.Limits(), EngineDataMap(Set(messageIds.map(\.peerId)).map(TelegramEngine.EngineData.Item.Peer.Peer.init)), @@ -2414,9 +2413,9 @@ func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: Peer isPremium = false } - var optionsMap: [MessageId: ChatAvailableMessageActionOptions] = [:] - var banPeer: Peer? - var banPeers: [Peer] = [] + var optionsMap: [EngineMessage.Id: ChatAvailableMessageActionOptions] = [:] + var banPeer: EngineRawPeer? + var banPeers: [EngineRawPeer] = [] var hadPersonalIncoming = false var hadBanPeerId = false var disableDelete = false @@ -2427,7 +2426,7 @@ func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: Peer var setTag = false var commonTags: Set? - func getPeer(_ peerId: PeerId) -> Peer? { + func getPeer(_ peerId: EnginePeer.Id) -> EngineRawPeer? { if let maybePeer = peerMap[peerId], let peer = maybePeer { return peer._asPeer() } else if let peer = peers[peerId] { @@ -2437,7 +2436,7 @@ func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: Peer } } - func getMessage(_ messageId: MessageId) -> Message? { + func getMessage(_ messageId: EngineMessage.Id) -> EngineRawMessage? { if let maybeMessage = messageMap[messageId], let message = maybeMessage { return message._asMessage() } else if let message = messages[messageId] { @@ -2447,7 +2446,7 @@ func chatAvailableMessageActionsImpl(engine: TelegramEngine, accountPeerId: Peer } } - func isPeerCopyProtected(_ peerId: PeerId) -> Bool? { + func isPeerCopyProtected(_ peerId: EnginePeer.Id) -> Bool? { let copyProtection = copyProtectionMap[peerId] let myCopyProtection = myCopyProtectionMap[peerId] if copyProtection == true || myCopyProtection == true { @@ -2914,10 +2913,10 @@ private final class ChatDeleteMessageContextItemNode: ASDisplayNode, ContextMenu final class ChatMessageAuthorContextItem: ContextMenuCustomItem { fileprivate let context: AccountContext - fileprivate let message: Message + fileprivate let message: EngineRawMessage fileprivate let action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, EnginePeer) -> Void)? - init(context: AccountContext, message: Message, action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, EnginePeer) -> Void)?) { + init(context: AccountContext, message: EngineRawMessage, action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, EnginePeer) -> Void)?) { self.context = context self.message = message self.action = action @@ -3158,13 +3157,13 @@ private final class ChatMessageAuthorContextItemNode: ASDisplayNode, ContextMenu final class ChatReadReportContextItem: ContextMenuCustomItem { fileprivate let context: AccountContext - fileprivate let message: Message + fileprivate let message: EngineRawMessage fileprivate let hasReadReports: Bool fileprivate let isEdit: Bool fileprivate let stats: MessageReadStats? fileprivate let action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, MessageReadStats?, [StickerPackCollectionInfo], TelegramMediaFile?) -> Void)? - init(context: AccountContext, message: Message, hasReadReports: Bool, isEdit: Bool, stats: MessageReadStats?, action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, MessageReadStats?, [StickerPackCollectionInfo], TelegramMediaFile?) -> Void)?) { + init(context: AccountContext, message: EngineRawMessage, hasReadReports: Bool, isEdit: Bool, stats: MessageReadStats?, action: ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void, MessageReadStats?, [StickerPackCollectionInfo], TelegramMediaFile?) -> Void)?) { self.context = context self.message = message self.hasReadReports = hasReadReports @@ -3746,10 +3745,10 @@ private func stringForRemainingTime(_ duration: Int32, strings: PresentationStri final class ChatRateTranscriptionContextItem: ContextMenuCustomItem { fileprivate let context: AccountContext - fileprivate let message: Message + fileprivate let message: EngineRawMessage fileprivate let action: (Bool) -> Void - init(context: AccountContext, message: Message, action: @escaping (Bool) -> Void) { + init(context: AccountContext, message: EngineRawMessage, action: @escaping (Bool) -> Void) { self.context = context self.message = message self.action = action diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift index 2c880d7c8e..2b3f3484ea 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import SwiftSignalKit import TelegramCore -import Postbox import TelegramUIPreferences import LegacyComponents import TextFormat @@ -14,7 +13,7 @@ import TelegramNotices import ChatPresentationInterfaceState import ChatContextQuery -func contextQueryResultStateForChatInterfacePresentationState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentQueryStates: inout [ChatPresentationInputQueryKind: (ChatPresentationInputQuery, Disposable)], requestBotLocationStatus: @escaping (PeerId) -> Void) -> [ChatPresentationInputQueryKind: ChatContextQueryUpdate] { +func contextQueryResultStateForChatInterfacePresentationState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentQueryStates: inout [ChatPresentationInputQueryKind: (ChatPresentationInputQuery, Disposable)], requestBotLocationStatus: @escaping (EnginePeer.Id) -> Void) -> [ChatPresentationInputQueryKind: ChatContextQueryUpdate] { let inputQueries = inputContextQueriesForChatPresentationIntefaceState(chatPresentationInterfaceState).filter({ query in if chatPresentationInterfaceState.editMessageState != nil { switch query { @@ -54,7 +53,7 @@ func contextQueryResultStateForChatInterfacePresentationState(_ chatPresentation return updates } -private func updatedContextQueryResultStateForQuery(context: AccountContext, peer: Peer?, chatLocation: ChatLocation, inputQuery: ChatPresentationInputQuery, previousQuery: ChatPresentationInputQuery?, requestBotLocationStatus: @escaping (PeerId) -> Void) -> Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, ChatContextQueryError> { +private func updatedContextQueryResultStateForQuery(context: AccountContext, peer: EngineRawPeer?, chatLocation: ChatLocation, inputQuery: ChatPresentationInputQuery, previousQuery: ChatPresentationInputQuery?, requestBotLocationStatus: @escaping (EnginePeer.Id) -> Void) -> Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, ChatContextQueryError> { switch inputQuery { case let .emoji(query): var signal: Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, ChatContextQueryError> = .complete() @@ -375,14 +374,14 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee if query.isSingleEmoji { return combineLatest( - context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), + context.engine.itemCollections.allItems(namespace: Namespaces.ItemCollection.CloudEmojiPacks), hasPremium ) - |> map { view, hasPremium -> [(String, TelegramMediaFile?, String)] in + |> map { items, hasPremium -> [(String, TelegramMediaFile?, String)] in var result: [(String, TelegramMediaFile?, String)] = [] - - for entry in view.entries { - guard let item = entry.item as? StickerPackItem, !item.file.isPremiumEmoji || hasPremium else { + + for entry in items { + guard let item = entry as? StickerPackItem, !item.file.isPremiumEmoji || hasPremium else { continue } let stringRepresentations = item.getStringRepresentationsOfIndexKeys() @@ -418,21 +417,21 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee |> castError(ChatContextQueryError.self) |> mapToSignal { keywords -> Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, ChatContextQueryError> in return combineLatest( - context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), + context.engine.itemCollections.allItems(namespace: Namespaces.ItemCollection.CloudEmojiPacks), hasPremium ) - |> map { view, hasPremium -> [(String, TelegramMediaFile?, String)] in + |> map { items, hasPremium -> [(String, TelegramMediaFile?, String)] in var result: [(String, TelegramMediaFile?, String)] = [] - + var allEmoticons: [String: String] = [:] for keyword in keywords { for emoticon in keyword.emoticons { allEmoticons[emoticon] = keyword.keyword } } - - for entry in view.entries { - guard let item = entry.item as? StickerPackItem, !item.file.isPremiumEmoji || hasPremium else { + + for entry in items { + guard let item = entry as? StickerPackItem, !item.file.isPremiumEmoji || hasPremium else { continue } let stringRepresentations = item.getStringRepresentationsOfIndexKeys() @@ -556,7 +555,7 @@ struct UrlPreviewState { var detectedUrls: [String] } -func urlPreviewStateForInputText(_ inputText: NSAttributedString?, context: AccountContext, currentQuery: UrlPreviewState?, forPeerId: PeerId?) -> (UrlPreviewState?, Signal<(TelegramMediaWebpage?) -> (TelegramMediaWebpage, String)?, NoError>)? { +func urlPreviewStateForInputText(_ inputText: NSAttributedString?, context: AccountContext, currentQuery: UrlPreviewState?, forPeerId: EnginePeer.Id?) -> (UrlPreviewState?, Signal<(TelegramMediaWebpage?) -> (TelegramMediaWebpage, String)?, NoError>)? { guard let _ = inputText else { if currentQuery != nil { return (nil, .single({ _ in return nil })) diff --git a/submodules/TelegramUI/Sources/MediaManager.swift b/submodules/TelegramUI/Sources/MediaManager.swift index 7163222876..6d9006381d 100644 --- a/submodules/TelegramUI/Sources/MediaManager.swift +++ b/submodules/TelegramUI/Sources/MediaManager.swift @@ -330,7 +330,7 @@ public final class MediaManagerImpl: NSObject, MediaManager { |> distinctUntilChanged(isEqual: { $0?.0 === $1?.0 && $0?.1 == $1?.1 }) |> mapToSignal { value -> Signal in if let (account, value) = value { - return playerAlbumArt(postbox: account.postbox, engine: TelegramEngine(account: account), fileReference: value.fullSizeResource.file, albumArt: value, thumbnail: false) + return playerAlbumArt(engine: TelegramEngine(account: account), fileReference: value.fullSizeResource.file, albumArt: value, thumbnail: false) |> map { generator -> UIImage? in let arguments = TransformImageArguments(corners: ImageCorners(), imageSize: CGSize(width: 640, height: 640), boundingSize: CGSize(width: 640, height: 640), intrinsicInsets: .zero) return generator(arguments)?.generateImage() diff --git a/submodules/TelegramUI/Sources/NavigateToChatController.swift b/submodules/TelegramUI/Sources/NavigateToChatController.swift index 4f9e8b5f2b..4a2555811b 100644 --- a/submodules/TelegramUI/Sources/NavigateToChatController.swift +++ b/submodules/TelegramUI/Sources/NavigateToChatController.swift @@ -3,7 +3,6 @@ import UIKit import Display import SwiftSignalKit import TelegramCore -import Postbox import AccountContext import GalleryUI import InstantPageUI @@ -51,13 +50,10 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam if channel.flags.contains(.displayForumAsTabs) { viewForumAsMessages = .single(true) } else { - viewForumAsMessages = params.context.account.postbox.combinedView(keys: [.cachedPeerData(peerId: peer.id)]) + viewForumAsMessages = params.context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.CachedData(id: peer.id)) |> take(1) - |> map { combinedView in - guard let cachedDataView = combinedView.views[.cachedPeerData(peerId: peer.id)] as? CachedPeerDataView else { - return false - } - if let cachedData = cachedDataView.cachedPeerData as? CachedChannelData, case let .known(viewForumAsMessages) = cachedData.viewForumAsMessages, viewForumAsMessages { + |> map { cachedPeerData in + if let cachedData = cachedPeerData as? CachedChannelData, case let .known(viewForumAsMessages) = cachedData.viewForumAsMessages, viewForumAsMessages { return true } else { return false @@ -415,7 +411,7 @@ public func isOverlayControllerForChatNotificationOverlayPresentation(_ controll } public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, scrollToEndIfExists: Bool, keepStack: NavigateToChatKeepStack, animated: Bool) -> Signal { - return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: messageId, preload: false) + return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(EngineMessage.Id(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: messageId, preload: false) |> deliverOnMainQueue |> beforeNext { [weak context, weak navigationController] result in guard let context = context, let navigationController = navigationController else { @@ -479,7 +475,7 @@ public func chatControllerForForumThreadImpl(context: AccountContext, peerId: En initialTextInputState: initialTextInputState )) } else { - return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: nil, preload: false) + return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(EngineMessage.Id(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: nil, preload: false) |> deliverOnMainQueue |> `catch` { _ -> Signal in return .complete() diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 1f0fd76396..7dcccfc6ba 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -4,7 +4,6 @@ import Display import AsyncDisplayKit import ComponentFlow import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -86,7 +85,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu context: AccountContext, chatLocation: ChatLocation, type: MediaManagerPlayerType, - initialMessageId: MessageId, + initialMessageId: EngineMessage.Id, initialOrder: MusicPlaybackSettingsOrder, playlistLocation: SharedMediaPlaylistLocation?, requestDismiss: @escaping () -> Void, @@ -120,8 +119,8 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu self.currentIsReversed = true } - var openMessageImpl: ((MessageId) -> Bool)? - var openMessageContextMenuImpl: ((Message, ASDisplayNode, CGRect, Any?) -> Void)? + var openMessageImpl: ((EngineMessage.Id) -> Bool)? + var openMessageContextMenuImpl: ((EngineRawMessage, ASDisplayNode, CGRect, Any?) -> Void)? self.controllerInteraction = ChatControllerInteraction(openMessage: { message, _ in if let openMessageImpl = openMessageImpl { return openMessageImpl(message.id) @@ -306,7 +305,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu self.historyFrameTopMaskNode.image = generateCornersImage(theme: self.presentationData.theme) self.historyFrameTopMaskNode.isUserInteractionEnabled = false - let tagMask: MessageTags + let tagMask: EngineMessage.Tags switch type { case .music: tagMask = .music @@ -392,7 +391,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu self.currentAlbumArt = fileReferenceAndAlbumArt if let (fileReference, albumArt) = fileReferenceAndAlbumArt { - self.albumArtNode.setSignal(playerAlbumArt(postbox: self.context.account.postbox, engine: self.context.engine, fileReference: fileReference, albumArt: albumArt, thumbnail: false)) + self.albumArtNode.setSignal(playerAlbumArt(engine: self.context.engine, fileReference: fileReference, albumArt: albumArt, thumbnail: false)) } self.containerLayoutUpdated(layout, transition: .animated(duration: 0.25, curve: .easeInOut)) @@ -1195,8 +1194,8 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu } } - private func transitionToUpdatedHistoryNode(atMessage messageId: MessageId) { - let tagMask: MessageTags + private func transitionToUpdatedHistoryNode(atMessage messageId: EngineMessage.Id) { + let tagMask: EngineMessage.Tags switch self.type { case .music: tagMask = .music @@ -1366,7 +1365,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu } } - private func openMessageContextMenu(message: Message, node: ASDisplayNode, frame: CGRect, recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil, location: CGPoint? = nil) { + private func openMessageContextMenu(message: EngineRawMessage, node: ASDisplayNode, frame: CGRect, recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil, location: CGPoint? = nil) { guard let node = node as? ContextExtractedContentContainingNode, let peer = message.peers[message.id.peerId].flatMap({ PeerReference($0) }), let file = message.media.first(where: { $0 is TelegramMediaFile}) as? TelegramMediaFile else { return } diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControlsNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControlsNode.swift index 5ba432e116..80dd636401 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControlsNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControlsNode.swift @@ -758,7 +758,7 @@ final class OverlayAudioPlayerControlsNode: ASDisplayNode { if self.currentAlbumArt != albumArt || !self.currentAlbumArtInitialized { self.currentAlbumArtInitialized = true self.currentAlbumArt = albumArt - self.albumArtNode.setSignal(playerAlbumArt(postbox: self.account.postbox, engine: self.engine, fileReference: self.currentFileReference, albumArt: albumArt, thumbnail: true)) + self.albumArtNode.setSignal(playerAlbumArt(engine: self.engine, fileReference: self.currentFileReference, albumArt: albumArt, thumbnail: true)) self.requestAlbumArtDisplay?(nil) } } diff --git a/submodules/TelegramUI/Sources/OverlayInstantVideoNode.swift b/submodules/TelegramUI/Sources/OverlayInstantVideoNode.swift index e4c763d9ca..e341ec78b0 100644 --- a/submodules/TelegramUI/Sources/OverlayInstantVideoNode.swift +++ b/submodules/TelegramUI/Sources/OverlayInstantVideoNode.swift @@ -4,7 +4,6 @@ import AsyncDisplayKit import SwiftSignalKit import Display import TelegramCore -import Postbox import TelegramPresentationData import UniversalMediaPlayer import TelegramUIPreferences @@ -40,14 +39,14 @@ final class OverlayInstantVideoNode: OverlayMediaItemNode { var playbackEnded: (() -> Void)? - init(context: AccountContext, postbox: Postbox, audioSession: ManagedAudioSession, manager: UniversalVideoManager, content: UniversalVideoContent, close: @escaping () -> Void) { + init(context: AccountContext, audioSession: ManagedAudioSession, manager: UniversalVideoManager, content: UniversalVideoContent, close: @escaping () -> Void) { self.close = close self.content = content var togglePlayPauseImpl: (() -> Void)? let decoration = OverlayInstantVideoDecoration(tapped: { togglePlayPauseImpl?() }) - self.videoNode = UniversalVideoNode(context: context, postbox: postbox, audioSession: audioSession, manager: manager, decoration: decoration, content: content, priority: .secondaryOverlay, snapshotContentWhenGone: true) + self.videoNode = UniversalVideoNode(context: context, postbox: context.account.postbox, audioSession: audioSession, manager: manager, decoration: decoration, content: content, priority: .secondaryOverlay, snapshotContentWhenGone: true) self.decoration = decoration super.init() diff --git a/submodules/TelegramUI/Sources/PreparedChatHistoryViewTransition.swift b/submodules/TelegramUI/Sources/PreparedChatHistoryViewTransition.swift index cfdec9f045..85bab95ea4 100644 --- a/submodules/TelegramUI/Sources/PreparedChatHistoryViewTransition.swift +++ b/submodules/TelegramUI/Sources/PreparedChatHistoryViewTransition.swift @@ -1,6 +1,5 @@ import Foundation import SwiftSignalKit -import Postbox import TelegramCore import Display import MergeLists @@ -9,7 +8,7 @@ import ChatControllerInteraction import ChatHistoryEntry import ChatMessageBubbleItemNode -func preparedChatHistoryViewTransition(from fromView: ChatHistoryView?, to toView: ChatHistoryView, reason: ChatHistoryViewTransitionReason, reverse: Bool, chatLocation: ChatLocation, source: ChatHistoryListSource, controllerInteraction: ChatControllerInteraction, scrollPosition: ChatHistoryViewScrollPosition?, scrollAnimationCurve: ListViewAnimationCurve?, initialData: InitialMessageHistoryData?, keyboardButtonsMessage: Message?, cachedData: CachedPeerData?, cachedDataMessages: [MessageId: Message]?, readStateData: [PeerId: ChatHistoryCombinedInitialReadStateData]?, flashIndicators: Bool, updatedMessageSelection: Bool, messageTransitionNode: ChatMessageTransitionNodeImpl?, allUpdated: Bool) -> ChatHistoryViewTransition { +func preparedChatHistoryViewTransition(from fromView: ChatHistoryView?, to toView: ChatHistoryView, reason: ChatHistoryViewTransitionReason, reverse: Bool, chatLocation: ChatLocation, source: ChatHistoryListSource, controllerInteraction: ChatControllerInteraction, scrollPosition: ChatHistoryViewScrollPosition?, scrollAnimationCurve: ListViewAnimationCurve?, initialData: EngineInitialMessageHistoryData?, keyboardButtonsMessage: EngineRawMessage?, cachedData: EngineCachedPeerData?, cachedDataMessages: [EngineMessage.Id: EngineRawMessage]?, readStateData: [EnginePeer.Id: ChatHistoryCombinedInitialReadStateData]?, flashIndicators: Bool, updatedMessageSelection: Bool, messageTransitionNode: ChatMessageTransitionNodeImpl?, allUpdated: Bool) -> ChatHistoryViewTransition { var mergeResult: (deleteIndices: [Int], indicesAndItems: [(Int, ChatHistoryEntry, Int?)], updateIndices: [(Int, ChatHistoryEntry, Int)]) let allUpdated = allUpdated || (fromView?.associatedData != toView.associatedData) if reverse { diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index aab652e2ae..3e44de995f 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -3978,7 +3978,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { } public func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController { - return proxySettingsController(accountManager: sharedContext.accountManager, sharedContext: sharedContext, postbox: account.postbox, network: account.network, mode: .modal, presentationData: sharedContext.currentPresentationData.with { $0 }, updatedPresentationData: sharedContext.presentationData) + return proxySettingsController(accountManager: sharedContext.accountManager, sharedContext: sharedContext, network: account.network, mode: .modal, presentationData: sharedContext.currentPresentationData.with { $0 }, updatedPresentationData: sharedContext.presentationData) } public func makeDataAndStorageController(context: AccountContext, sensitiveContent: Bool) -> ViewController { diff --git a/submodules/TelegramUI/Sources/SharedMediaPlayer.swift b/submodules/TelegramUI/Sources/SharedMediaPlayer.swift index b53bcaab96..8e69e29324 100644 --- a/submodules/TelegramUI/Sources/SharedMediaPlayer.swift +++ b/submodules/TelegramUI/Sources/SharedMediaPlayer.swift @@ -238,7 +238,7 @@ final class SharedMediaPlayer { if let mediaManager = strongSelf.mediaManager, let context = strongSelf.context, let item = item as? MessageMediaPlaylistItem { switch playbackData.source { case let .telegramFile(fileReference, _, _): - let videoNode = OverlayInstantVideoNode(context: context, postbox: strongSelf.engine.account.postbox, audioSession: strongSelf.audioSession, manager: mediaManager.universalVideoManager, content: NativeVideoContent(id: .message(item.message.stableId, fileReference.media.fileId), userLocation: .peer(item.message.id.peerId), fileReference: fileReference, enableSound: false, baseRate: rateValue, isAudioVideoMessage: true, captureProtected: item.message.isCopyProtected(), storeAfterDownload: nil), close: { [weak mediaManager] in + let videoNode = OverlayInstantVideoNode(context: context, audioSession: strongSelf.audioSession, manager: mediaManager.universalVideoManager, content: NativeVideoContent(id: .message(item.message.stableId, fileReference.media.fileId), userLocation: .peer(item.message.id.peerId), fileReference: fileReference, enableSound: false, baseRate: rateValue, isAudioVideoMessage: true, captureProtected: item.message.isCopyProtected(), storeAfterDownload: nil), close: { [weak mediaManager] in mediaManager?.setPlaylist(nil, type: .voice, control: .playback(.pause)) }) strongSelf.playbackItem = .instantVideo(videoNode) diff --git a/submodules/TelegramUI/Sources/SharedNotificationManager.swift b/submodules/TelegramUI/Sources/SharedNotificationManager.swift index c2a945ef66..7ce3502e36 100644 --- a/submodules/TelegramUI/Sources/SharedNotificationManager.swift +++ b/submodules/TelegramUI/Sources/SharedNotificationManager.swift @@ -2,7 +2,6 @@ import Foundation import UIKit import UserNotifications import SwiftSignalKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -129,7 +128,7 @@ public final class SharedNotificationManager { } let previousDisposable = context.disposable context.disposable = (account.stateManager.pollStateUpdateCompletion() - |> mapToSignal { messageIds -> Signal<[MessageId], NoError> in + |> mapToSignal { messageIds -> Signal<[EngineMessage.Id], NoError> in return .single(messageIds) |> delay(1.0, queue: Queue.mainQueue()) } @@ -218,7 +217,7 @@ public final class SharedNotificationManager { let aps = payload["aps"] as? [AnyHashable: Any] - var readMessageId: MessageId? + var readMessageId: EngineMessage.Id? var isForcedLogOut = false var isCall = false var isAnnouncement = false @@ -229,7 +228,7 @@ public final class SharedNotificationManager { var body: String? var apnsSound: String? var configurationUpdate: (Int32, String, Int32, Data?)? - var messagesDeleted: [MessageId] = [] + var messagesDeleted: [EngineMessage.Id] = [] if let aps = aps, let alert = aps["alert"] as? String { if let range = alert.range(of: ": ") { title = String(alert[.. = .single(false), expand: @escaping () -> Void, close: @escaping () -> Void) { + public init(context: AccountContext, audioSession: ManagedAudioSession, manager: UniversalVideoManager, content: UniversalVideoContent, shouldBeDismissed: Signal = .single(false), expand: @escaping () -> Void, close: @escaping () -> Void) { self.content = content self.defaultExpand = expand @@ -62,7 +61,7 @@ public final class OverlayUniversalVideoNode: OverlayMediaItemNode, AVPictureInP }, controlsAreShowingUpdated: { value in controlsAreShowingUpdatedImpl?(value) }) - self.videoNode = UniversalVideoNode(context: context, postbox: postbox, audioSession: audioSession, manager: manager, decoration: decoration, content: content, priority: .overlay) + self.videoNode = UniversalVideoNode(context: context, postbox: context.account.postbox, audioSession: audioSession, manager: manager, decoration: decoration, content: content, priority: .overlay) self.decoration = decoration super.init() diff --git a/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift b/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift index 9bc2c0c03c..5df3fb288a 100644 --- a/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift +++ b/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift @@ -327,43 +327,43 @@ public final class PeerChannelMemberCategoriesContextsManager { } } - public func recent(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, requestUpdate: Bool = true, count: Int32? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { + public func recent(engine: TelegramEngine, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, requestUpdate: Bool = true, count: Int32? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { let key: PeerChannelMemberContextKey if let searchQuery = searchQuery { key = .recentSearch(searchQuery) } else { key = .recent } - return self.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: key, requestUpdate: requestUpdate, count: count, updated: updated) + return self.getContext(engine: engine, postbox: engine.account.postbox, network: engine.account.network, accountPeerId: accountPeerId, peerId: peerId, key: key, requestUpdate: requestUpdate, count: count, updated: updated) } - - public func mentions(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, threadMessageId: MessageId?, searchQuery: String? = nil, requestUpdate: Bool = true, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { + + public func mentions(engine: TelegramEngine, accountPeerId: PeerId, peerId: PeerId, threadMessageId: MessageId?, searchQuery: String? = nil, requestUpdate: Bool = true, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { let key: PeerChannelMemberContextKey = .mentions(threadId: threadMessageId, query: searchQuery) - return self.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: key, requestUpdate: requestUpdate, updated: updated) + return self.getContext(engine: engine, postbox: engine.account.postbox, network: engine.account.network, accountPeerId: accountPeerId, peerId: peerId, key: key, requestUpdate: requestUpdate, updated: updated) } - - public func admins(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { - return self.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: .admins(searchQuery), requestUpdate: true, updated: updated) + + public func admins(engine: TelegramEngine, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { + return self.getContext(engine: engine, postbox: engine.account.postbox, network: engine.account.network, accountPeerId: accountPeerId, peerId: peerId, key: .admins(searchQuery), requestUpdate: true, updated: updated) } - - public func contacts(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { - return self.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: .contacts(searchQuery), requestUpdate: true, updated: updated) + + public func contacts(engine: TelegramEngine, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { + return self.getContext(engine: engine, postbox: engine.account.postbox, network: engine.account.network, accountPeerId: accountPeerId, peerId: peerId, key: .contacts(searchQuery), requestUpdate: true, updated: updated) } - - public func bots(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { - return self.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: .bots(searchQuery), requestUpdate: true, updated: updated) + + public func bots(engine: TelegramEngine, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { + return self.getContext(engine: engine, postbox: engine.account.postbox, network: engine.account.network, accountPeerId: accountPeerId, peerId: peerId, key: .bots(searchQuery), requestUpdate: true, updated: updated) } - - public func restricted(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { - return self.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: .restricted(searchQuery), requestUpdate: true, updated: updated) + + public func restricted(engine: TelegramEngine, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { + return self.getContext(engine: engine, postbox: engine.account.postbox, network: engine.account.network, accountPeerId: accountPeerId, peerId: peerId, key: .restricted(searchQuery), requestUpdate: true, updated: updated) } - - public func banned(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { - return self.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: .banned(searchQuery), requestUpdate: true, updated: updated) + + public func banned(engine: TelegramEngine, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { + return self.getContext(engine: engine, postbox: engine.account.postbox, network: engine.account.network, accountPeerId: accountPeerId, peerId: peerId, key: .banned(searchQuery), requestUpdate: true, updated: updated) } - - public func restrictedAndBanned(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { - return self.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: .restrictedAndBanned(searchQuery), requestUpdate: true, updated: updated) + + public func restrictedAndBanned(engine: TelegramEngine, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { + return self.getContext(engine: engine, postbox: engine.account.postbox, network: engine.account.network, accountPeerId: accountPeerId, peerId: peerId, key: .restrictedAndBanned(searchQuery), requestUpdate: true, updated: updated) } public func updateMemberBannedRights(engine: TelegramEngine, peerId: PeerId, memberId: PeerId, bannedRights: TelegramChatBannedRights?) -> Signal { @@ -569,11 +569,11 @@ public final class PeerChannelMemberCategoriesContextsManager { |> runOn(Queue.mainQueue()) } - public func recentOnlineSmall(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId) -> Signal<(total: Int32, recent: Int32), NoError> { + public func recentOnlineSmall(engine: TelegramEngine, accountPeerId: PeerId, peerId: PeerId) -> Signal<(total: Int32, recent: Int32), NoError> { return Signal { [weak self] subscriber in var previousIds: Set? let statusesDisposable = MetaDisposable() - let disposableAndControl = self?.recent(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, updated: { state in + let disposableAndControl = self?.recent(engine: engine, accountPeerId: accountPeerId, peerId: peerId, updated: { state in var idList: [PeerId] = [] for item in state.list { idList.append(item.peer.id) diff --git a/submodules/WebUI/Sources/WebAppMessageChatPreviewItem.swift b/submodules/WebUI/Sources/WebAppMessageChatPreviewItem.swift index 69c0a2d14e..af6446c1ef 100644 --- a/submodules/WebUI/Sources/WebAppMessageChatPreviewItem.swift +++ b/submodules/WebUI/Sources/WebAppMessageChatPreviewItem.swift @@ -4,7 +4,6 @@ import Display import AsyncDisplayKit import SwiftSignalKit import TelegramCore -import Postbox import TelegramPresentationData import TelegramUIPreferences import ItemListUI @@ -20,9 +19,14 @@ final class PeerNameColorChatPreviewItem: ListViewItem, ItemListItem, ListItemCo if lhs.text != rhs.text { return false } - if areMediaArraysEqual(lhs.media, rhs.media) { + if lhs.media.count != rhs.media.count { return false } + for i in 0 ..< lhs.media.count { + if !lhs.media[i].isEqual(to: rhs.media[i]) { + return false + } + } if lhs.botAddress != rhs.botAddress { return false } @@ -31,7 +35,7 @@ final class PeerNameColorChatPreviewItem: ListViewItem, ItemListItem, ListItemCo let text: String let entities: TextEntitiesMessageAttribute? - let media: [Media] + let media: [EngineRawMedia] let replyMarkup: ReplyMarkupMessageAttribute? let botAddress: String } @@ -189,17 +193,17 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode { var items: [ListViewItem] = [] for messageItem in item.messageItems.reversed() { - let authorPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)) - let botPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) - - var peers = SimpleDictionary() - let messages = SimpleDictionary() + let authorPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)) + let botPeerId = EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)) + + var peers = EngineSimpleDictionary() + let messages = EngineSimpleDictionary() peers[authorPeerId] = TelegramUser(id: authorPeerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) peers[botPeerId] = TelegramUser(id: botPeerId, accessHash: nil, firstName: messageItem.botAddress, lastName: "", username: messageItem.botAddress, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) let media = messageItem.media - var attributes: [MessageAttribute] = [] + var attributes: [EngineMessage.Attribute] = [] if let entities = messageItem.entities { attributes.append(entities) } @@ -209,7 +213,7 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode { attributes.append(InlineBotMessageAttribute(peerId: botPeerId, title: nil)) - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: authorPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: attributes, media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message = EngineRawMessage(stableId: 1, stableVersion: 0, id: EngineMessage.Id(peerId: authorPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: attributes, media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false, rank: nil, rankRole: nil)) } diff --git a/submodules/WebUI/Sources/WebAppMessagePreviewScreen.swift b/submodules/WebUI/Sources/WebAppMessagePreviewScreen.swift index 5d960c53b3..49da936b4e 100644 --- a/submodules/WebUI/Sources/WebAppMessagePreviewScreen.swift +++ b/submodules/WebUI/Sources/WebAppMessagePreviewScreen.swift @@ -4,7 +4,6 @@ import AsyncDisplayKit import Display import ComponentFlow import SwiftSignalKit -import Postbox import TelegramCore import Markdown import TextFormat @@ -138,7 +137,7 @@ private final class SheetContent: CombinedComponent { var text: String = "" var entities: TextEntitiesMessageAttribute? - var media: [Media] = [] + var media: [EngineRawMedia] = [] var replyMarkup: ReplyMarkupMessageAttribute? switch component.preparedMessage.result { From c64653ed37ce9fe2bc74e260e9e960fcf3ab5dc1 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Thu, 7 May 2026 07:40:39 +0200 Subject: [PATCH 14/14] Bump version --- versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions.json b/versions.json index 4fce20f3a0..98720bd9e0 100644 --- a/versions.json +++ b/versions.json @@ -1,5 +1,5 @@ { - "app": "12.7", + "app": "12.7.1", "xcode": "26.2", "deploy_xcode": "26.2", "bazel": "8.4.2:45e9388abf21d1107e146ea366ad080eb93cb6a5f3a4a3b048f78de0bc3faffa",