From a4b4bb5a82117dc9da1991a432c7bb1618032c28 Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Tue, 16 Jul 2024 19:12:26 +0800 Subject: [PATCH] [WIP] Bot previews --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 + .../Sources/AccountContext.swift | 2 +- .../Sources/BrowserInstantPageContent.swift | 2 +- .../Sources/ChatListController.swift | 12 +- .../Sources/ChatListSearchListPaneNode.swift | 8 +- .../Sources/ChatListShimmerNode.swift | 2 +- .../Sources/Node/ChatListItem.swift | 4 +- .../InviteContactsControllerNode.swift | 2 +- .../Sources/ContactsPeerItem.swift | 6 +- .../Sources/InstantPageControllerNode.swift | 2 +- .../Sources/InviteLinkViewController.swift | 4 +- .../Sources/ItemListAvatarAndNameItem.swift | 6 +- .../Sources/MediaPickerSelectedListNode.swift | 2 +- .../Sources/DeviceContactInfoController.swift | 2 +- .../BubbleSettingsController.swift | 4 +- .../ForwardPrivacyChatPreviewItem.swift | 2 +- ...ectivePrivacySettingsPeersController.swift | 2 +- .../TextSizeSelectionController.swift | 16 +- .../Themes/ThemePreviewControllerNode.swift | 18 +- .../Themes/ThemeSettingsChatPreviewItem.swift | 4 +- submodules/TelegramApi/Sources/Api0.swift | 2 +- submodules/TelegramApi/Sources/Api26.swift | 18 +- submodules/TelegramApi/Sources/Api36.swift | 10 +- .../Account/AccountIntermediateState.swift | 2 +- .../Sources/ApiUtils/TelegramUser.swift | 12 +- .../ApiUtils/TelegramUserPresence.swift | 2 +- .../State/AccountStateManagementUtils.swift | 2 +- .../Sources/State/AccountViewTracker.swift | 2 +- .../Sources/State/UpdatesApiUtils.swift | 2 +- .../SyncCore/SyncCore_CachedUserData.swift | 121 +++- .../SyncCore/SyncCore_TelegramUser.swift | 40 +- .../TelegramEngine/Data/PeersData.swift | 28 + .../Messages/PendingStoryManager.swift | 88 ++- .../TelegramEngine/Messages/Stories.swift | 148 +++++ .../Messages/StoryListContext.swift | 144 +++++ .../Messages/TelegramEngineMessages.swift | 4 + .../Peers/UpdateCachedPeerData.swift | 20 +- .../TelegramCore/Sources/UpdatePeers.swift | 6 +- ...ChatInlineSearchResultsListComponent.swift | 4 +- .../ChatMessageAttachedContentNode.swift | 2 +- .../Sources/ChatMessageBubbleItemNode.swift | 6 +- .../Sources/ChatMessageItemImpl.swift | 4 +- .../Sources/ChatMessageReplyInfoNode.swift | 2 +- .../ChatTitleView/Sources/ChatTitleView.swift | 7 +- .../EmptyStateIndicatorComponent/BUILD | 1 + .../EmptyStateIndicatorComponent.swift | 41 +- .../Sources/PeerInfoPaneNode.swift | 1 + .../PeerInfoScreenPersonalChannelItem.swift | 2 +- .../PeerInfoScreen/Sources/PeerInfoData.swift | 51 +- .../Sources/PeerInfoPaneContainerNode.swift | 29 +- .../Sources/PeerInfoScreen.swift | 546 +++++++++++------- .../Sources/PeerInfoStoryPaneNode.swift | 211 ++++++- .../Sources/SendInviteLinkScreen.swift | 3 +- .../PeerNameColorChatPreviewItem.swift | 4 +- .../Sources/PeerSelectionLoadingView.swift | 2 +- .../Sources/ReactionChatPreviewItem.swift | 2 +- .../ThemeAccentColorControllerNode.swift | 14 +- .../Sources/WallpaperGalleryItem.swift | 4 +- .../Sources/ChatControllerNode.swift | 2 +- .../Sources/PollResultsController.swift | 2 +- .../Sources/TelegramRootController.swift | 93 +-- 61 files changed, 1321 insertions(+), 465 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 80ea7e8f73..9b119f2058 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -12533,3 +12533,5 @@ Sorry for the inconvenience."; "Monetization.Proceeds.TonAndStars.Info" = "Stars and TON from your total balance can be used for ads or withdrawn as rewards 21 and 3 days respectively after they are earned."; "Stars.Transaction.FragmentUnknown_URL" = "https://fragment.com/stars"; +"Conversation.StatusBotSubscribers_1" = "1 user"; +"Conversation.StatusBotSubscribers_any" = "%d users"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 74e7e2e42a..33d919d785 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -853,7 +853,7 @@ public protocol MediaEditorScreenResult { public protocol TelegramRootControllerInterface: NavigationController { @discardableResult - func openStoryCamera(customTarget: EnginePeer.Id?, transitionIn: StoryCameraTransitionIn?, transitionedIn: @escaping () -> Void, transitionOut: @escaping (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator? + func openStoryCamera(customTarget: Stories.PendingTarget?, transitionIn: StoryCameraTransitionIn?, transitionedIn: @escaping () -> Void, transitionOut: @escaping (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator? func proceedWithStoryUpload(target: Stories.PendingTarget, result: MediaEditorScreenResult, existingMedia: EngineMedia?, forwardInfo: Stories.PendingForwardInfo?, externalState: MediaEditorTransitionOutExternalState, commit: @escaping (@escaping () -> Void) -> Void) func getContactsController() -> ViewController? diff --git a/submodules/BrowserUI/Sources/BrowserInstantPageContent.swift b/submodules/BrowserUI/Sources/BrowserInstantPageContent.swift index 7abc50eea1..2490767e14 100644 --- a/submodules/BrowserUI/Sources/BrowserInstantPageContent.swift +++ b/submodules/BrowserUI/Sources/BrowserInstantPageContent.swift @@ -963,7 +963,7 @@ final class BrowserInstantPageContent: UIView, BrowserContent, UIScrollViewDeleg }, openUrl: { _ in }, openPeer: { _ in }, showAll: false) - let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", 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) + let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", 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) let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) let controller = LocationViewController(context: self.context, subject: EngineMessage(message), params: controllerParams) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 00f4da65af..0a3d4341b9 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -2808,15 +2808,17 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController return nil } if let componentView = self.chatListHeaderView() { - let peerId: EnginePeer.Id + let peerId: EnginePeer.Id? switch target { case .myStories: peerId = self.context.account.peerId case let .peer(id): peerId = id + case .botPreview: + peerId = nil } - if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) { + if let peerId, let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) { return StoryCameraTransitionOut( destinationView: transitionView, destinationRect: transitionView.bounds, @@ -5994,15 +5996,17 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController return nil } if let componentView = self.chatListHeaderView() { - let peerId: EnginePeer.Id + let peerId: EnginePeer.Id? switch target { case .myStories: peerId = self.context.account.peerId case let .peer(id): peerId = id + case .botPreview: + peerId = nil } - if let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) { + if let peerId, let (transitionView, _) = componentView.storyPeerListView()?.transitionViewForItem(peerId: peerId) { return StoryCameraTransitionOut( destinationView: transitionView, destinationRect: transitionView.bounds, diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index fa182a92d7..5596602d70 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -184,7 +184,11 @@ private enum ChatListRecentEntry: Comparable, Identifiable { if user.flags.contains(.isSupport) && !servicePeer { status = .custom(string: strings.Bot_GenericSupportStatus, multiline: false, isActive: false, icon: nil) } else if let _ = user.botInfo { - status = .custom(string: strings.Bot_GenericBotStatus, multiline: false, isActive: false, icon: nil) + if let subscriberCount = user.subscriberCount { + status = .custom(string: strings.Conversation_StatusBotSubscribers(subscriberCount), multiline: false, isActive: false, icon: nil) + } else { + status = .custom(string: strings.Bot_GenericBotStatus, multiline: false, isActive: false, icon: nil) + } } else if user.id != context.account.peerId && !servicePeer { let presence = peer.presence ?? TelegramUserPresence(status: .none, lastActivity: 0) status = .presence(EnginePeer.Presence(presence), timeFormat) @@ -4498,7 +4502,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode { let chatListPresentationData = ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true) - let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", 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)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", 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)) let timestamp1: Int32 = 100000 var peers: [EnginePeer.Id: EnginePeer] = [:] peers[peer1.id] = peer1 diff --git a/submodules/ChatListUI/Sources/ChatListShimmerNode.swift b/submodules/ChatListUI/Sources/ChatListShimmerNode.swift index 2009fc63d0..1bd0168a82 100644 --- a/submodules/ChatListUI/Sources/ChatListShimmerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListShimmerNode.swift @@ -150,7 +150,7 @@ public final class ChatListShimmerNode: ASDisplayNode { let chatListPresentationData = ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true) - let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", 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)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", 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)) let timestamp1: Int32 = 100000 let peers: [EnginePeer.Id: EnginePeer] = [:] let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 4fa0dd9931..232dc37a49 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -2279,14 +2279,14 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { 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) + 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) } } 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) + 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) } } diff --git a/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift b/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift index d3127070f0..29d1cba608 100644 --- a/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift +++ b/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift @@ -56,7 +56,7 @@ private enum InviteContactsEntry: Comparable, Identifiable { } else { status = .none } - let peer: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: contact.firstName, lastName: contact.lastName, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: contact.firstName, lastName: contact.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)) return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: status, enabled: true, selection: selection, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: ChatListSearchItemHeader(type: .contacts, theme: theme, strings: strings, actionTitle: nil, action: nil), action: { _ in interaction.toggleContact(id) }) diff --git a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift index 663fca5d61..b6e72f5525 100644 --- a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift +++ b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift @@ -868,7 +868,11 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { break case let .presence(presence, dateTimeFormat): if case let .peer(peer, _) = item.peer, let peer, case let .user(user) = peer, user.botInfo != nil { - statusAttributedString = NSAttributedString(string: item.presentationData.strings.Bot_GenericBotStatus, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor) + if let subscriberCount = user.subscriberCount { + statusAttributedString = NSAttributedString(string: item.presentationData.strings.Conversation_StatusBotSubscribers(subscriberCount), font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor) + } else { + statusAttributedString = NSAttributedString(string: item.presentationData.strings.Bot_GenericBotStatus, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor) + } } else { userPresence = presence let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index c79d463bd5..e2e9a15e1e 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -1428,7 +1428,7 @@ final class InstantPageControllerNode: ASDisplayNode, ASScrollViewDelegate { }, openUrl: { _ in }, openPeer: { _ in }, showAll: false) - let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", 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) + let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", 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) let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) let controller = LocationViewController(context: self.context, subject: EngineMessage(message), params: controllerParams) diff --git a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift index f69aaf3115..d69e30ea2b 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift @@ -740,7 +740,7 @@ public final class InviteLinkViewController: ViewController { if requestsState.importers.isEmpty && requestsState.isLoadingMore { count = min(4, state.count) loading = true - let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), 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) + let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), 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) for i in 0 ..< count { entries.append(.request(Int32(i), presentationData.theme, presentationData.dateTimeFormat, EnginePeer.user(fakeUser), 0, true)) } @@ -774,7 +774,7 @@ public final class InviteLinkViewController: ViewController { if state.importers.isEmpty && state.isLoadingMore { count = min(4, state.count) loading = true - let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), 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) + let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), 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) for i in 0 ..< count { entries.append(.importer(Int32(i), presentationData.theme, presentationData.dateTimeFormat, EnginePeer.user(fakeUser), 0, false, true)) } diff --git a/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift b/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift index 7c467645b2..34a6d5ff2c 100644 --- a/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift +++ b/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift @@ -449,7 +449,11 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo statusText = "" statusColor = item.presentationData.theme.list.itemPrimaryTextColor } else if let _ = peer.botInfo { - statusText = item.presentationData.strings.Bot_GenericBotStatus + if let subscriberCount = peer.subscriberCount { + statusText = item.presentationData.strings.Conversation_StatusBotSubscribers(subscriberCount) + } else { + statusText = item.presentationData.strings.Bot_GenericBotStatus + } statusColor = item.presentationData.theme.list.itemSecondaryTextColor } else if case .generic = item.mode, !servicePeer, let presence = item.presence { let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 diff --git a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift index 78caaba0fe..8b5b6960ac 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift @@ -1046,7 +1046,7 @@ final class MediaPickerSelectedListNode: ASDisplayNode, ASScrollViewDelegate, AS if !self.isExternalPreview { let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) var peers = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, 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) + peers[peerId] = TelegramUser(id: peerId, 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) let previewText = groupLayouts.count > 1 ? presentationData.strings.Attachment_MessagesPreview : presentationData.strings.Attachment_MessagePreview diff --git a/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift b/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift index be85ed72cc..8cee4bf6a0 100644 --- a/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift +++ b/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift @@ -671,7 +671,7 @@ private func deviceContactInfoEntries(context: ShareControllerAccountContext, pr firstName = presentationData.strings.Message_Contact } - entries.append(.info(entries.count, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: peer ?? EnginePeer.user(TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: firstName, lastName: isOrganization ? nil : personName.1, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)), state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), job: isOrganization ? nil : jobSummary, isPlain: !isShare, hiddenAvatar: hiddenAvatar)) + entries.append(.info(entries.count, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: peer ?? EnginePeer.user(TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: firstName, lastName: isOrganization ? nil : personName.1, 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)), state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), job: isOrganization ? nil : jobSummary, isPlain: !isShare, hiddenAvatar: hiddenAvatar)) if !selecting { if let _ = peer { diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index 5a19bd9b4a..312ebb57a8 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -163,8 +163,8 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, ASScrollViewDel let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: 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: [:]) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift index a118eb7283..52c56e8455 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift @@ -145,7 +145,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { var peers = SimpleDictionary() let messages = SimpleDictionary() - 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: 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: []) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift index 81ecb8434b..d1202a9c8e 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift @@ -175,7 +175,7 @@ private enum SelectivePrivacyPeersEntry: ItemListNodeEntry { switch self { case let .premiumUsersItem(editing, enabled): let peer: EnginePeer = .user(TelegramUser( - id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)), accessHash: nil, firstName: presentationData.strings.PrivacySettings_CategoryPremiumUsers, 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)) + id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)), accessHash: nil, firstName: presentationData.strings.PrivacySettings_CategoryPremiumUsers, 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)) return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(), nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, customAvatarIcon: premiumAvatarIcon, presence: nil, text: .none, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: { }, setPeerIdWithRevealedOptions: { previousId, id in arguments.setPeerIdWithRevealedOptions(previousId, id) diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift index 2ce353ed87..94e9ed572d 100644 --- a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift @@ -312,14 +312,14 @@ 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)) - 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)) - 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)) + 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)) + 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)) + 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)) 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)) - 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)) - 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)) + 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)) + 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)) 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)) - 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)) + 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)) let timestamp = self.referenceTimestamp @@ -435,8 +435,8 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, ASScrollView let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: 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: [:]) diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift index 4dfabf4ada..336cf3e8b6 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift @@ -461,15 +461,15 @@ 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)) - 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)) - 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)) + 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)) + 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)) + 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)) 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)) - 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)) - 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)) + 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)) + 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)) 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)) - 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)) - 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)) + 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)) + 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)) let timestamp = self.referenceTimestamp @@ -590,8 +590,8 @@ final class ThemePreviewControllerNode: ASDisplayNode, ASScrollViewDelegate { let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil) var sampleMessages: [Message] = [] diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index b431aff3f3..27d2fb7cab 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -163,11 +163,11 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { let replyMessageId = MessageId(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) + 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) 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: [:]) } - 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) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: [], peers: peers, associatedMessages: messages, 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) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], 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)) } diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 2b3e37e1d4..a534054d76 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -1080,7 +1080,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1886646706] = { return Api.UrlAuthResult.parse_urlAuthResultAccepted($0) } dict[-1445536993] = { return Api.UrlAuthResult.parse_urlAuthResultDefault($0) } dict[-1831650802] = { return Api.UrlAuthResult.parse_urlAuthResultRequest($0) } - dict[559694904] = { return Api.User.parse_user($0) } + dict[1340722400] = { return Api.User.parse_user($0) } dict[-742634630] = { return Api.User.parse_userEmpty($0) } dict[-862357728] = { return Api.UserFull.parse_userFull($0) } dict[-2100168954] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) } diff --git a/submodules/TelegramApi/Sources/Api26.swift b/submodules/TelegramApi/Sources/Api26.swift index e09e22c164..4d3405e880 100644 --- a/submodules/TelegramApi/Sources/Api26.swift +++ b/submodules/TelegramApi/Sources/Api26.swift @@ -452,14 +452,14 @@ public extension Api { } public extension Api { enum User: TypeConstructorDescription { - case user(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: Api.UserProfilePhoto?, status: Api.UserStatus?, botInfoVersion: Int32?, restrictionReason: [Api.RestrictionReason]?, botInlinePlaceholder: String?, langCode: String?, emojiStatus: Api.EmojiStatus?, usernames: [Api.Username]?, storiesMaxId: Int32?, color: Api.PeerColor?, profileColor: Api.PeerColor?) + case user(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: Api.UserProfilePhoto?, status: Api.UserStatus?, botInfoVersion: Int32?, restrictionReason: [Api.RestrictionReason]?, botInlinePlaceholder: String?, langCode: String?, emojiStatus: Api.EmojiStatus?, usernames: [Api.Username]?, storiesMaxId: Int32?, color: Api.PeerColor?, profileColor: Api.PeerColor?, botDailyUsers: Int32?) case userEmpty(id: Int64) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .user(let flags, let flags2, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode, let emojiStatus, let usernames, let storiesMaxId, let color, let profileColor): + case .user(let flags, let flags2, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode, let emojiStatus, let usernames, let storiesMaxId, let color, let profileColor, let botDailyUsers): if boxed { - buffer.appendInt32(559694904) + buffer.appendInt32(1340722400) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags2, buffer: buffer, boxed: false) @@ -488,6 +488,7 @@ public extension Api { if Int(flags2) & Int(1 << 5) != 0 {serializeInt32(storiesMaxId!, buffer: buffer, boxed: false)} if Int(flags2) & Int(1 << 8) != 0 {color!.serialize(buffer, true)} if Int(flags2) & Int(1 << 9) != 0 {profileColor!.serialize(buffer, true)} + if Int(flags2) & Int(1 << 12) != 0 {serializeInt32(botDailyUsers!, buffer: buffer, boxed: false)} break case .userEmpty(let id): if boxed { @@ -500,8 +501,8 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .user(let flags, let flags2, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode, let emojiStatus, let usernames, let storiesMaxId, let color, let profileColor): - return ("user", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("username", username as Any), ("phone", phone as Any), ("photo", photo as Any), ("status", status as Any), ("botInfoVersion", botInfoVersion as Any), ("restrictionReason", restrictionReason as Any), ("botInlinePlaceholder", botInlinePlaceholder as Any), ("langCode", langCode as Any), ("emojiStatus", emojiStatus as Any), ("usernames", usernames as Any), ("storiesMaxId", storiesMaxId as Any), ("color", color as Any), ("profileColor", profileColor as Any)]) + case .user(let flags, let flags2, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode, let emojiStatus, let usernames, let storiesMaxId, let color, let profileColor, let botDailyUsers): + return ("user", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("username", username as Any), ("phone", phone as Any), ("photo", photo as Any), ("status", status as Any), ("botInfoVersion", botInfoVersion as Any), ("restrictionReason", restrictionReason as Any), ("botInlinePlaceholder", botInlinePlaceholder as Any), ("langCode", langCode as Any), ("emojiStatus", emojiStatus as Any), ("usernames", usernames as Any), ("storiesMaxId", storiesMaxId as Any), ("color", color as Any), ("profileColor", profileColor as Any), ("botDailyUsers", botDailyUsers as Any)]) case .userEmpty(let id): return ("userEmpty", [("id", id as Any)]) } @@ -560,6 +561,8 @@ public extension Api { if Int(_2!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() { _19 = Api.parse(reader, signature: signature) as? Api.PeerColor } } + var _20: Int32? + if Int(_2!) & Int(1 << 12) != 0 {_20 = reader.readInt32() } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil @@ -579,8 +582,9 @@ public extension Api { let _c17 = (Int(_2!) & Int(1 << 5) == 0) || _17 != nil let _c18 = (Int(_2!) & Int(1 << 8) == 0) || _18 != nil let _c19 = (Int(_2!) & Int(1 << 9) == 0) || _19 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 { - return Api.User.user(flags: _1!, flags2: _2!, id: _3!, accessHash: _4, firstName: _5, lastName: _6, username: _7, phone: _8, photo: _9, status: _10, botInfoVersion: _11, restrictionReason: _12, botInlinePlaceholder: _13, langCode: _14, emojiStatus: _15, usernames: _16, storiesMaxId: _17, color: _18, profileColor: _19) + let _c20 = (Int(_2!) & Int(1 << 12) == 0) || _20 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 { + return Api.User.user(flags: _1!, flags2: _2!, id: _3!, accessHash: _4, firstName: _5, lastName: _6, username: _7, phone: _8, photo: _9, status: _10, botInfoVersion: _11, restrictionReason: _12, botInlinePlaceholder: _13, langCode: _14, emojiStatus: _15, usernames: _16, storiesMaxId: _17, color: _18, profileColor: _19, botDailyUsers: _20) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api36.swift b/submodules/TelegramApi/Sources/Api36.swift index 614ecb3df2..3670a82adc 100644 --- a/submodules/TelegramApi/Sources/Api36.swift +++ b/submodules/TelegramApi/Sources/Api36.swift @@ -2263,11 +2263,15 @@ public extension Api.functions.bots { } } public extension Api.functions.bots { - static func deletePreviewMedia(bot: Api.InputUser, media: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func deletePreviewMedia(bot: Api.InputUser, media: [Api.InputMedia]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(1220635873) + buffer.appendInt32(481471475) bot.serialize(buffer, true) - media.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(media.count)) + for item in media { + item.serialize(buffer, true) + } return (FunctionDescription(name: "bots.deletePreviewMedia", parameters: [("bot", String(describing: bot)), ("media", String(describing: media))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in let reader = BufferReader(buffer) var result: Api.Bool? diff --git a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift index 7163cb1994..ce0867744c 100644 --- a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift +++ b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift @@ -542,7 +542,7 @@ struct AccountMutableState { var presences: [PeerId: Api.UserStatus] = [:] for user in users { switch user { - case let .user(_, _, id, _, _, _, _, _, _, status, _, _, _, _, _, _, _, _, _): + case let .user(_, _, id, _, _, _, _, _, _, status, _, _, _, _, _, _, _, _, _, _): if let status = status { presences[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))] = status } diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift index e9c38bdd93..b93cc8e6aa 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift @@ -36,7 +36,7 @@ extension TelegramPeerUsername { extension TelegramUser { convenience init(user: Api.User) { switch user { - case let .user(flags, flags2, id, accessHash, firstName, lastName, username, phone, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, usernames, _, color, profileColor): + case let .user(flags, flags2, id, accessHash, firstName, lastName, username, phone, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, usernames, _, color, profileColor, subscriberCount): let representations: [TelegramMediaImageRepresentation] = photo.flatMap(parsedTelegramProfilePhoto) ?? [] let isMin = (flags & (1 << 20)) != 0 @@ -124,15 +124,15 @@ extension TelegramUser { } } - self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, firstName: firstName, lastName: lastName, username: username, phone: phone, photo: representations, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? [], storiesHidden: storiesHidden, nameColor: nameColorIndex.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId, profileColor: profileColorIndex.flatMap { PeerNameColor(rawValue: $0) }, profileBackgroundEmojiId: profileBackgroundEmojiId) + self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, firstName: firstName, lastName: lastName, username: username, phone: phone, photo: representations, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? [], storiesHidden: storiesHidden, nameColor: nameColorIndex.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId, profileColor: profileColorIndex.flatMap { PeerNameColor(rawValue: $0) }, profileBackgroundEmojiId: profileBackgroundEmojiId, subscriberCount: subscriberCount) case let .userEmpty(id): - self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), 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) + self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), 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) } } static func merge(_ lhs: TelegramUser?, rhs: Api.User) -> TelegramUser? { switch rhs { - case let .user(flags, _, _, rhsAccessHash, _, _, _, _, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, _, _, nameColor, profileColor): + case let .user(flags, _, _, rhsAccessHash, _, _, _, _, photo, _, _, restrictionReason, botInlinePlaceholder, _, emojiStatus, _, _, nameColor, profileColor, subscriberCount): let isMin = (flags & (1 << 20)) != 0 if !isMin { return TelegramUser(user: rhs) @@ -233,7 +233,7 @@ extension TelegramUser { } } - return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: lhs.username, phone: lhs.phone, photo: telegramPhoto, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: lhs.usernames, storiesHidden: lhs.storiesHidden, nameColor: nameColorIndex.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId, profileColor: profileColorIndex.flatMap { PeerNameColor(rawValue: $0) }, profileBackgroundEmojiId: profileBackgroundEmojiId) + return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: lhs.username, phone: lhs.phone, photo: telegramPhoto, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: lhs.usernames, storiesHidden: lhs.storiesHidden, nameColor: nameColorIndex.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId, profileColor: profileColorIndex.flatMap { PeerNameColor(rawValue: $0) }, profileBackgroundEmojiId: profileBackgroundEmojiId, subscriberCount: subscriberCount) } else { return TelegramUser(user: rhs) } @@ -294,7 +294,7 @@ extension TelegramUser { storiesHidden = lhs.storiesHidden } - return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: lhs.username, phone: lhs.phone, photo: photo, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus, usernames: lhs.usernames, storiesHidden: storiesHidden, nameColor: rhs.nameColor, backgroundEmojiId: rhs.backgroundEmojiId, profileColor: rhs.profileColor, profileBackgroundEmojiId: rhs.profileBackgroundEmojiId) + return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: lhs.username, phone: lhs.phone, photo: photo, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus, usernames: lhs.usernames, storiesHidden: storiesHidden, nameColor: rhs.nameColor, backgroundEmojiId: rhs.backgroundEmojiId, profileColor: rhs.profileColor, profileBackgroundEmojiId: rhs.profileBackgroundEmojiId, subscriberCount: rhs.subscriberCount) } } } diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramUserPresence.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramUserPresence.swift index df313c16c1..ff0a3f1900 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramUserPresence.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramUserPresence.swift @@ -26,7 +26,7 @@ extension TelegramUserPresence { convenience init?(apiUser: Api.User) { switch apiUser { - case let .user(_, _, _, _, _, _, _, _, _, status, _, _, _, _, _, _, _, _, _): + case let .user(_, _, _, _, _, _, _, _, _, status, _, _, _, _, _, _, _, _, _, _): if let status = status { self.init(apiStatus: status) } else { diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 5e00964182..7e67b1668b 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -1121,7 +1121,7 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox: if updatedState.peers[peerId] == nil { updatedState.updatePeer(peerId, { peer in if peer == nil { - return TelegramUser(id: peerId, accessHash: nil, firstName: "Telegram Notifications", lastName: nil, username: nil, phone: nil, photo: [], botInfo: BotUserInfo(flags: [], inlinePlaceholder: nil), restrictionInfo: nil, flags: [.isVerified], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + return TelegramUser(id: peerId, accessHash: nil, firstName: "Telegram Notifications", lastName: nil, username: nil, phone: nil, photo: [], botInfo: BotUserInfo(flags: [], inlinePlaceholder: nil), restrictionInfo: nil, flags: [.isVerified], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil) } else { return peer } diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index 432ed9bf48..15d15fb579 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -1472,7 +1472,7 @@ public final class AccountViewTracker { if i < slice.count { let value = result[i] transaction.updatePeerCachedData(peerIds: Set([slice[i].0]), update: { _, cachedData in - var cachedData = cachedData as? CachedUserData ?? CachedUserData(about: nil, botInfo: nil, editableBotInfo: nil, peerStatusSettings: nil, pinnedMessageId: nil, isBlocked: false, commonGroupCount: 0, voiceCallsAvailable: true, videoCallsAvailable: true, callsPrivate: true, canPinMessages: true, hasScheduledMessages: true, autoremoveTimeout: .unknown, themeEmoticon: nil, photo: .unknown, personalPhoto: .unknown, fallbackPhoto: .unknown, premiumGiftOptions: [], voiceMessagesAvailable: true, wallpaper: nil, flags: [], businessHours: nil, businessLocation: nil, greetingMessage: nil, awayMessage: nil, connectedBot: nil, businessIntro: .unknown, birthday: nil, personalChannel: .unknown) + var cachedData = cachedData as? CachedUserData ?? CachedUserData(about: nil, botInfo: nil, editableBotInfo: nil, peerStatusSettings: nil, pinnedMessageId: nil, isBlocked: false, commonGroupCount: 0, voiceCallsAvailable: true, videoCallsAvailable: true, callsPrivate: true, canPinMessages: true, hasScheduledMessages: true, autoremoveTimeout: .unknown, themeEmoticon: nil, photo: .unknown, personalPhoto: .unknown, fallbackPhoto: .unknown, premiumGiftOptions: [], voiceMessagesAvailable: true, wallpaper: nil, flags: [], businessHours: nil, businessLocation: nil, greetingMessage: nil, awayMessage: nil, connectedBot: nil, businessIntro: .unknown, birthday: nil, personalChannel: .unknown, botPreview: nil) var flags = cachedData.flags if case .boolTrue = value { flags.insert(.premiumRequired) diff --git a/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift b/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift index f938a9ea43..0ec47fcdf3 100644 --- a/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift +++ b/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift @@ -193,7 +193,7 @@ extension Api.Chat { extension Api.User { var peerId: PeerId { switch self { - case let .user(_, _, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .user(_, _, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): return PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)) case let .userEmpty(id): return PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift index ea394efd5d..62c160c7c8 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift @@ -625,6 +625,48 @@ extension TelegramBusinessChatLinks { } public final class CachedUserData: CachedPeerData { + public final class BotPreview: Codable, Equatable { + private enum CodingKeys: String, CodingKey { + case media + } + + public let media: [Media] + + public init(media: [Media]) { + self.media = media + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let mediaData = try container.decode([Data].self, forKey: .media) + self.media = mediaData.compactMap { data -> Media? in + return PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? Media + } + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + let mediaData = self.media.map { media -> Data in + let encoder = PostboxEncoder() + encoder.encodeRootObject(media) + return encoder.makeData() + } + try container.encode(mediaData, forKey: .media) + } + + public static func ==(lhs: BotPreview, rhs: BotPreview) -> Bool { + if lhs === rhs { + return true + } + if !areMediaArraysEqual(lhs.media, rhs.media) { + return false + } + return true + } + } + public let about: String? public let botInfo: BotInfo? public let editableBotInfo: EditableBotInfo? @@ -654,6 +696,7 @@ public final class CachedUserData: CachedPeerData { public let businessIntro: CachedTelegramBusinessIntro public let birthday: TelegramBirthday? public let personalChannel: CachedTelegramPersonalChannel + public let botPreview: BotPreview? public let peerIds: Set public let messageIds: Set @@ -691,9 +734,10 @@ public final class CachedUserData: CachedPeerData { self.businessIntro = .unknown self.birthday = nil self.personalChannel = .unknown + self.botPreview = nil } - public init(about: String?, botInfo: BotInfo?, editableBotInfo: EditableBotInfo?, peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, isBlocked: Bool, commonGroupCount: Int32, voiceCallsAvailable: Bool, videoCallsAvailable: Bool, callsPrivate: Bool, canPinMessages: Bool, hasScheduledMessages: Bool, autoremoveTimeout: CachedPeerAutoremoveTimeout, themeEmoticon: String?, photo: CachedPeerProfilePhoto, personalPhoto: CachedPeerProfilePhoto, fallbackPhoto: CachedPeerProfilePhoto, premiumGiftOptions: [CachedPremiumGiftOption], voiceMessagesAvailable: Bool, wallpaper: TelegramWallpaper?, flags: CachedUserFlags, businessHours: TelegramBusinessHours?, businessLocation: TelegramBusinessLocation?, greetingMessage: TelegramBusinessGreetingMessage?, awayMessage: TelegramBusinessAwayMessage?, connectedBot: TelegramAccountConnectedBot?, businessIntro: CachedTelegramBusinessIntro, birthday: TelegramBirthday?, personalChannel: CachedTelegramPersonalChannel) { + public init(about: String?, botInfo: BotInfo?, editableBotInfo: EditableBotInfo?, peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, isBlocked: Bool, commonGroupCount: Int32, voiceCallsAvailable: Bool, videoCallsAvailable: Bool, callsPrivate: Bool, canPinMessages: Bool, hasScheduledMessages: Bool, autoremoveTimeout: CachedPeerAutoremoveTimeout, themeEmoticon: String?, photo: CachedPeerProfilePhoto, personalPhoto: CachedPeerProfilePhoto, fallbackPhoto: CachedPeerProfilePhoto, premiumGiftOptions: [CachedPremiumGiftOption], voiceMessagesAvailable: Bool, wallpaper: TelegramWallpaper?, flags: CachedUserFlags, businessHours: TelegramBusinessHours?, businessLocation: TelegramBusinessLocation?, greetingMessage: TelegramBusinessGreetingMessage?, awayMessage: TelegramBusinessAwayMessage?, connectedBot: TelegramAccountConnectedBot?, businessIntro: CachedTelegramBusinessIntro, birthday: TelegramBirthday?, personalChannel: CachedTelegramPersonalChannel, botPreview: BotPreview?) { self.about = about self.botInfo = botInfo self.editableBotInfo = editableBotInfo @@ -723,6 +767,7 @@ public final class CachedUserData: CachedPeerData { self.businessIntro = businessIntro self.birthday = birthday self.personalChannel = personalChannel + self.botPreview = botPreview self.peerIds = Set() @@ -786,6 +831,8 @@ public final class CachedUserData: CachedPeerData { self.birthday = decoder.decodeCodable(TelegramBirthday.self, forKey: "bday") self.personalChannel = decoder.decodeCodable(CachedTelegramPersonalChannel.self, forKey: "pchan") ?? .unknown + + self.botPreview = decoder.decodeCodable(BotPreview.self, forKey: "botPreview") } public func encode(_ encoder: PostboxEncoder) { @@ -885,7 +932,12 @@ public final class CachedUserData: CachedPeerData { encoder.encodeNil(forKey: "bday") } - encoder.encodeCodable(personalChannel, forKey: "pchan") + encoder.encodeCodable(self.personalChannel, forKey: "pchan") + if let botPreview = self.botPreview { + encoder.encodeCodable(botPreview, forKey: "botPreview") + } else { + encoder.encodeNil(forKey: "botPreview") + } } public func isEqual(to: CachedPeerData) -> Bool { @@ -923,124 +975,131 @@ public final class CachedUserData: CachedPeerData { if other.personalChannel != self.personalChannel { return false } + if other.botPreview != self.botPreview { + return false + } return other.about == self.about && other.botInfo == self.botInfo && other.editableBotInfo == self.editableBotInfo && self.peerStatusSettings == other.peerStatusSettings && self.isBlocked == other.isBlocked && self.commonGroupCount == other.commonGroupCount && self.voiceCallsAvailable == other.voiceCallsAvailable && self.videoCallsAvailable == other.videoCallsAvailable && self.callsPrivate == other.callsPrivate && self.hasScheduledMessages == other.hasScheduledMessages && self.autoremoveTimeout == other.autoremoveTimeout && self.themeEmoticon == other.themeEmoticon && self.photo == other.photo && self.personalPhoto == other.personalPhoto && self.fallbackPhoto == other.fallbackPhoto && self.premiumGiftOptions == other.premiumGiftOptions && self.voiceMessagesAvailable == other.voiceMessagesAvailable && self.flags == other.flags && self.wallpaper == other.wallpaper } public func withUpdatedAbout(_ about: String?) -> CachedUserData { - return CachedUserData(about: about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedBotInfo(_ botInfo: BotInfo?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedEditableBotInfo(_ editableBotInfo: EditableBotInfo?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedIsBlocked(_ isBlocked: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedCommonGroupCount(_ commonGroupCount: Int32) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedVoiceCallsAvailable(_ voiceCallsAvailable: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedVideoCallsAvailable(_ videoCallsAvailable: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedCallsPrivate(_ callsPrivate: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedCanPinMessages(_ canPinMessages: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedThemeEmoticon(_ themeEmoticon: String?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedPhoto(_ photo: CachedPeerProfilePhoto) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedPersonalPhoto(_ personalPhoto: CachedPeerProfilePhoto) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedFallbackPhoto(_ fallbackPhoto: CachedPeerProfilePhoto) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedPremiumGiftOptions(_ premiumGiftOptions: [CachedPremiumGiftOption]) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedVoiceMessagesAvailable(_ voiceMessagesAvailable: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedWallpaper(_ wallpaper: TelegramWallpaper?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedFlags(_ flags: CachedUserFlags) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedBusinessHours(_ businessHours: TelegramBusinessHours?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedBusinessLocation(_ businessLocation: TelegramBusinessLocation?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedGreetingMessage(_ greetingMessage: TelegramBusinessGreetingMessage?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedAwayMessage(_ awayMessage: TelegramBusinessAwayMessage?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedConnectedBot(_ connectedBot: TelegramAccountConnectedBot?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedBusinessIntro(_ businessIntro: TelegramBusinessIntro?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: .known(businessIntro), birthday: self.birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: .known(businessIntro), birthday: self.birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedBirthday(_ birthday: TelegramBirthday?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: birthday, personalChannel: self.personalChannel) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: birthday, personalChannel: self.personalChannel, botPreview: self.botPreview) } public func withUpdatedPersonalChannel(_ personalChannel: TelegramPersonalChannel?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: .known(personalChannel)) + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: .known(personalChannel), botPreview: self.botPreview) + } + + public func withUpdatedBotPreview(_ botPreview: BotPreview?) -> CachedUserData { + return CachedUserData(about: self.about, botInfo: self.botInfo, editableBotInfo: self.editableBotInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags, businessHours: self.businessHours, businessLocation: self.businessLocation, greetingMessage: self.greetingMessage, awayMessage: self.awayMessage, connectedBot: self.connectedBot, businessIntro: self.businessIntro, birthday: self.birthday, personalChannel: self.personalChannel, botPreview: botPreview) } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift index d1586a041f..afa7b85300 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift @@ -117,6 +117,7 @@ public final class TelegramUser: Peer, Equatable { public let backgroundEmojiId: Int64? public let profileColor: PeerNameColor? public let profileBackgroundEmojiId: Int64? + public let subscriberCount: Int32? public var nameOrPhone: String { if let firstName = self.firstName { @@ -205,7 +206,8 @@ public final class TelegramUser: Peer, Equatable { nameColor: PeerNameColor?, backgroundEmojiId: Int64?, profileColor: PeerNameColor?, - profileBackgroundEmojiId: Int64? + profileBackgroundEmojiId: Int64?, + subscriberCount: Int32? ) { self.id = id self.accessHash = accessHash @@ -224,6 +226,7 @@ public final class TelegramUser: Peer, Equatable { self.backgroundEmojiId = backgroundEmojiId self.profileColor = profileColor self.profileBackgroundEmojiId = profileBackgroundEmojiId + self.subscriberCount = subscriberCount } public init(decoder: PostboxDecoder) { @@ -268,6 +271,8 @@ public final class TelegramUser: Peer, Equatable { self.backgroundEmojiId = decoder.decodeOptionalInt64ForKey("bgem") self.profileColor = decoder.decodeOptionalInt32ForKey("pclr").flatMap { PeerNameColor(rawValue: $0) } self.profileBackgroundEmojiId = decoder.decodeOptionalInt64ForKey("pgem") + + self.subscriberCount = decoder.decodeOptionalInt32ForKey("ssc") } public func encode(_ encoder: PostboxEncoder) { @@ -351,6 +356,12 @@ public final class TelegramUser: Peer, Equatable { } else { encoder.encodeNil(forKey: "pgem") } + + if let subscriberCount = self.subscriberCount { + encoder.encodeInt32(subscriberCount, forKey: "ssc") + } else { + encoder.encodeNil(forKey: "ssc") + } } public func isEqual(_ other: Peer) -> Bool { @@ -418,55 +429,58 @@ public final class TelegramUser: Peer, Equatable { if lhs.profileBackgroundEmojiId != rhs.profileBackgroundEmojiId { return false } + if lhs.subscriberCount != rhs.subscriberCount { + return false + } return true } public func withUpdatedUsername(_ username: String?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedUsernames(_ usernames: [TelegramPeerUsername]) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedNames(firstName: String?, lastName: String?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: firstName, lastName: lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: firstName, lastName: lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedPhone(_ phone: String?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedPhoto(_ representations: [TelegramMediaImageRepresentation]) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: representations, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: representations, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedEmojiStatus(_ emojiStatus: PeerEmojiStatus?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedFlags(_ flags: UserInfoFlags) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedStoriesHidden(_ storiesHidden: Bool?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedNameColor(_ nameColor: PeerNameColor) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedBackgroundEmojiId(_ backgroundEmojiId: Int64?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedProfileColor(_ profileColor: PeerNameColor?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } public func withUpdatedProfileBackgroundEmojiId(_ profileBackgroundEmojiId: Int64?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId, subscriberCount: self.subscriberCount) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift index 224c4b5cb2..0f832241c8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift @@ -2047,5 +2047,33 @@ public extension TelegramEngine.EngineData.Item { } } } + + public struct BotPreview: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { + public typealias Result = CachedUserData.BotPreview? + + 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() + } + if let cachedData = view.cachedPeerData as? CachedUserData { + return cachedData.botPreview + } else { + return nil + } + } + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/PendingStoryManager.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/PendingStoryManager.swift index 6c094379ee..2100467d23 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/PendingStoryManager.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/PendingStoryManager.swift @@ -12,6 +12,7 @@ public extension Stories { case myStories case peer(PeerId) + case botPreview(PeerId) public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) @@ -21,6 +22,8 @@ public extension Stories { self = .myStories case 1: self = .peer(try container.decode(PeerId.self, forKey: .peerId)) + case 2: + self = .botPreview(try container.decode(PeerId.self, forKey: .peerId)) default: self = .myStories } @@ -35,6 +38,9 @@ public extension Stories { case let .peer(peerId): try container.encode(1 as Int32, forKey: .discriminator) try container.encode(peerId, forKey: .peerId) + case let .botPreview(peerId): + try container.encode(2 as Int32, forKey: .discriminator) + try container.encode(peerId, forKey: .peerId) } } } @@ -369,12 +375,14 @@ final class PendingStoryManager { print(currentPendingItemContext) }) } - self.queuedPendingItems = Set(localState.items.map { item -> PeerId in + self.queuedPendingItems = Set(localState.items.compactMap { item -> PeerId? in switch item.target { case .myStories: return self.accountPeerId case let .peer(id): return id + case .botPreview: + return nil } }) @@ -397,33 +405,75 @@ final class PendingStoryManager { self.currentPendingItemContext = pendingItemContext let toPeerId: PeerId + var isBotPreview = false switch firstItem.target { case .myStories: toPeerId = self.accountPeerId case let .peer(peerId): toPeerId = peerId + case let .botPreview(peerId): + toPeerId = peerId + isBotPreview = true } let stableId = firstItem.stableId - pendingItemContext.disposable = (_internal_uploadStoryImpl(postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, stateManager: self.stateManager, messageMediaPreuploadManager: self.messageMediaPreuploadManager, revalidationContext: self.revalidationContext, auxiliaryMethods: self.auxiliaryMethods, toPeerId: toPeerId, stableId: stableId, media: firstItem.media, mediaAreas: firstItem.mediaAreas, text: firstItem.text, entities: firstItem.entities, embeddedStickers: firstItem.embeddedStickers, pin: firstItem.pin, privacy: firstItem.privacy, isForwardingDisabled: firstItem.isForwardingDisabled, period: Int(firstItem.period), randomId: firstItem.randomId, forwardInfo: firstItem.forwardInfo) - |> deliverOn(self.queue)).start(next: { [weak self] event in - guard let `self` = self else { - return - } - switch event { - case let .progress(progress): - if let currentPendingItemContext = self.currentPendingItemContext, currentPendingItemContext.item.stableId == stableId { - currentPendingItemContext.progress = progress - currentPendingItemContext.updated() + if isBotPreview { + pendingItemContext.disposable = (_internal_uploadBotPreviewImpl( + postbox: self.postbox, + network: self.network, + accountPeerId: self.accountPeerId, + stateManager: self.stateManager, + messageMediaPreuploadManager: self.messageMediaPreuploadManager, + revalidationContext: self.revalidationContext, + auxiliaryMethods: self.auxiliaryMethods, + toPeerId: toPeerId, + stableId: stableId, + media: firstItem.media, + mediaAreas: firstItem.mediaAreas, + text: firstItem.text, + entities: firstItem.entities, + embeddedStickers: firstItem.embeddedStickers, + randomId: firstItem.randomId + ) + |> deliverOn(self.queue)).start(next: { [weak self] event in + guard let self else { + return } - case let .completed(id): - if let id = id { - self.allStoriesEventsPipe.putNext((stableId, id)) + switch event { + case let .progress(progress): + if let currentPendingItemContext = self.currentPendingItemContext, currentPendingItemContext.item.stableId == stableId { + currentPendingItemContext.progress = progress + currentPendingItemContext.updated() + } + case let .completed(id): + if let id = id { + self.allStoriesEventsPipe.putNext((stableId, id)) + } + // wait for the local state to change via Postbox + break } - // wait for the local state to change via Postbox - break - } - }) + }) + } else { + pendingItemContext.disposable = (_internal_uploadStoryImpl(postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, stateManager: self.stateManager, messageMediaPreuploadManager: self.messageMediaPreuploadManager, revalidationContext: self.revalidationContext, auxiliaryMethods: self.auxiliaryMethods, toPeerId: toPeerId, stableId: stableId, media: firstItem.media, mediaAreas: firstItem.mediaAreas, text: firstItem.text, entities: firstItem.entities, embeddedStickers: firstItem.embeddedStickers, pin: firstItem.pin, privacy: firstItem.privacy, isForwardingDisabled: firstItem.isForwardingDisabled, period: Int(firstItem.period), randomId: firstItem.randomId, forwardInfo: firstItem.forwardInfo) + |> deliverOn(self.queue)).start(next: { [weak self] event in + guard let `self` = self else { + return + } + switch event { + case let .progress(progress): + if let currentPendingItemContext = self.currentPendingItemContext, currentPendingItemContext.item.stableId == stableId { + currentPendingItemContext.progress = progress + currentPendingItemContext.updated() + } + case let .completed(id): + if let id = id { + self.allStoriesEventsPipe.putNext((stableId, id)) + } + // wait for the local state to change via Postbox + break + } + }) + } } self.processContextsUpdated() @@ -440,6 +490,8 @@ final class PendingStoryManager { currentProgress[self.accountPeerId] = currentPendingItemContext.progress case let .peer(id): currentProgress[id] = currentPendingItemContext.progress + case .botPreview: + break } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Stories.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Stories.swift index 38c07f640b..21d995f956 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Stories.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Stories.swift @@ -1261,6 +1261,152 @@ func _internal_uploadStoryImpl( } } +func _internal_uploadBotPreviewImpl( + postbox: Postbox, + network: Network, + accountPeerId: PeerId, + stateManager: AccountStateManager, + messageMediaPreuploadManager: MessageMediaPreuploadManager, + revalidationContext: MediaReferenceRevalidationContext, + auxiliaryMethods: AccountAuxiliaryMethods, + toPeerId: PeerId, + stableId: Int32, + media: Media, + mediaAreas: [MediaArea], + text: String, + entities: [MessageTextEntity], + embeddedStickers: [TelegramMediaFile], + randomId: Int64 +) -> Signal { + return postbox.transaction { transaction -> Api.InputUser? in + if let peer = transaction.getPeer(toPeerId) { + return apiInputUser(peer) + } + return nil + } + |> mapToSignal { inputUser -> Signal in + guard let inputUser else { + return .single(.completed(nil)) + } + + let passFetchProgress = media is TelegramMediaFile + let (contentSignal, _) = uploadedStoryContent(postbox: postbox, network: network, media: media, mediaReference: nil, embeddedStickers: embeddedStickers, accountPeerId: accountPeerId, messageMediaPreuploadManager: messageMediaPreuploadManager, revalidationContext: revalidationContext, auxiliaryMethods: auxiliaryMethods, passFetchProgress: passFetchProgress) + return contentSignal + |> mapToSignal { result -> Signal in + switch result { + case let .progress(progress): + return .single(.progress(progress.progress)) + case let .content(content): + return postbox.transaction { transaction -> Signal in + switch content.content { + case let .media(inputMedia, _): + return network.request(Api.functions.bots.addPreviewMedia(bot: inputUser, media: inputMedia)) + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + |> mapToSignal { resultMedia -> Signal in + return postbox.transaction { transaction -> StoryUploadResult in + var currentState: Stories.LocalState + if let value = transaction.getLocalStoryState()?.get(Stories.LocalState.self) { + currentState = value + } else { + currentState = Stories.LocalState(items: []) + } + if let index = currentState.items.firstIndex(where: { $0.stableId == stableId }) { + currentState.items.remove(at: index) + transaction.setLocalStoryState(state: CodableEntry(currentState)) + } + + if let resultMediaValue = textMediaAndExpirationTimerFromApiMedia(resultMedia, toPeerId).media { + transaction.updatePeerCachedData(peerIds: Set([toPeerId]), update: { _, current in + guard var current = current as? CachedUserData else { + return current + } + guard let currentBotPreview = current.botPreview else { + return current + } + var media = currentBotPreview.media + media.append(resultMediaValue) + let botPreview = CachedUserData.BotPreview(media: media) + current = current.withUpdatedBotPreview(botPreview) + return current + }) + } + + return .completed(nil) + } + } + default: + return .complete() + } + } + |> switchToLatest + default: + return .complete() + } + } + } +} + +func _internal_deleteBotPreviews(account: Account, peerId: PeerId, ids: [MediaId]) -> Signal { + return account.postbox.transaction { transaction -> (Api.InputUser?, [Api.InputMedia]) in + guard let inputPeer = transaction.getPeer(peerId).flatMap(apiInputUser) else { + return (nil, []) + } + + var inputMedia: [Api.InputMedia] = [] + transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current -> CachedPeerData? in + guard var current = current as? CachedUserData else { + return current + } + guard let currentBotPreview = current.botPreview else { + return current + } + var media = currentBotPreview.media + + for item in media { + guard let id = item.id else { + continue + } + if ids.contains(id) { + if let image = item as? TelegramMediaImage, let resource = image.representations.last?.resource as? CloudPhotoSizeMediaResource { + inputMedia.append(.inputMediaPhoto(flags: 0, id: .inputPhoto(id: resource.photoId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), ttlSeconds: nil)) + inputMedia.append(Api.InputMedia.inputMediaPhoto(flags: 0, id: Api.InputPhoto.inputPhoto(id: resource.photoId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), ttlSeconds: nil)) + } else if let file = item as? TelegramMediaFile, let resource = file.resource as? CloudDocumentMediaResource { + inputMedia.append(.inputMediaDocument(flags: 0, id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())), ttlSeconds: nil, query: nil)) + } + } + } + + media = media.filter({ item in + guard let id = item.id else { + return false + } + return !ids.contains(id) + }) + let botPreview = CachedUserData.BotPreview(media: media) + current = current.withUpdatedBotPreview(botPreview) + return current + }) + + return (inputPeer, inputMedia) + } + |> mapToSignal { inputPeer, inputMedia -> Signal in + guard let inputPeer else { + return .complete() + } + + return account.network.request(Api.functions.bots.deletePreviewMedia(bot: inputPeer, media: inputMedia)) + |> `catch` { _ -> Signal in + return .single(.boolFalse) + } + |> mapToSignal { _ -> Signal in + return .complete() + } + } +} + func _internal_editStory(account: Account, peerId: PeerId, id: Int32, media: EngineStoryInputMedia?, mediaAreas: [MediaArea]?, text: String?, entities: [MessageTextEntity]?, privacy: EngineStoryPrivacy?) -> Signal { let contentSignal: Signal let originalMedia: Media? @@ -1472,6 +1618,8 @@ func _internal_checkStoriesUploadAvailability(account: Account, target: Stories. return .inputPeerSelf case let .peer(peerId): return transaction.getPeer(peerId).flatMap(apiInputPeer) + case let .botPreview(peerId): + return transaction.getPeer(peerId).flatMap(apiInputPeer) } } |> mapToSignal { inputPeer -> Signal in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/StoryListContext.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/StoryListContext.swift index 4357f346e4..fa33bd18a0 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/StoryListContext.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/StoryListContext.swift @@ -2066,3 +2066,147 @@ public func _internal_pollPeerStories(postbox: Postbox, network: Network, accoun } } } + +public final class BotPreviewStoryListContext: StoryListContext { + private final class Impl { + private let queue: Queue + private let account: Account + private let engine: TelegramEngine + private let peerId: EnginePeer.Id + private let isArchived: Bool + + private let statePromise = Promise() + private var stateValue: State { + didSet { + self.statePromise.set(.single(self.stateValue)) + } + } + var state: Signal { + return self.statePromise.get() + } + + private var isLoadingMore: Bool = false + private var requestDisposable: Disposable? + + private var updatesDisposable: Disposable? + + private var completionCallbacksByToken: [AnyHashable: [() -> Void]] = [:] + + private var nextId: Int32 = 1 + private var idMapping: [MediaId: Int32] = [:] + + init(queue: Queue, account: Account, engine: TelegramEngine, peerId: EnginePeer.Id) { + self.queue = queue + self.account = account + self.engine = engine + self.peerId = peerId + + let isArchived = false + + self.isArchived = isArchived + + self.stateValue = State(peerReference: nil, items: [], pinnedIds: Set(), totalCount: 0, loadMoreToken: AnyHashable(0 as Int), isCached: true, hasCache: false, allEntityFiles: [:], isLoading: false) + + self.requestDisposable = (engine.data.subscribe( + TelegramEngine.EngineData.Item.Peer.Peer(id: peerId), + TelegramEngine.EngineData.Item.Peer.BotPreview(id: peerId) + ) + |> deliverOnMainQueue).start(next: { [weak self] peer, botPreview in + guard let self else { + return + } + + var items: [State.Item] = [] + + if let botPreview { + for media in botPreview.media { + guard let mediaId = media.id else { + continue + } + + let id: Int32 + if let current = self.idMapping[mediaId] { + id = current + } else { + id = self.nextId + self.nextId += 1 + self.idMapping[mediaId] = id + } + + items.append(State.Item( + id: StoryId(peerId: peerId, id: id), + storyItem: EngineStoryItem( + id: id, + timestamp: 0, + expirationTimestamp: Int32.max, + media: EngineMedia(media), + alternativeMedia: nil, + mediaAreas: [], + text: "", + entities: [], + views: nil, + privacy: nil, + isPinned: false, + isExpired: false, + isPublic: false, + isPending: false, + isCloseFriends: false, + isContacts: false, + isSelectedContacts: false, + isForwardingDisabled: false, + isEdited: false, + isMy: false, + myReaction: nil, + forwardInfo: nil, + author: nil + ), + peer: nil + )) + } + } + + self.stateValue = State( + peerReference: (peer?._asPeer()).flatMap(PeerReference.init), + items: items, + pinnedIds: Set(), + totalCount: items.count, + loadMoreToken: nil, + isCached: botPreview != nil, + hasCache: botPreview != nil, + allEntityFiles: [:], + isLoading: botPreview == nil + ) + }) + } + + deinit { + self.requestDisposable?.dispose() + } + + func loadMore(completion: (() -> Void)?) { + } + } + + public var state: Signal { + return impl.signalWith { impl, subscriber in + return impl.state.start(next: subscriber.putNext) + } + } + + private let queue: Queue + private let impl: QueueLocalObject + + public init(account: Account, engine: TelegramEngine, peerId: EnginePeer.Id) { + let queue = Queue.mainQueue() + self.queue = queue + self.impl = QueueLocalObject(queue: queue, generate: { + return Impl(queue: queue, account: account, engine: engine, peerId: peerId) + }) + } + + public func loadMore(completion: (() -> Void)? = nil) { + self.impl.with { impl in + impl.loadMore(completion : completion) + } + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index 4245cf9907..7b24d405ac 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -1369,6 +1369,10 @@ public extension TelegramEngine { return _internal_getStoryById(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, peerId: peerId, id: id) } + public func deleteBotPreviews(peerId: EnginePeer.Id, ids: [MediaId]) -> Signal { + return _internal_deleteBotPreviews(account: self.account, peerId: peerId, ids: ids) + } + public func synchronouslyIsMessageDeletedInteractively(ids: [EngineMessage.Id]) -> [EngineMessage.Id] { return self.account.stateManager.synchronouslyIsMessageDeletedInteractively(ids: ids) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index 7024b67e07..186ab62cb4 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -197,6 +197,22 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee editableBotInfo = .single(nil) } + let botPreview: Signal + if let user = maybePeer as? TelegramUser, let _ = user.botInfo { + botPreview = network.request(Api.functions.bots.getPreviewMedias(bot: inputUser)) + |> `catch` { _ -> Signal<[Api.MessageMedia], NoError> in + return .single([]) + } + |> map { result -> CachedUserData.BotPreview? in + return CachedUserData.BotPreview(media: result.compactMap { item -> Media? in + let value = textMediaAndExpirationTimerFromApiMedia(item, user.id) + return value.media + }) + } + } else { + botPreview = .single(nil) + } + var additionalConnectedBots: Signal = .single(nil) if rawPeerId == accountPeerId { additionalConnectedBots = network.request(Api.functions.account.getConnectedBots()) @@ -210,9 +226,10 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee network.request(Api.functions.users.getFullUser(id: inputUser)) |> retryRequest, editableBotInfo, + botPreview, additionalConnectedBots ) - |> mapToSignal { result, editableBotInfo, additionalConnectedBots -> Signal in + |> mapToSignal { result, editableBotInfo, botPreview, additionalConnectedBots -> Signal in return postbox.transaction { transaction -> Bool in switch result { case let .userFull(fullUser, chats, users): @@ -401,6 +418,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee .withUpdatedBusinessIntro(mappedBusinessIntro) .withUpdatedBirthday(mappedBirthday) .withUpdatedPersonalChannel(personalChannel) + .withUpdatedBotPreview(botPreview) } }) } diff --git a/submodules/TelegramCore/Sources/UpdatePeers.swift b/submodules/TelegramCore/Sources/UpdatePeers.swift index edbf3ffb9a..86e58b9712 100644 --- a/submodules/TelegramCore/Sources/UpdatePeers.swift +++ b/submodules/TelegramCore/Sources/UpdatePeers.swift @@ -51,7 +51,7 @@ func updatePeers(transaction: Transaction, accountPeerId: PeerId, peers: Accumul if let telegramUser = TelegramUser.merge(transaction.getPeer(user.peerId) as? TelegramUser, rhs: user) { parsedPeers.append(telegramUser) switch user { - case let .user(flags, flags2, _, _, _, _, _, _, _, _, _, _, _, _, _, _, storiesMaxId, _, _): + case let .user(flags, flags2, _, _, _, _, _, _, _, _, _, _, _, _, _, _, storiesMaxId, _, _, _): let isMin = (flags & (1 << 20)) != 0 let storiesUnavailable = (flags2 & (1 << 4)) != 0 @@ -315,7 +315,7 @@ func updatePeerPresences(transaction: Transaction, accountPeerId: PeerId, peerPr parsedPresences[peerId] = presence default: switch user { - case let .user(flags, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .user(flags, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): let isMin = (flags & (1 << 20)) != 0 if isMin, let _ = transaction.getPeerPresence(peerId: peerId) { } else { @@ -383,7 +383,7 @@ func updateContacts(transaction: Transaction, apiUsers: [Api.User]) { for user in apiUsers { var isContact: Bool? switch user { - case let .user(flags, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .user(flags, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): if (flags & (1 << 20)) == 0 { isContact = (flags & (1 << 11)) != 0 } diff --git a/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift b/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift index 802c7ee155..0206dacbb7 100644 --- a/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift +++ b/submodules/TelegramUI/Components/Chat/ChatInlineSearchResultsListComponent/Sources/ChatInlineSearchResultsListComponent.swift @@ -753,14 +753,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)) + 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)) } } 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)) + 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)) } } if effectiveAuthor == nil { diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift index 4c4c6237fe..4ee70dcddd 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift @@ -234,7 +234,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) + 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) } } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift index 7cc4ac28a1..f8352540e1 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift @@ -1496,11 +1496,11 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI if let sourceAuthorInfo, let originalAuthorId = sourceAuthorInfo.originalAuthor, let peer = item.message.peers[originalAuthorId] { effectiveAuthor = peer } else if let sourceAuthorInfo, let originalAuthorName = sourceAuthorInfo.originalAuthorName { - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(originalAuthorName.persistentHashValue % 32))), accessHash: nil, firstName: originalAuthorName, 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) + effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(originalAuthorName.persistentHashValue % 32))), accessHash: nil, firstName: originalAuthorName, 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) } else { ignoreForward = true 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) + 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) } } } @@ -1517,7 +1517,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI displayAuthorInfo = !mergedTop.merged && incoming } else if let forwardInfo = item.content.firstMessage.forwardInfo, forwardInfo.flags.contains(.isImported), let authorSignature = forwardInfo.authorSignature { ignoreForward = true - 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) + 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) displayAuthorInfo = !mergedTop.merged && incoming } else if let _ = item.content.firstMessage.adAttribute, let author = item.content.firstMessage.author { ignoreForward = true diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift index 4c7a445884..4deb81d110 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift @@ -281,14 +281,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) + 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) } } 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) + 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) } } displayAuthorInfo = incoming && effectiveAuthor != nil diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift index 2a69aa8db6..7c350d7d90 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageReplyInfoNode/Sources/ChatMessageReplyInfoNode.swift @@ -209,7 +209,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) + 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) } } diff --git a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift index d8474a2073..cfd2961cb8 100644 --- a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift +++ b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift @@ -555,7 +555,12 @@ public final class ChatTitleView: UIView, NavigationBarTitleView { let string = NSAttributedString(string: statusText, font: subtitleFont, textColor: titleTheme.rootController.navigationBar.secondaryTextColor) state = .info(string, .generic) } else if let _ = user.botInfo { - let statusText = self.strings.Bot_GenericBotStatus + let statusText: String + if let subscriberCount = user.subscriberCount { + statusText = self.strings.Conversation_StatusBotSubscribers(subscriberCount) + } else { + statusText = self.strings.Bot_GenericBotStatus + } let string = NSAttributedString(string: statusText, font: subtitleFont, textColor: titleTheme.rootController.navigationBar.secondaryTextColor) state = .info(string, .generic) diff --git a/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/BUILD b/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/BUILD index dc8ed1d04c..c42e1faea0 100644 --- a/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/BUILD +++ b/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/BUILD @@ -14,6 +14,7 @@ swift_library( "//submodules/ComponentFlow", "//submodules/Components/AnimatedStickerComponent", "//submodules/Components/MultilineTextComponent", + "//submodules/Components/BalancedTextComponent", "//submodules/TelegramUI/Components/ButtonComponent", "//submodules/TelegramPresentationData", "//submodules/AccountContext", diff --git a/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift b/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift index a977743330..47357705fc 100644 --- a/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift +++ b/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift @@ -7,11 +7,12 @@ import ButtonComponent import TelegramPresentationData import AccountContext import MultilineTextComponent +import BalancedTextComponent public final class EmptyStateIndicatorComponent: Component { public let context: AccountContext public let theme: PresentationTheme - public let animationName: String + public let animationName: String? public let title: String public let text: String public let actionTitle: String? @@ -24,7 +25,7 @@ public final class EmptyStateIndicatorComponent: Component { context: AccountContext, theme: PresentationTheme, fitToHeight: Bool, - animationName: String, + animationName: String?, title: String, text: String, actionTitle: String?, @@ -94,16 +95,19 @@ public final class EmptyStateIndicatorComponent: Component { self.component = component self.componentState = state - let animationSize = self.animation.update( - transition: transition, - component: AnyComponent(AnimatedStickerComponent( - account: component.context.account, - animation: AnimatedStickerComponent.Animation(source: .bundle(name: component.animationName), loop: true), - size: CGSize(width: 120.0, height: 120.0) - )), - environment: {}, - containerSize: CGSize(width: 120.0, height: 120.0) - ) + var animationSize: CGSize? + if let animationName = component.animationName { + animationSize = self.animation.update( + transition: transition, + component: AnyComponent(AnimatedStickerComponent( + account: component.context.account, + animation: AnimatedStickerComponent.Animation(source: .bundle(name: animationName), loop: true), + size: CGSize(width: 120.0, height: 120.0) + )), + environment: {}, + containerSize: CGSize(width: 120.0, height: 120.0) + ) + } let titleSize = self.title.update( transition: .immediate, component: AnyComponent(MultilineTextComponent( @@ -116,13 +120,13 @@ public final class EmptyStateIndicatorComponent: Component { ) let textSize = self.text.update( transition: .immediate, - component: AnyComponent(MultilineTextComponent( + component: AnyComponent(BalancedTextComponent( text: .plain(NSAttributedString(string: component.text, font: Font.regular(15.0), textColor: component.theme.list.itemSecondaryTextColor)), horizontalAlignment: .center, maximumNumberOfLines: 0 )), environment: {}, - containerSize: CGSize(width: min(300.0, availableSize.width - 16.0 * 2.0), height: 1000.0) + containerSize: CGSize(width: min(400.0, availableSize.width - 16.0 * 2.0), height: 1000.0) ) var buttonSize: CGSize? if let actionTitle = component.actionTitle { @@ -203,7 +207,12 @@ public final class EmptyStateIndicatorComponent: Component { let titleSpacing: CGFloat = 17.0 let buttonSpacing: CGFloat = 21.0 - var totalHeight: CGFloat = animationSize.height + animationSpacing + titleSize.height + titleSpacing + textSize.height + var totalHeight: CGFloat = 0.0 + + if let animationSize { + totalHeight += animationSize.height + animationSpacing + } + totalHeight += titleSize.height + titleSpacing + textSize.height if let buttonSize { totalHeight += buttonSpacing + buttonSize.height } @@ -218,7 +227,7 @@ public final class EmptyStateIndicatorComponent: Component { contentY = floor((availableSize.height - totalHeight) * 0.5) } - if let animationView = self.animation.view { + if let animationSize, let animationView = self.animation.view { if animationView.superview == nil { self.addSubview(animationView) } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/Sources/PeerInfoPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/Sources/PeerInfoPaneNode.swift index 5b8d3acff0..0306135d38 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/Sources/PeerInfoPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/Sources/PeerInfoPaneNode.swift @@ -6,6 +6,7 @@ import Display import TelegramPresentationData public enum PeerInfoPaneKey: Int32 { + case botPreview case members case stories case storyArchive diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenPersonalChannelItem.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenPersonalChannelItem.swift index abc95fbf4a..ed6532694a 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenPersonalChannelItem.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenPersonalChannelItem.swift @@ -176,7 +176,7 @@ public final class LoadingOverlayNode: ASDisplayNode { let chatListPresentationData = ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true) - let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", 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)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", 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)) let timestamp1: Int32 = 100000 let peers: [EnginePeer.Id: EnginePeer] = [:] let interaction = ChatListNodeInteraction(context: context, animationCache: context.animationCache, animationRenderer: context.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift index 48e0f0dde5..faaa189d25 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift @@ -336,6 +336,7 @@ final class PeerInfoScreenData { let members: PeerInfoMembersData? let storyListContext: StoryListContext? let storyArchiveListContext: StoryListContext? + let botPreviewStoryListContext: StoryListContext? let encryptionKeyFingerprint: SecretChatKeyFingerprint? let globalSettings: TelegramGlobalSettings? let invitations: PeerExportedInvitationsState? @@ -346,6 +347,7 @@ final class PeerInfoScreenData { let isPowerSavingEnabled: Bool? let accountIsPremium: Bool let hasSavedMessageTags: Bool + let hasBotPreviewItems: Bool let isPremiumRequiredForStoryPosting: Bool let personalChannel: PeerInfoPersonalChannelData? let starsState: StarsContext.State? @@ -380,6 +382,7 @@ final class PeerInfoScreenData { members: PeerInfoMembersData?, storyListContext: StoryListContext?, storyArchiveListContext: StoryListContext?, + botPreviewStoryListContext: StoryListContext?, encryptionKeyFingerprint: SecretChatKeyFingerprint?, globalSettings: TelegramGlobalSettings?, invitations: PeerExportedInvitationsState?, @@ -390,6 +393,7 @@ final class PeerInfoScreenData { isPowerSavingEnabled: Bool?, accountIsPremium: Bool, hasSavedMessageTags: Bool, + hasBotPreviewItems: Bool, isPremiumRequiredForStoryPosting: Bool, personalChannel: PeerInfoPersonalChannelData?, starsState: StarsContext.State?, @@ -412,6 +416,7 @@ final class PeerInfoScreenData { self.members = members self.storyListContext = storyListContext self.storyArchiveListContext = storyArchiveListContext + self.botPreviewStoryListContext = botPreviewStoryListContext self.encryptionKeyFingerprint = encryptionKeyFingerprint self.globalSettings = globalSettings self.invitations = invitations @@ -422,6 +427,7 @@ final class PeerInfoScreenData { self.isPowerSavingEnabled = isPowerSavingEnabled self.accountIsPremium = accountIsPremium self.hasSavedMessageTags = hasSavedMessageTags + self.hasBotPreviewItems = hasBotPreviewItems self.isPremiumRequiredForStoryPosting = isPremiumRequiredForStoryPosting self.personalChannel = personalChannel self.starsState = starsState @@ -909,6 +915,7 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id, members: nil, storyListContext: hasStories == true ? storyListContext : nil, storyArchiveListContext: nil, + botPreviewStoryListContext: nil, encryptionKeyFingerprint: nil, globalSettings: globalSettings, invitations: nil, @@ -919,6 +926,7 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id, isPowerSavingEnabled: isPowerSavingEnabled, accountIsPremium: peer?.isPremium ?? false, hasSavedMessageTags: false, + hasBotPreviewItems: false, isPremiumRequiredForStoryPosting: true, personalChannel: personalChannel, starsState: starsState, @@ -952,6 +960,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen members: nil, storyListContext: nil, storyArchiveListContext: nil, + botPreviewStoryListContext: nil, encryptionKeyFingerprint: nil, globalSettings: nil, invitations: nil, @@ -962,6 +971,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen isPowerSavingEnabled: nil, accountIsPremium: false, hasSavedMessageTags: false, + hasBotPreviewItems: false, isPremiumRequiredForStoryPosting: true, personalChannel: nil, starsState: nil, @@ -982,7 +992,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen enum StatusInputData: Equatable { case none case presence(TelegramUserPresence) - case bot + case bot(subscriberCount: Int32?) case support } let status = Signal { subscriber in @@ -1025,7 +1035,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen return .support } if user.botInfo != nil { - return .bot + return .bot(subscriberCount: user.subscriberCount) } guard let presence = view.peerPresences[userPeerId] as? TelegramUserPresence else { return .none @@ -1034,8 +1044,12 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen } |> distinctUntilChanged).start(next: { inputData in switch inputData { - case .bot: - subscriber.putNext(PeerInfoStatusData(text: strings.Bot_GenericBotStatus, isActivity: false, key: nil)) + case let .bot(subscriberCount): + if let subscriberCount, subscriberCount > 0 { + subscriber.putNext(PeerInfoStatusData(text: strings.Conversation_StatusBotSubscribers(subscriberCount), isActivity: false, key: nil)) + } else { + subscriber.putNext(PeerInfoStatusData(text: strings.Bot_GenericBotStatus, isActivity: false, key: nil)) + } case .support: subscriber.putNext(PeerInfoStatusData(text: strings.Bot_GenericSupportStatus, isActivity: false, key: nil)) default: @@ -1102,6 +1116,20 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen hasStoryArchive = .single(false) } + var botPreviewStoryListContext: StoryListContext? + let hasBotPreviewItems: Signal + if case .bot = kind { + let botPreviewStoryListContextValue = BotPreviewStoryListContext(account: context.account, engine: context.engine, peerId: peerId) + botPreviewStoryListContext = botPreviewStoryListContextValue + hasBotPreviewItems = botPreviewStoryListContextValue.state + |> map { state in + return !state.items.isEmpty + } + |> distinctUntilChanged + } else { + hasBotPreviewItems = .single(false) + } + let accountIsPremium = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) |> map { peer -> Bool in return peer?.isPremium ?? false @@ -1209,11 +1237,12 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, + hasBotPreviewItems, peerInfoPersonalChannel(context: context, peerId: peerId, isSettings: false), privacySettings, starsRevenueContextAndState ) - |> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, hasStoryArchive, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, personalChannel, privacySettings, starsRevenueContextAndState -> PeerInfoScreenData in + |> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, hasStoryArchive, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, hasBotPreviewItems, personalChannel, privacySettings, starsRevenueContextAndState -> PeerInfoScreenData in var availablePanes = availablePanes if isMyProfile { availablePanes?.insert(.stories, at: 0) @@ -1246,6 +1275,12 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen availablePanes = availablePanesValue } } + + if let user = peerView.peers[peerView.peerId] as? TelegramUser, let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) { + availablePanes?.insert(.botPreview, at: 0) + } else if let cachedData = peerView.cachedData as? CachedUserData, let botPreview = cachedData.botPreview, !botPreview.media.isEmpty { + availablePanes?.insert(.botPreview, at: 0) + } } } else { availablePanes = nil @@ -1295,6 +1330,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen members: nil, storyListContext: storyListContext, storyArchiveListContext: storyArchiveListContext, + botPreviewStoryListContext: botPreviewStoryListContext, encryptionKeyFingerprint: encryptionKeyFingerprint, globalSettings: globalSettings, invitations: nil, @@ -1305,6 +1341,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen isPowerSavingEnabled: nil, accountIsPremium: accountIsPremium, hasSavedMessageTags: hasSavedMessageTags, + hasBotPreviewItems: hasBotPreviewItems, isPremiumRequiredForStoryPosting: false, personalChannel: personalChannel, starsState: nil, @@ -1502,6 +1539,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen members: nil, storyListContext: storyListContext, storyArchiveListContext: nil, + botPreviewStoryListContext: nil, encryptionKeyFingerprint: nil, globalSettings: nil, invitations: invitations, @@ -1512,6 +1550,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen isPowerSavingEnabled: nil, accountIsPremium: accountIsPremium, hasSavedMessageTags: hasSavedMessageTags, + hasBotPreviewItems: false, isPremiumRequiredForStoryPosting: isPremiumRequiredForStoryPosting, personalChannel: nil, starsState: nil, @@ -1800,6 +1839,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen members: membersData, storyListContext: storyListContext, storyArchiveListContext: nil, + botPreviewStoryListContext: nil, encryptionKeyFingerprint: nil, globalSettings: nil, invitations: invitations, @@ -1810,6 +1850,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen isPowerSavingEnabled: nil, accountIsPremium: accountIsPremium, hasSavedMessageTags: hasSavedMessageTags, + hasBotPreviewItems: false, isPremiumRequiredForStoryPosting: isPremiumRequiredForStoryPosting, personalChannel: nil, starsState: nil, diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift index 447b807ec8..378306bbfc 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift @@ -404,10 +404,10 @@ private final class PeerInfoPendingPane { ensureRectVisible: @escaping (UIView, CGRect) -> Void, externalDataUpdated: @escaping (ContainedViewLayoutTransition) -> Void ) { - let captureProtected = data.peer?.isCopyProtectionEnabled ?? false + var captureProtected = data.peer?.isCopyProtectionEnabled ?? false let paneNode: PeerInfoPaneNode switch key { - case .stories, .storyArchive: + case .stories, .storyArchive, .botPreview: var canManage = false if let peer = data.peer { if peer.id == context.account.peerId { @@ -419,7 +419,27 @@ private final class PeerInfoPendingPane { } } - let visualPaneNode = PeerInfoStoryPaneNode(context: context, scope: .peer(id: peerId, isSaved: false, isArchived: key == .storyArchive), captureProtected: captureProtected, isProfileEmbedded: true, canManageStories: canManage, navigationController: chatControllerInteraction.navigationController, listContext: key == .storyArchive ? data.storyArchiveListContext : data.storyListContext) + var listContext: StoryListContext? + var scope: PeerInfoStoryPaneNode.Scope = .peer(id: peerId, isSaved: false, isArchived: key == .storyArchive) + switch key { + case .storyArchive: + listContext = data.storyArchiveListContext + case .botPreview: + listContext = data.botPreviewStoryListContext + scope = .botPreview(id: peerId) + + if let peer = data.peer { + if let user = peer as? TelegramUser, let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) { + canManage = true + } + } + + captureProtected = false + default: + listContext = data.storyListContext + } + + let visualPaneNode = PeerInfoStoryPaneNode(context: context, scope: scope, captureProtected: captureProtected, isProfileEmbedded: true, canManageStories: canManage, navigationController: chatControllerInteraction.navigationController, listContext: listContext) paneNode = visualPaneNode visualPaneNode.openCurrentDate = { openMediaCalendar() @@ -1092,6 +1112,9 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat title = presentationData.strings.PeerInfo_PaneStories case .storyArchive: title = presentationData.strings.PeerInfo_PaneArchivedStories + case .botPreview: + //TODO:localize + title = "Preview" case .media: title = presentationData.strings.PeerInfo_PaneMedia case .files: diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index d8f1373090..459fd6c012 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -3626,6 +3626,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro guard let self else { return } + self.headerNode.navigationButtonContainer.performAction?(.postStory, nil, nil) } @@ -9783,92 +9784,100 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro private func openPostStory(sourceFrame: CGRect?) { self.postingAvailabilityDisposable?.dispose() - let canPostStatus: Signal - #if DEBUG && false - canPostStatus = .single(StoriesUploadAvailability.premiumRequired) - #else - canPostStatus = self.context.engine.messages.checkStoriesUploadAvailability(target: .peer(self.peerId)) - #endif - - self.postingAvailabilityDisposable = (canPostStatus - |> deliverOnMainQueue).startStrict(next: { [weak self] status in - guard let self else { + if let data = self.data, let user = data.peer as? TelegramUser, let botInfo = user.botInfo { + if !botInfo.flags.contains(.canEdit) { return } - switch status { - case .available: - var cameraTransitionIn: StoryCameraTransitionIn? - if let rightButton = self.headerNode.navigationButtonContainer.rightButtonNodes[.postStory] { - cameraTransitionIn = StoryCameraTransitionIn( - sourceView: rightButton.view, - sourceRect: rightButton.view.bounds, - sourceCornerRadius: rightButton.view.bounds.height * 0.5 - ) - } - - if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface { - let coordinator = rootController.openStoryCamera(customTarget: self.peerId, transitionIn: cameraTransitionIn, transitionedIn: {}, transitionOut: self.storyCameraTransitionOut()) - coordinator?.animateIn() - } - case .channelBoostRequired: - self.postingAvailabilityDisposable?.dispose() - - self.postingAvailabilityDisposable = combineLatest( - queue: Queue.mainQueue(), - self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.peerId)), - self.context.engine.peers.getChannelBoostStatus(peerId: self.peerId), - self.context.engine.peers.getMyBoostStatus() - ).startStrict(next: { [weak self] peer, boostStatus, myBoostStatus in - guard let self, let peer, let boostStatus, let myBoostStatus else { - return - } - - if let navigationController = self.controller?.navigationController as? NavigationController { - if let previousController = navigationController.viewControllers.last as? ShareWithPeersScreen { - previousController.dismiss() - } - let controller = self.context.sharedContext.makePremiumBoostLevelsController(context: self.context, peerId: peer.id, subject: .stories, boostStatus: boostStatus, myBoostStatus: myBoostStatus, forceDark: false, openStats: { [weak self] in - if let self { - self.openStats(section: .boosts, boostStatus: boostStatus) - } - }) - navigationController.pushViewController(controller) - } - - self.hapticFeedback.impact(.light) - }).strict() - case .premiumRequired, .monthlyLimit, .weeklyLimit, .expiringLimit: - if let sourceFrame { - let context = self.context - let location = CGRect(origin: CGPoint(x: sourceFrame.midX, y: sourceFrame.maxY), size: CGSize()) - - let text: String - text = self.presentationData.strings.StoryFeed_TooltipPremiumPostingLimited - - let tooltipController = TooltipScreen( - context: context, - account: context.account, - sharedContext: context.sharedContext, - text: .markdown(text: text), - style: .customBlur(UIColor(rgb: 0x2a2a2a), 2.0), - icon: .none, - location: .point(location, .top), - shouldDismissOnTouch: { [weak self] point, containerFrame in - if containerFrame.contains(point) { - let controller = context.sharedContext.makePremiumIntroController(context: context, source: .stories, forceDark: false, dismissed: nil) - self?.controller?.push(controller) - return .dismiss(consume: true) - } else { - return .dismiss(consume: false) - } - } - ) - self.controller?.present(tooltipController, in: .current) - } - default: - break + let cameraTransitionIn: StoryCameraTransitionIn? = nil + + if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface { + let coordinator = rootController.openStoryCamera(customTarget: .botPreview(self.peerId), transitionIn: cameraTransitionIn, transitionedIn: {}, transitionOut: self.storyCameraTransitionOut()) + coordinator?.animateIn() } - }).strict() + } else { + let canPostStatus: Signal + canPostStatus = self.context.engine.messages.checkStoriesUploadAvailability(target: .peer(self.peerId)) + + self.postingAvailabilityDisposable = (canPostStatus + |> deliverOnMainQueue).startStrict(next: { [weak self] status in + guard let self else { + return + } + switch status { + case .available: + var cameraTransitionIn: StoryCameraTransitionIn? + if let rightButton = self.headerNode.navigationButtonContainer.rightButtonNodes[.postStory] { + cameraTransitionIn = StoryCameraTransitionIn( + sourceView: rightButton.view, + sourceRect: rightButton.view.bounds, + sourceCornerRadius: rightButton.view.bounds.height * 0.5 + ) + } + + if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface { + let coordinator = rootController.openStoryCamera(customTarget: self.peerId == self.context.account.peerId ? nil : .peer(self.peerId), transitionIn: cameraTransitionIn, transitionedIn: {}, transitionOut: self.storyCameraTransitionOut()) + coordinator?.animateIn() + } + case .channelBoostRequired: + self.postingAvailabilityDisposable?.dispose() + + self.postingAvailabilityDisposable = combineLatest( + queue: Queue.mainQueue(), + self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.peerId)), + self.context.engine.peers.getChannelBoostStatus(peerId: self.peerId), + self.context.engine.peers.getMyBoostStatus() + ).startStrict(next: { [weak self] peer, boostStatus, myBoostStatus in + guard let self, let peer, let boostStatus, let myBoostStatus else { + return + } + + if let navigationController = self.controller?.navigationController as? NavigationController { + if let previousController = navigationController.viewControllers.last as? ShareWithPeersScreen { + previousController.dismiss() + } + let controller = self.context.sharedContext.makePremiumBoostLevelsController(context: self.context, peerId: peer.id, subject: .stories, boostStatus: boostStatus, myBoostStatus: myBoostStatus, forceDark: false, openStats: { [weak self] in + if let self { + self.openStats(section: .boosts, boostStatus: boostStatus) + } + }) + navigationController.pushViewController(controller) + } + + self.hapticFeedback.impact(.light) + }).strict() + case .premiumRequired, .monthlyLimit, .weeklyLimit, .expiringLimit: + if let sourceFrame { + let context = self.context + let location = CGRect(origin: CGPoint(x: sourceFrame.midX, y: sourceFrame.maxY), size: CGSize()) + + let text: String + text = self.presentationData.strings.StoryFeed_TooltipPremiumPostingLimited + + let tooltipController = TooltipScreen( + context: context, + account: context.account, + sharedContext: context.sharedContext, + text: .markdown(text: text), + style: .customBlur(UIColor(rgb: 0x2a2a2a), 2.0), + icon: .none, + location: .point(location, .top), + shouldDismissOnTouch: { [weak self] point, containerFrame in + if containerFrame.contains(point) { + let controller = context.sharedContext.makePremiumIntroController(context: context, source: .stories, forceDark: false, dismissed: nil) + self?.controller?.push(controller) + return .dismiss(consume: true) + } else { + return .dismiss(consume: false) + } + } + ) + self.controller?.present(tooltipController, in: .current) + } + default: + break + } + }).strict() + } } private func storyCameraTransitionOut() -> (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut? { @@ -10775,153 +10784,74 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro private func displayMediaGalleryContextMenu(source: ContextReferenceContentNode, gesture: ContextGesture?) { let peerId = self.peerId - let _ = (self.context.engine.data.get(EngineDataMap([ - TelegramEngine.EngineData.Item.Messages.MessageCount(peerId: peerId, threadId: self.chatLocation.threadId, tag: .photo), - TelegramEngine.EngineData.Item.Messages.MessageCount(peerId: peerId, threadId: self.chatLocation.threadId, tag: .video) - ])) - |> deliverOnMainQueue).startStandalone(next: { [weak self] messageCounts in - guard let strongSelf = self else { + if let currentPaneKey = self.paneContainerNode.currentPaneKey, case .botPreview = currentPaneKey { + guard let controller = self.controller else { return } - - var mediaCount: [MessageTags: Int32] = [:] - for (key, count) in messageCounts { - mediaCount[key.tag] = count.flatMap(Int32.init) ?? 0 - } - - let photoCount: Int32 = mediaCount[.photo] ?? 0 - let videoCount: Int32 = mediaCount[.video] ?? 0 - - guard let controller = strongSelf.controller else { + guard let pane = self.paneContainerNode.currentPane?.node as? PeerInfoStoryPaneNode else { return } - guard let pane = strongSelf.paneContainerNode.currentPane?.node as? PeerInfoVisualMediaPaneNode else { - return - } - + + let _ = pane + var items: [ContextMenuItem] = [] - - let strings = strongSelf.presentationData.strings - - var recurseGenerateAction: ((Bool) -> ContextMenuActionItem)? - let generateAction: (Bool) -> ContextMenuActionItem = { [weak pane] isZoomIn in - let nextZoomLevel = isZoomIn ? pane?.availableZoomLevels().increment : pane?.availableZoomLevels().decrement - let canZoom: Bool = nextZoomLevel != nil - - return ContextMenuActionItem(id: isZoomIn ? 0 : 1, text: isZoomIn ? strings.SharedMedia_ZoomIn : strings.SharedMedia_ZoomOut, textColor: canZoom ? .primary : .disabled, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: isZoomIn ? "Chat/Context Menu/ZoomIn" : "Chat/Context Menu/ZoomOut"), color: canZoom ? theme.contextMenu.primaryColor : theme.contextMenu.primaryColor.withMultipliedAlpha(0.4)) - }, action: canZoom ? { action in - guard let pane = pane, let zoomLevel = isZoomIn ? pane.availableZoomLevels().increment : pane.availableZoomLevels().decrement else { - return - } - pane.updateZoomLevel(level: zoomLevel) - if let recurseGenerateAction = recurseGenerateAction { - action.updateAction(0, recurseGenerateAction(true)) - action.updateAction(1, recurseGenerateAction(false)) - } - } : nil) - } - recurseGenerateAction = { isZoomIn in - return generateAction(isZoomIn) - } - - items.append(.action(generateAction(true))) - items.append(.action(generateAction(false))) - + + let strings = self.presentationData.strings + let _ = strings + + //TODO:localize + var ignoreNextActions = false - if strongSelf.chatLocation.threadId == nil { - items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ShowCalendar, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Calendar"), color: theme.contextMenu.primaryColor) - }, action: { _, a in - if ignoreNextActions { - return - } - ignoreNextActions = true - a(.default) - - self?.openMediaCalendar() - }))) - } - - if photoCount != 0 && videoCount != 0 { - items.append(.separator) - - let showPhotos: Bool - switch pane.contentType { - case .photo, .photoOrVideo: - showPhotos = true - default: - showPhotos = false + + items.append(.action(ContextMenuActionItem(text: "Add Preview", icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Add"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] _, a in + if ignoreNextActions { + return } - let showVideos: Bool - switch pane.contentType { - case .video, .photoOrVideo: - showVideos = true - default: - showVideos = false + ignoreNextActions = true + a(.default) + + if let self { + self.headerNode.navigationButtonContainer.performAction?(.postStory, nil, nil) } - - items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ShowPhotos, icon: { theme in - if !showPhotos { - return nil - } - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) - }, action: { [weak pane] _, a in - a(.default) - - guard let pane = pane else { - return - } - let updatedContentType: PeerInfoVisualMediaPaneNode.ContentType - switch pane.contentType { - case .photoOrVideo: - updatedContentType = .video - case .photo: - updatedContentType = .photo - case .video: - updatedContentType = .photoOrVideo - default: - updatedContentType = pane.contentType - } - pane.updateContentType(contentType: updatedContentType) - }))) - items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ShowVideos, icon: { theme in - if !showVideos { - return nil - } - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) - }, action: { [weak pane] _, a in - a(.default) - - guard let pane = pane else { - return - } - let updatedContentType: PeerInfoVisualMediaPaneNode.ContentType - switch pane.contentType { - case .photoOrVideo: - updatedContentType = .photo - case .photo: - updatedContentType = .photoOrVideo - case .video: - updatedContentType = .video - default: - updatedContentType = pane.contentType - } - pane.updateContentType(contentType: updatedContentType) - }))) - } - - let contextController = ContextController(presentationData: strongSelf.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: source)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) - contextController.passthroughTouchEvent = { sourceView, point in + }))) + + items.append(.action(ContextMenuActionItem(text: "Reorder", icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] _, a in + if ignoreNextActions { + return + } + ignoreNextActions = true + a(.default) + + let _ = self + }))) + + items.append(.action(ContextMenuActionItem(text: "Select", icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Select"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] _, a in + if ignoreNextActions { + return + } + ignoreNextActions = true + a(.default) + + let _ = self + }))) + + let contextController = ContextController(presentationData: self.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: source)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) + contextController.passthroughTouchEvent = { [weak self] sourceView, point in guard let strongSelf = self else { return .ignore } - + let localPoint = strongSelf.view.convert(sourceView.convert(point, to: nil), from: nil) guard let localResult = strongSelf.hitTest(localPoint, with: nil) else { return .dismiss(consume: true, result: nil) } - + var testView: UIView? = localResult while true { if let testViewValue = testView { @@ -10944,12 +10874,188 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro break } } - + return .dismiss(consume: true, result: nil) } - strongSelf.mediaGalleryContextMenu = contextController + self.mediaGalleryContextMenu = contextController controller.presentInGlobalOverlay(contextController) - }) + } else { + let _ = (self.context.engine.data.get(EngineDataMap([ + TelegramEngine.EngineData.Item.Messages.MessageCount(peerId: peerId, threadId: self.chatLocation.threadId, tag: .photo), + TelegramEngine.EngineData.Item.Messages.MessageCount(peerId: peerId, threadId: self.chatLocation.threadId, tag: .video) + ])) + |> deliverOnMainQueue).startStandalone(next: { [weak self] messageCounts in + guard let strongSelf = self else { + return + } + + var mediaCount: [MessageTags: Int32] = [:] + for (key, count) in messageCounts { + mediaCount[key.tag] = count.flatMap(Int32.init) ?? 0 + } + + let photoCount: Int32 = mediaCount[.photo] ?? 0 + let videoCount: Int32 = mediaCount[.video] ?? 0 + + guard let controller = strongSelf.controller else { + return + } + guard let pane = strongSelf.paneContainerNode.currentPane?.node as? PeerInfoVisualMediaPaneNode else { + return + } + + var items: [ContextMenuItem] = [] + + let strings = strongSelf.presentationData.strings + + var recurseGenerateAction: ((Bool) -> ContextMenuActionItem)? + let generateAction: (Bool) -> ContextMenuActionItem = { [weak pane] isZoomIn in + let nextZoomLevel = isZoomIn ? pane?.availableZoomLevels().increment : pane?.availableZoomLevels().decrement + let canZoom: Bool = nextZoomLevel != nil + + return ContextMenuActionItem(id: isZoomIn ? 0 : 1, text: isZoomIn ? strings.SharedMedia_ZoomIn : strings.SharedMedia_ZoomOut, textColor: canZoom ? .primary : .disabled, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: isZoomIn ? "Chat/Context Menu/ZoomIn" : "Chat/Context Menu/ZoomOut"), color: canZoom ? theme.contextMenu.primaryColor : theme.contextMenu.primaryColor.withMultipliedAlpha(0.4)) + }, action: canZoom ? { action in + guard let pane = pane, let zoomLevel = isZoomIn ? pane.availableZoomLevels().increment : pane.availableZoomLevels().decrement else { + return + } + pane.updateZoomLevel(level: zoomLevel) + if let recurseGenerateAction = recurseGenerateAction { + action.updateAction(0, recurseGenerateAction(true)) + action.updateAction(1, recurseGenerateAction(false)) + } + } : nil) + } + recurseGenerateAction = { isZoomIn in + return generateAction(isZoomIn) + } + + items.append(.action(generateAction(true))) + items.append(.action(generateAction(false))) + + var ignoreNextActions = false + if strongSelf.chatLocation.threadId == nil { + items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ShowCalendar, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Calendar"), color: theme.contextMenu.primaryColor) + }, action: { _, a in + if ignoreNextActions { + return + } + ignoreNextActions = true + a(.default) + + self?.openMediaCalendar() + }))) + } + + if photoCount != 0 && videoCount != 0 { + items.append(.separator) + + let showPhotos: Bool + switch pane.contentType { + case .photo, .photoOrVideo: + showPhotos = true + default: + showPhotos = false + } + let showVideos: Bool + switch pane.contentType { + case .video, .photoOrVideo: + showVideos = true + default: + showVideos = false + } + + items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ShowPhotos, icon: { theme in + if !showPhotos { + return nil + } + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) + }, action: { [weak pane] _, a in + a(.default) + + guard let pane = pane else { + return + } + let updatedContentType: PeerInfoVisualMediaPaneNode.ContentType + switch pane.contentType { + case .photoOrVideo: + updatedContentType = .video + case .photo: + updatedContentType = .photo + case .video: + updatedContentType = .photoOrVideo + default: + updatedContentType = pane.contentType + } + pane.updateContentType(contentType: updatedContentType) + }))) + items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ShowVideos, icon: { theme in + if !showVideos { + return nil + } + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) + }, action: { [weak pane] _, a in + a(.default) + + guard let pane = pane else { + return + } + let updatedContentType: PeerInfoVisualMediaPaneNode.ContentType + switch pane.contentType { + case .photoOrVideo: + updatedContentType = .photo + case .photo: + updatedContentType = .photoOrVideo + case .video: + updatedContentType = .video + default: + updatedContentType = pane.contentType + } + pane.updateContentType(contentType: updatedContentType) + }))) + } + + let contextController = ContextController(presentationData: strongSelf.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: source)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) + contextController.passthroughTouchEvent = { sourceView, point in + guard let strongSelf = self else { + return .ignore + } + + let localPoint = strongSelf.view.convert(sourceView.convert(point, to: nil), from: nil) + guard let localResult = strongSelf.hitTest(localPoint, with: nil) else { + return .dismiss(consume: true, result: nil) + } + + var testView: UIView? = localResult + while true { + if let testViewValue = testView { + if let node = testViewValue.asyncdisplaykit_node as? PeerInfoHeaderNavigationButton { + node.isUserInteractionEnabled = false + DispatchQueue.main.async { + node.isUserInteractionEnabled = true + } + return .dismiss(consume: false, result: nil) + } else if let node = testViewValue.asyncdisplaykit_node as? PeerInfoVisualMediaPaneNode { + node.brieflyDisableTouchActions() + return .dismiss(consume: false, result: nil) + } else if let node = testViewValue.asyncdisplaykit_node as? PeerInfoStoryPaneNode { + node.brieflyDisableTouchActions() + return .dismiss(consume: false, result: nil) + } else { + testView = testViewValue.superview + } + } else { + break + } + } + + return .dismiss(consume: true, result: nil) + } + strongSelf.mediaGalleryContextMenu = contextController + controller.presentInGlobalOverlay(contextController) + }) + } } private func openMediaCalendar() { @@ -11626,6 +11732,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } case .media: rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .more, isForExpandedView: true)) + case .botPreview: + if let data = self.data, data.hasBotPreviewItems { + rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .more, isForExpandedView: true)) + } default: break } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift index e254ffd891..c5741a30f7 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift @@ -1476,6 +1476,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr case peer(id: EnginePeer.Id, isSaved: Bool, isArchived: Bool) case search(query: String) case location(coordinates: MediaArea.Coordinates, venue: MediaArea.Venue) + case botPreview(id: EnginePeer.Id) } public struct ZoomLevel { @@ -1548,6 +1549,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr private var mapInfoNode: LocationInfoListItemNode? private var searchHeader: ComponentView? + private var barBackgroundLayer: SimpleLayer? + private let itemGrid: SparseItemGrid private let itemGridBinding: SparseItemGridBindingImpl private let directMediaImageCache: DirectMediaImageCache @@ -1699,6 +1702,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr self.listSource = SearchStoryListContext(account: context.account, source: .hashtag(query)) case let .location(coordinates, venue): self.listSource = SearchStoryListContext(account: context.account, source: .mediaArea(.venue(coordinates: coordinates, venue: venue))) + case let .botPreview(id): + self.listSource = BotPreviewStoryListContext(account: context.account, engine: context.engine, peerId: id) } } self.calendarSource = nil @@ -2170,6 +2175,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr switch self.scope { case let .peer(_, _, isArchived): paneKey = isArchived ? .storyArchive : .stories + case .botPreview: + paneKey = .botPreview default: paneKey = .stories } @@ -2623,7 +2630,12 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr let title: String if state.totalCount == 0 { - title = "" + if case .botPreview = self.scope { + //TODO:localize + title = "no preview added" + } else { + title = "" + } } else if case let .peer(_, isSaved, isArchived) = self.scope { if isSaved { title = self.presentationData.strings.StoryList_SubtitleSaved(Int32(state.totalCount)) @@ -2632,6 +2644,13 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr } else { title = self.presentationData.strings.StoryList_SubtitleCount(Int32(state.totalCount)) } + } else if case .botPreview = self.scope { + //TODO:localize + if state.totalCount == 1 { + title = "1 preview" + } else { + title = "\(state.totalCount) previews" + } } else { title = "" } @@ -2639,6 +2658,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr switch self.scope { case let .peer(_, _, isArchived): paneKey = isArchived ? .storyArchive : .stories + case .botPreview: + paneKey = .botPreview default: paneKey = .stories } @@ -3036,38 +3057,88 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr } private func presentDeleteConfirmation(ids: Set) { - guard case let .peer(peerId, _, _) = self.scope else { - return - } - - let presentationData = self.presentationData - let controller = ActionSheetController(presentationData: presentationData) - let dismissAction: () -> Void = { [weak controller] in - controller?.dismissAnimated() - } - - let title: String = presentationData.strings.StoryList_DeleteConfirmation_Title(Int32(ids.count)) - - controller.setItemGroups([ - ActionSheetItemGroup(items: [ - ActionSheetTextItem(title: title), - ActionSheetButtonItem(title: presentationData.strings.StoryList_DeleteConfirmation_Action, color: .destructive, action: { [weak self] in - dismissAction() - - guard let self else { - return + if case let .peer(peerId, _, _) = self.scope { + let presentationData = self.presentationData + let controller = ActionSheetController(presentationData: presentationData) + let dismissAction: () -> Void = { [weak controller] in + controller?.dismissAnimated() + } + + let title: String = presentationData.strings.StoryList_DeleteConfirmation_Title(Int32(ids.count)) + + controller.setItemGroups([ + ActionSheetItemGroup(items: [ + ActionSheetTextItem(title: title), + ActionSheetButtonItem(title: presentationData.strings.StoryList_DeleteConfirmation_Action, color: .destructive, action: { [weak self] in + dismissAction() + + guard let self else { + return + } + + if let parentController = self.parentController as? PeerInfoScreen { + parentController.cancelItemSelection() + } + + let _ = self.context.engine.messages.deleteStories(peerId: peerId, ids: Array(ids)).startStandalone() + }) + ]), + ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) + ]) + self.parentController?.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) + } else if case let .botPreview(peerId) = self.scope { + let presentationData = self.presentationData + let controller = ActionSheetController(presentationData: presentationData) + let dismissAction: () -> Void = { [weak controller] in + controller?.dismissAnimated() + } + + var mappedItemIds: [MediaId] = [] + if let items = self.items { + mappedItemIds = items.items.compactMap { item -> MediaId? in + guard let item = item as? VisualMediaItem else { + return nil } - - if let parentController = self.parentController as? PeerInfoScreen { - parentController.cancelItemSelection() + if ids.contains(item.story.id) { + return item.story.media.id + } else { + return nil } - - let _ = self.context.engine.messages.deleteStories(peerId: peerId, ids: Array(ids)).startStandalone() - }) - ]), - ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) - ]) - self.parentController?.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) + } + } + if mappedItemIds.isEmpty { + return + } + + //TODO:localize + let title: String + if mappedItemIds.count == 1 { + title = "Delete 1 Preview?" + } else { + title = "Delete \(mappedItemIds.count) Previews?" + } + + controller.setItemGroups([ + ActionSheetItemGroup(items: [ + ActionSheetTextItem(title: title), + ActionSheetButtonItem(title: "Delete", color: .destructive, action: { [weak self] in + dismissAction() + + guard let self else { + return + } + + if let parentController = self.parentController as? PeerInfoScreen { + parentController.cancelItemSelection() + } + + let _ = self.context.engine.messages.deleteBotPreviews(peerId: peerId, ids: mappedItemIds) + }) + ]), + ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) + ]) + self.parentController?.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) + } } private func update(transition: ContainedViewLayoutTransition) { @@ -3266,6 +3337,19 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr mapOptionsNode.updateLayout(size: mapOptionsFrame.size, leftInset: sideInset, rightInset: sideInset, transition: transition) } + if self.isProfileEmbedded, case .botPreview = self.scope { + let barBackgroundLayer: SimpleLayer + if let current = self.barBackgroundLayer { + barBackgroundLayer = current + } else { + barBackgroundLayer = SimpleLayer() + self.barBackgroundLayer = barBackgroundLayer + self.layer.insertSublayer(barBackgroundLayer, at: 0) + } + barBackgroundLayer.backgroundColor = presentationData.theme.list.plainBackgroundColor.cgColor + transition.updateFrame(layer: barBackgroundLayer, frame: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: gridTopInset))) + } + var bottomInset = bottomInset if self.isProfileEmbedded, let selectedIds = self.itemInteraction.selectedIds, self.canManageStories, case let .peer(peerId, _, isArchived) = self.scope { let selectionPanel: ComponentView @@ -3465,6 +3549,71 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScr backgroundColor = presentationData.theme.list.blocksBackgroundColor } + if self.didUpdateItemsOnce { + ComponentTransition(animation: .curve(duration: 0.2, curve: .easeInOut)).setBackgroundColor(view: self.view, color: backgroundColor) + } else { + self.view.backgroundColor = backgroundColor + } + } else if case .botPreview = self.scope, let items = self.items, items.items.isEmpty, items.count == 0 { + let emptyStateView: ComponentView + var emptyStateTransition = ComponentTransition(transition) + if let current = self.emptyStateView { + emptyStateView = current + } else { + emptyStateTransition = .immediate + emptyStateView = ComponentView() + self.emptyStateView = emptyStateView + } + //TODO:localize + let emptyStateSize = emptyStateView.update( + transition: emptyStateTransition, + component: AnyComponent(EmptyStateIndicatorComponent( + context: self.context, + theme: presentationData.theme, + fitToHeight: self.isProfileEmbedded, + animationName: nil, + title: "No Preview", + text: "Upload screenshots and video demos for your Mini App that will be visible for your users here.", + actionTitle: self.canManageStories ? "Add Preview" : nil, + action: { [weak self] in + guard let self else { + return + } + self.emptyAction?() + }, + additionalActionTitle: nil, + additionalAction: {} + )), + environment: {}, + containerSize: CGSize(width: size.width, height: size.height - gridTopInset - bottomInset) + ) + + let emptyStateFrame: CGRect + if self.isProfileEmbedded { + emptyStateFrame = CGRect(origin: CGPoint(x: floor((size.width - emptyStateSize.width) * 0.5), y: max(gridTopInset + 22.0, floor((visibleHeight - gridTopInset - bottomInset - emptyStateSize.height) * 0.5))), size: emptyStateSize) + } else { + emptyStateFrame = CGRect(origin: CGPoint(x: floor((size.width - emptyStateSize.width) * 0.5), y: gridTopInset), size: emptyStateSize) + } + + if let emptyStateComponentView = emptyStateView.view { + if emptyStateComponentView.superview == nil { + self.view.addSubview(emptyStateComponentView) + if self.didUpdateItemsOnce { + emptyStateComponentView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + } + } + emptyStateTransition.setFrame(view: emptyStateComponentView, frame: emptyStateFrame) + } + + let backgroundColor: UIColor + if self.isProfileEmbedded, case .botPreview = self.scope { + backgroundColor = presentationData.theme.list.blocksBackgroundColor + } else if self.isProfileEmbedded { + backgroundColor = presentationData.theme.list.plainBackgroundColor + } else { + backgroundColor = presentationData.theme.list.blocksBackgroundColor + } + if self.didUpdateItemsOnce { ComponentTransition(animation: .curve(duration: 0.2, curve: .easeInOut)).setBackgroundColor(view: self.view, color: backgroundColor) } else { diff --git a/submodules/TelegramUI/Components/SendInviteLinkScreen/Sources/SendInviteLinkScreen.swift b/submodules/TelegramUI/Components/SendInviteLinkScreen/Sources/SendInviteLinkScreen.swift index 9cbdf82a8a..4d8f5ecebd 100644 --- a/submodules/TelegramUI/Components/SendInviteLinkScreen/Sources/SendInviteLinkScreen.swift +++ b/submodules/TelegramUI/Components/SendInviteLinkScreen/Sources/SendInviteLinkScreen.swift @@ -1012,7 +1012,8 @@ public class SendInviteLinkScreen: ViewControllerComponentContainer { nameColor: user.nameColor, backgroundEmojiId: user.backgroundEmojiId, profileColor: user.profileColor, - profileBackgroundEmojiId: user.profileBackgroundEmojiId + profileBackgroundEmojiId: user.profileBackgroundEmojiId, + subscriberCount: user.subscriberCount )), canInviteWithPremium: canInviteWithPremium, premiumRequiredToContact: premiumRequiredToContact diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift index c96c73c3a5..2d28458d85 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift @@ -225,12 +225,12 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode { var peers = SimpleDictionary() var messages = SimpleDictionary() - 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) + 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) let replyMessageId = MessageId(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) + 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) 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: [:]) } diff --git a/submodules/TelegramUI/Components/Settings/PeerSelectionScreen/Sources/PeerSelectionLoadingView.swift b/submodules/TelegramUI/Components/Settings/PeerSelectionScreen/Sources/PeerSelectionLoadingView.swift index 7b2d0511a5..407a1b3eae 100644 --- a/submodules/TelegramUI/Components/Settings/PeerSelectionScreen/Sources/PeerSelectionLoadingView.swift +++ b/submodules/TelegramUI/Components/Settings/PeerSelectionScreen/Sources/PeerSelectionLoadingView.swift @@ -159,7 +159,7 @@ final class PeerSelectionLoadingView: UIView { if self.currentParams?.size != size || self.currentParams?.presentationData !== presentationData { self.currentParams = (size, presentationData) - let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", 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)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", 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)) let items = (0 ..< 1).map { _ -> ContactsPeerItem in return ContactsPeerItem( diff --git a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift index c1b99534e1..658f8e70b7 100644 --- a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift +++ b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift @@ -278,7 +278,7 @@ class ReactionChatPreviewItemNode: ListViewItemNode { var peers = SimpleDictionary() let messages = SimpleDictionary() - 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil) let messageText = item.strings.Settings_QuickReactionSetup_DemoMessageText diff --git a/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift b/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift index 7c4c162569..6ba47f35df 100644 --- a/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift +++ b/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift @@ -954,12 +954,12 @@ 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)) - 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)) - 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)) + 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)) + 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)) + 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)) 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)) - 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)) - 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)) + 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)) + 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)) let timestamp = self.referenceTimestamp @@ -1047,8 +1047,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, ASScrollViewDelegate let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil) var sampleMessages: [Message] = [] diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift index 62e79340c7..5047fb1cf6 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperGalleryItem.swift @@ -1513,8 +1513,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode { 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: 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: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil) peers[otherPeerId] = otherAuthor var messageAttributes: [MessageAttribute] = [] diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 0ac342390c..46432255a9 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -540,7 +540,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { let author: Peer if link.isCentered { - author = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + author = TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil) } else { author = accountPeer } diff --git a/submodules/TelegramUI/Sources/PollResultsController.swift b/submodules/TelegramUI/Sources/PollResultsController.swift index 7b35b3fd0f..071e764638 100644 --- a/submodules/TelegramUI/Sources/PollResultsController.swift +++ b/submodules/TelegramUI/Sources/PollResultsController.swift @@ -333,7 +333,7 @@ private func pollResultsControllerEntries(presentationData: PresentationData, me displayCount = Int(voterCount) } for peerIndex in 0 ..< displayCount { - let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), 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) + let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), 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) let peer = EngineRenderedPeer(peer: EnginePeer(fakeUser)) entries.append(.optionPeer(optionId: i, index: peerIndex, peer: peer, optionText: optionTextHeader, optionTextEntities: optionTextHeaderEntities, optionAdditionalText: optionAdditionalTextHeader, optionCount: voterCount, optionExpanded: false, opaqueIdentifier: option.opaqueIdentifier, shimmeringAlternation: peerIndex % 2, isFirstInOption: peerIndex == 0)) } diff --git a/submodules/TelegramUI/Sources/TelegramRootController.swift b/submodules/TelegramUI/Sources/TelegramRootController.swift index b2cedba094..4979df19a1 100644 --- a/submodules/TelegramUI/Sources/TelegramRootController.swift +++ b/submodules/TelegramUI/Sources/TelegramRootController.swift @@ -300,7 +300,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon } @discardableResult - public func openStoryCamera(customTarget: EnginePeer.Id?, transitionIn: StoryCameraTransitionIn?, transitionedIn: @escaping () -> Void, transitionOut: @escaping (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator? { + public func openStoryCamera(customTarget: Stories.PendingTarget?, transitionIn: StoryCameraTransitionIn?, transitionedIn: @escaping () -> Void, transitionOut: @escaping (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator? { guard let controller = self.viewControllers.last as? ViewController else { return nil } @@ -386,11 +386,22 @@ public final class TelegramRootController: NavigationController, TelegramRootCon transitionIn = .camera } + let mediaEditorCustomTarget = customTarget.flatMap { value -> EnginePeer.Id? in + switch value { + case .myStories: + return nil + case let .peer(id): + return id + case let .botPreview(id): + return id + } + } + let controller = MediaEditorScreen( context: context, mode: .storyEditor, subject: subject, - customTarget: customTarget, + customTarget: mediaEditorCustomTarget, transitionIn: transitionIn, transitionOut: { finished, isNew in if finished, let transitionOut = (externalState.transitionOut ?? transitionOut)(externalState.storyTarget, false), let destinationView = transitionOut.destinationView { @@ -414,39 +425,47 @@ public final class TelegramRootController: NavigationController, TelegramRootCon commit({}) return } - - let target: Stories.PendingTarget - let targetPeerId: EnginePeer.Id - if let customTarget { - target = .peer(customTarget) - targetPeerId = customTarget - } else { - if let sendAsPeerId = result.options.sendAsPeerId { - target = .peer(sendAsPeerId) - targetPeerId = sendAsPeerId - } else { - target = .myStories - targetPeerId = context.account.peerId - } - } - externalState.storyTarget = target - - let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: targetPeerId)) - |> deliverOnMainQueue).startStandalone(next: { [weak self] peer in - guard let self, let peer else { - return - } - - if case let .user(user) = peer { - externalState.isPeerArchived = user.storiesHidden ?? false - } else if case let .channel(channel) = peer { - externalState.isPeerArchived = channel.storiesHidden ?? false - } - - self.proceedWithStoryUpload(target: target, result: result, existingMedia: nil, forwardInfo: nil, externalState: externalState, commit: commit) + + if let customTarget, case .botPreview = customTarget { + externalState.storyTarget = customTarget + self.proceedWithStoryUpload(target: customTarget, result: result, existingMedia: nil, forwardInfo: nil, externalState: externalState, commit: commit) dismissCameraImpl?() - }) + return + } else { + let target: Stories.PendingTarget + let targetPeerId: EnginePeer.Id + if let customTarget, case let .peer(id) = customTarget { + target = .peer(id) + targetPeerId = id + } else { + if let sendAsPeerId = result.options.sendAsPeerId { + target = .peer(sendAsPeerId) + targetPeerId = sendAsPeerId + } else { + target = .myStories + targetPeerId = context.account.peerId + } + } + externalState.storyTarget = target + + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: targetPeerId)) + |> deliverOnMainQueue).startStandalone(next: { [weak self] peer in + guard let self, let peer else { + return + } + + if case let .user(user) = peer { + externalState.isPeerArchived = user.storiesHidden ?? false + } else if case let .channel(channel) = peer { + externalState.isPeerArchived = channel.storiesHidden ?? false + } + + self.proceedWithStoryUpload(target: target, result: result, existingMedia: nil, forwardInfo: nil, externalState: externalState, commit: commit) + + dismissCameraImpl?() + }) + } } as (MediaEditorScreen.Result, @escaping (@escaping () -> Void) -> Void) -> Void ) controller.cancelled = { showDraftTooltip in @@ -507,12 +526,14 @@ public final class TelegramRootController: NavigationController, TelegramRootCon return } let context = self.context - let targetPeerId: EnginePeer.Id + let targetPeerId: EnginePeer.Id? switch target { case let .peer(peerId): targetPeerId = peerId case .myStories: targetPeerId = context.account.peerId + case .botPreview: + targetPeerId = nil } if let rootTabController = self.rootTabController { @@ -594,7 +615,9 @@ public final class TelegramRootController: NavigationController, TelegramRootCon return } - chatListController.scrollToStories(peerId: targetPeerId) + if let targetPeerId { + chatListController.scrollToStories(peerId: targetPeerId) + } Queue.mainQueue().justDispatch { commit({}) }