From e7fb73cadd72d5c91141cd5c1b759721e941c6e7 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 18 Jan 2023 01:13:56 +0400 Subject: [PATCH 01/10] Channel translation --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 +- .../Sources/ChatController.swift | 7 +- .../Sources/AttachmentPanel.swift | 4 + .../ChatPanelInterfaceInteraction.swift | 21 ++ .../ChatPresentationInterfaceState.swift | 148 ++++++----- .../Display/Source/LinkHighlightingNode.swift | 19 +- .../GalleryData/Sources/GalleryData.swift | 2 +- .../Sources/GalleryControllerNode.swift | 9 + .../Sources/MediaPickerScreen.swift | 4 +- .../Sources/AvatarGalleryController.swift | 62 ++--- .../AvatarGalleryItemFooterContentNode.swift | 2 +- .../Sources/PeerAvatarImageGalleryItem.swift | 6 +- .../Sources/PeerInfoAvatarListNode.swift | 49 ++-- .../Sources/ColorPickerComponent.swift | 32 ++- .../Chat/Title Panels/Contents.json | 6 +- .../Translate.imageset/Contents.json | 12 + .../Translate.imageset/translate.pdf | 129 ++++++++++ .../TelegramUI/Sources/ChatController.swift | 125 ++++++++- .../Sources/ChatControllerNode.swift | 62 ++++- .../Sources/ChatHistoryListNode.swift | 45 +++- .../ChatMessageTextBubbleContentNode.swift | 43 +++- .../Sources/ChatRecentActionsController.swift | 4 + .../Sources/ChatTranslationPanelNode.swift | 243 ++++++++++++++++++ .../Sources/PeerInfo/PeerInfoHeaderNode.swift | 8 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 65 ++++- .../Sources/PeerSelectionControllerNode.swift | 32 ++- .../Sources/ShimmeringLinkNode.swift | 99 +++++++ submodules/TranslateUI/BUILD | 1 + .../TranslateUI/Sources/ChatTranslation.swift | 224 ++++++++++++++++ .../TranslateUI/Sources/Translate.swift | 4 +- .../Sources/UndoOverlayController.swift | 2 +- .../Sources/UndoOverlayControllerNode.swift | 11 +- 32 files changed, 1293 insertions(+), 189 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Translate.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Translate.imageset/translate.pdf create mode 100644 submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift create mode 100644 submodules/TelegramUI/Sources/ShimmeringLinkNode.swift create mode 100644 submodules/TranslateUI/Sources/ChatTranslation.swift diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 76df30be70..3b5a8499c6 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8686,7 +8686,7 @@ Sorry for the inconvenience."; "RequestPeer.SelectionConfirmationTitle" = "Are you sure you want to send %1$@ to %2$@?"; "RequestPeer.SelectionConfirmationInviteText" = "This will also add %1$@ to %2$@."; -"RequestPeer.SelectionConfirmationInviteWithRightsText" = "This will also add %1$@ to %2$@ with the following rights:\n\n%3$@."; +"RequestPeer.SelectionConfirmationInviteWithRightsText" = "This will also add %1$@ to %2$@ with the following rights:\n\n%3$@"; "RequestPeer.SelectionConfirmationSend" = "Send"; "CreateGroup.PublicLinkTitle" = "SET A PUBLIC LINK"; diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index a304f1861d..5259b30474 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -48,8 +48,9 @@ public final class ChatMessageItemAssociatedData: Equatable { public let accountPeer: EnginePeer? public let topicAuthorId: EnginePeer.Id? public let hasBots: Bool + public let translateToLanguage: String? - public init(automaticDownloadPeerType: MediaAutoDownloadPeerType, automaticDownloadPeerId: EnginePeer.Id?, automaticDownloadNetworkType: MediaAutoDownloadNetworkType, isRecentActions: Bool = false, subject: ChatControllerSubject? = nil, contactsPeerIds: Set = Set(), channelDiscussionGroup: ChannelDiscussionGroupStatus = .unknown, animatedEmojiStickers: [String: [StickerPackItem]] = [:], additionalAnimatedEmojiStickers: [String: [Int: StickerPackItem]] = [:], forcedResourceStatus: FileMediaResourceStatus? = nil, currentlyPlayingMessageId: EngineMessage.Index? = nil, isCopyProtectionEnabled: Bool = false, availableReactions: AvailableReactions?, defaultReaction: MessageReaction.Reaction?, isPremium: Bool, accountPeer: EnginePeer?, forceInlineReactions: Bool = false, alwaysDisplayTranscribeButton: DisplayTranscribeButton = DisplayTranscribeButton(canBeDisplayed: false, displayForNotConsumed: false), topicAuthorId: EnginePeer.Id? = nil, hasBots: Bool = false) { + public init(automaticDownloadPeerType: MediaAutoDownloadPeerType, automaticDownloadPeerId: EnginePeer.Id?, automaticDownloadNetworkType: MediaAutoDownloadNetworkType, isRecentActions: Bool = false, subject: ChatControllerSubject? = nil, contactsPeerIds: Set = Set(), channelDiscussionGroup: ChannelDiscussionGroupStatus = .unknown, animatedEmojiStickers: [String: [StickerPackItem]] = [:], additionalAnimatedEmojiStickers: [String: [Int: StickerPackItem]] = [:], forcedResourceStatus: FileMediaResourceStatus? = nil, currentlyPlayingMessageId: EngineMessage.Index? = nil, isCopyProtectionEnabled: Bool = false, availableReactions: AvailableReactions?, defaultReaction: MessageReaction.Reaction?, isPremium: Bool, accountPeer: EnginePeer?, forceInlineReactions: Bool = false, alwaysDisplayTranscribeButton: DisplayTranscribeButton = DisplayTranscribeButton(canBeDisplayed: false, displayForNotConsumed: false), topicAuthorId: EnginePeer.Id? = nil, hasBots: Bool = false, translateToLanguage: String? = nil) { self.automaticDownloadPeerType = automaticDownloadPeerType self.automaticDownloadPeerId = automaticDownloadPeerId self.automaticDownloadNetworkType = automaticDownloadNetworkType @@ -70,6 +71,7 @@ public final class ChatMessageItemAssociatedData: Equatable { self.topicAuthorId = topicAuthorId self.alwaysDisplayTranscribeButton = alwaysDisplayTranscribeButton self.hasBots = hasBots + self.translateToLanguage = translateToLanguage } public static func == (lhs: ChatMessageItemAssociatedData, rhs: ChatMessageItemAssociatedData) -> Bool { @@ -130,6 +132,9 @@ public final class ChatMessageItemAssociatedData: Equatable { if lhs.hasBots != rhs.hasBots { return false } + if lhs.translateToLanguage != rhs.translateToLanguage { + return false + } return true } } diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index 800a2e141a..c95c3b4079 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -705,6 +705,10 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { }, insertText: { _ in }, backwardsDeleteText: { }, restartTopic: { + }, toggleTranslation: { _ in + }, changeTranslationLanguage: { _ in + }, addDoNotTranslateLanguage: { _ in + }, hideTranslationPanel: { }, requestLayout: { _ in }, chatController: { return nil diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift index 9fa4c200f7..871e00b7b1 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift @@ -54,6 +54,11 @@ public enum ChatPanelRestrictionInfoDisplayType { case alert } +public enum ChatTranslationDisplayType { + case original + case translated +} + public final class ChatPanelInterfaceInteraction { public let setupReplyMessage: (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void public let setupEditMessage: (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void @@ -148,6 +153,10 @@ public final class ChatPanelInterfaceInteraction { public let insertText: (NSAttributedString) -> Void public let backwardsDeleteText: () -> Void public let restartTopic: () -> Void + public let toggleTranslation: (ChatTranslationDisplayType) -> Void + public let changeTranslationLanguage: (String) -> Void + public let addDoNotTranslateLanguage: (String) -> Void + public let hideTranslationPanel: () -> Void public let requestLayout: (ContainedViewLayoutTransition) -> Void public let chatController: () -> ViewController? public let statuses: ChatPanelInterfaceInteractionStatuses? @@ -246,6 +255,10 @@ public final class ChatPanelInterfaceInteraction { insertText: @escaping (NSAttributedString) -> Void, backwardsDeleteText: @escaping () -> Void, restartTopic: @escaping () -> Void, + toggleTranslation: @escaping (ChatTranslationDisplayType) -> Void, + changeTranslationLanguage: @escaping (String) -> Void, + addDoNotTranslateLanguage: @escaping (String) -> Void, + hideTranslationPanel: @escaping () -> Void, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, chatController: @escaping () -> ViewController?, statuses: ChatPanelInterfaceInteractionStatuses? @@ -343,6 +356,10 @@ public final class ChatPanelInterfaceInteraction { self.insertText = insertText self.backwardsDeleteText = backwardsDeleteText self.restartTopic = restartTopic + self.toggleTranslation = toggleTranslation + self.changeTranslationLanguage = changeTranslationLanguage + self.addDoNotTranslateLanguage = addDoNotTranslateLanguage + self.hideTranslationPanel = hideTranslationPanel self.requestLayout = requestLayout self.chatController = chatController @@ -448,6 +465,10 @@ public final class ChatPanelInterfaceInteraction { }, insertText: { _ in }, backwardsDeleteText: { }, restartTopic: { + }, toggleTranslation: { _ in + }, changeTranslationLanguage: { _ in + }, addDoNotTranslateLanguage: { _ in + }, hideTranslationPanel: { }, requestLayout: { _ in }, chatController: { return nil diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift index b14d1f9a62..1f91bb562b 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift @@ -340,6 +340,22 @@ public enum ChatHistoryNodeHistoryState: Equatable { case loaded(isEmpty: Bool) } +public struct ChatPresentationTranslationState: Equatable { + public var isEnabled: Bool + public var fromLang: String + public var toLang: String + + public init( + isEnabled: Bool, + fromLang: String, + toLang: String + ) { + self.isEnabled = isEnabled + self.fromLang = fromLang + self.toLang = toLang + } +} + public final class ChatPresentationInterfaceState: Equatable { public struct ThreadData: Equatable { public var title: String @@ -423,6 +439,7 @@ public final class ChatPresentationInterfaceState: Equatable { public let customEmojiAvailable: Bool public let threadData: ThreadData? public let isGeneralThreadClosed: Bool? + public let translationState: ChatPresentationTranslationState? public init(chatWallpaper: TelegramWallpaper, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, accountPeerId: PeerId, mode: ChatControllerPresentationMode, chatLocation: ChatLocation, subject: ChatControllerSubject?, peerNearbyData: ChatPeerNearbyData?, greetingData: ChatGreetingData?, pendingUnpinnedAllMessages: Bool, activeGroupCallInfo: ChatActiveGroupCallInfo?, hasActiveGroupCall: Bool, importState: ChatPresentationImportState?, threadData: ThreadData?, isGeneralThreadClosed: Bool?) { self.interfaceState = ChatInterfaceState() @@ -489,11 +506,12 @@ public final class ChatPresentationInterfaceState: Equatable { self.forceInputCommandsHidden = false self.voiceMessagesAvailable = true self.customEmojiAvailable = true - self.threadData = nil - self.isGeneralThreadClosed = nil + self.threadData = threadData + self.isGeneralThreadClosed = isGeneralThreadClosed + self.translationState = nil } - public init(interfaceState: ChatInterfaceState, chatLocation: ChatLocation, renderedPeer: RenderedPeer?, isNotAccessible: Bool, explicitelyCanPinMessages: Bool, contactStatus: ChatContactStatus?, hasBots: Bool, isArchived: Bool, inputTextPanelState: ChatTextInputPanelState, editMessageState: ChatEditInterfaceMessageState?, recordedMediaPreview: ChatRecordedMediaPreview?, inputQueryResults: [ChatPresentationInputQueryKind: ChatPresentationInputQueryResult], inputMode: ChatInputMode, titlePanelContexts: [ChatTitlePanelContext], keyboardButtonsMessage: Message?, pinnedMessageId: MessageId?, pinnedMessage: ChatPinnedMessage?, peerIsBlocked: Bool, peerIsMuted: Bool, peerDiscussionId: PeerId?, peerGeoLocation: PeerGeoLocation?, callsAvailable: Bool, callsPrivate: Bool, slowmodeState: ChatSlowmodeState?, chatHistoryState: ChatHistoryNodeHistoryState?, botStartPayload: String?, urlPreview: (String, TelegramMediaWebpage)?, editingUrlPreview: (String, TelegramMediaWebpage)?, search: ChatSearchData?, searchQuerySuggestionResult: ChatPresentationInputQueryResult?, presentationReady: Bool, chatWallpaper: TelegramWallpaper, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, accountPeerId: PeerId, mode: ChatControllerPresentationMode, hasScheduledMessages: Bool, autoremoveTimeout: Int32?, subject: ChatControllerSubject?, peerNearbyData: ChatPeerNearbyData?, greetingData: ChatGreetingData?, pendingUnpinnedAllMessages: Bool, activeGroupCallInfo: ChatActiveGroupCallInfo?, hasActiveGroupCall: Bool, importState: ChatPresentationImportState?, reportReason: ReportReason?, showCommands: Bool, hasBotCommands: Bool, showSendAsPeers: Bool, sendAsPeers: [SendAsPeer]?, botMenuButton: BotMenuButton, showWebView: Bool, currentSendAsPeerId: PeerId?, copyProtectionEnabled: Bool, hasPlentyOfMessages: Bool, isPremium: Bool, forceInputCommandsHidden: Bool, voiceMessagesAvailable: Bool, customEmojiAvailable: Bool, threadData: ThreadData?, isGeneralThreadClosed: Bool?) { + public init(interfaceState: ChatInterfaceState, chatLocation: ChatLocation, renderedPeer: RenderedPeer?, isNotAccessible: Bool, explicitelyCanPinMessages: Bool, contactStatus: ChatContactStatus?, hasBots: Bool, isArchived: Bool, inputTextPanelState: ChatTextInputPanelState, editMessageState: ChatEditInterfaceMessageState?, recordedMediaPreview: ChatRecordedMediaPreview?, inputQueryResults: [ChatPresentationInputQueryKind: ChatPresentationInputQueryResult], inputMode: ChatInputMode, titlePanelContexts: [ChatTitlePanelContext], keyboardButtonsMessage: Message?, pinnedMessageId: MessageId?, pinnedMessage: ChatPinnedMessage?, peerIsBlocked: Bool, peerIsMuted: Bool, peerDiscussionId: PeerId?, peerGeoLocation: PeerGeoLocation?, callsAvailable: Bool, callsPrivate: Bool, slowmodeState: ChatSlowmodeState?, chatHistoryState: ChatHistoryNodeHistoryState?, botStartPayload: String?, urlPreview: (String, TelegramMediaWebpage)?, editingUrlPreview: (String, TelegramMediaWebpage)?, search: ChatSearchData?, searchQuerySuggestionResult: ChatPresentationInputQueryResult?, presentationReady: Bool, chatWallpaper: TelegramWallpaper, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, accountPeerId: PeerId, mode: ChatControllerPresentationMode, hasScheduledMessages: Bool, autoremoveTimeout: Int32?, subject: ChatControllerSubject?, peerNearbyData: ChatPeerNearbyData?, greetingData: ChatGreetingData?, pendingUnpinnedAllMessages: Bool, activeGroupCallInfo: ChatActiveGroupCallInfo?, hasActiveGroupCall: Bool, importState: ChatPresentationImportState?, reportReason: ReportReason?, showCommands: Bool, hasBotCommands: Bool, showSendAsPeers: Bool, sendAsPeers: [SendAsPeer]?, botMenuButton: BotMenuButton, showWebView: Bool, currentSendAsPeerId: PeerId?, copyProtectionEnabled: Bool, hasPlentyOfMessages: Bool, isPremium: Bool, forceInputCommandsHidden: Bool, voiceMessagesAvailable: Bool, customEmojiAvailable: Bool, threadData: ThreadData?, isGeneralThreadClosed: Bool?, translationState: ChatPresentationTranslationState?) { self.interfaceState = interfaceState self.chatLocation = chatLocation self.renderedPeer = renderedPeer @@ -560,6 +578,7 @@ public final class ChatPresentationInterfaceState: Equatable { self.customEmojiAvailable = customEmojiAvailable self.threadData = threadData self.isGeneralThreadClosed = isGeneralThreadClosed + self.translationState = translationState } public static func ==(lhs: ChatPresentationInterfaceState, rhs: ChatPresentationInterfaceState) -> Bool { @@ -773,35 +792,38 @@ public final class ChatPresentationInterfaceState: Equatable { if lhs.isGeneralThreadClosed != rhs.isGeneralThreadClosed { return false } + if lhs.translationState != rhs.translationState { + return false + } return true } public func updatedInterfaceState(_ f: (ChatInterfaceState) -> ChatInterfaceState) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: f(self.interfaceState), chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: f(self.interfaceState), chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedPeer(_ f: (RenderedPeer?) -> RenderedPeer?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: f(self.renderedPeer), isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: f(self.renderedPeer), isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedIsNotAccessible(_ isNotAccessible: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedExplicitelyCanPinMessages(_ explicitelyCanPinMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedContactStatus(_ contactStatus: ChatContactStatus?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedHasBots(_ hasBots: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedIsArchived(_ isArchived: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedInputQueryResult(queryKind: ChatPresentationInputQueryKind, _ f: (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?) -> ChatPresentationInterfaceState { @@ -813,207 +835,211 @@ public final class ChatPresentationInterfaceState: Equatable { inputQueryResults.removeValue(forKey: queryKind) } - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedInputTextPanelState(_ f: (ChatTextInputPanelState) -> ChatTextInputPanelState) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: f(self.inputTextPanelState), editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: f(self.inputTextPanelState), editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedEditMessageState(_ editMessageState: ChatEditInterfaceMessageState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedRecordedMediaPreview(_ recordedMediaPreview: ChatRecordedMediaPreview?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedInputMode(_ f: (ChatInputMode) -> ChatInputMode) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: f(self.inputMode), titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: f(self.inputMode), titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedTitlePanelContext(_ f: ([ChatTitlePanelContext]) -> [ChatTitlePanelContext]) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: f(self.titlePanelContexts), keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: f(self.titlePanelContexts), keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedKeyboardButtonsMessage(_ message: Message?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: message, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: message, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedPinnedMessage(_ pinnedMessage: ChatPinnedMessage?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedPeerIsBlocked(_ peerIsBlocked: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedPeerIsMuted(_ peerIsMuted: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedPeerDiscussionId(_ peerDiscussionId: PeerId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedPeerGeoLocation(_ peerGeoLocation: PeerGeoLocation?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedCallsAvailable(_ callsAvailable: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedCallsPrivate(_ callsPrivate: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedSlowmodeState(_ slowmodeState: ChatSlowmodeState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedBotStartPayload(_ botStartPayload: String?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedChatHistoryState(_ chatHistoryState: ChatHistoryNodeHistoryState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedUrlPreview(_ urlPreview: (String, TelegramMediaWebpage)?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedEditingUrlPreview(_ editingUrlPreview: (String, TelegramMediaWebpage)?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedSearch(_ search: ChatSearchData?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedSearchQuerySuggestionResult(_ f: (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: f(self.searchQuerySuggestionResult), presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: f(self.searchQuerySuggestionResult), presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedMode(_ mode: ChatControllerPresentationMode) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedPresentationReady(_ presentationReady: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedTheme(_ theme: PresentationTheme) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedStrings(_ strings: PresentationStrings) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedDateTimeFormat(_ dateTimeFormat: PresentationDateTimeFormat) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedChatWallpaper(_ chatWallpaper: TelegramWallpaper) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedBubbleCorners(_ bubbleCorners: PresentationChatBubbleCorners) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedAutoremoveTimeout(_ autoremoveTimeout: Int32?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedPendingUnpinnedAllMessages(_ pendingUnpinnedAllMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedActiveGroupCallInfo(_ activeGroupCallInfo: ChatActiveGroupCallInfo?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedHasActiveGroupCall(_ hasActiveGroupCall: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedImportState(_ importState: ChatPresentationImportState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedReportReason(_ reportReason: ReportReason?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedShowCommands(_ showCommands: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedHasBotCommands(_ hasBotCommands: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedShowSendAsPeers(_ showSendAsPeers: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedSendAsPeers(_ sendAsPeers: [SendAsPeer]?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedCurrentSendAsPeerId(_ currentSendAsPeerId: PeerId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedBotMenuButton(_ botMenuButton: BotMenuButton) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedShowWebView(_ showWebView: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedCopyProtectionEnabled(_ copyProtectionEnabled: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedHasPlentyOfMessages(_ hasPlentyOfMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedIsPremium(_ isPremium: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedForceInputCommandsHidden(_ forceInputCommandsHidden: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedVoiceMessagesAvailable(_ voiceMessagesAvailable: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedCustomEmojiAvailable(_ customEmojiAvailable: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedThreadData(_ threadData: ThreadData?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: threadData, isGeneralThreadClosed: self.isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState) } public func updatedIsGeneralThreadClosed(_ isGeneralThreadClosed: Bool?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: isGeneralThreadClosed) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: isGeneralThreadClosed, translationState: self.translationState) + } + + public func updatedTranslationState(_ translationState: ChatPresentationTranslationState?) -> ChatPresentationInterfaceState { + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: translationState) } } diff --git a/submodules/Display/Source/LinkHighlightingNode.swift b/submodules/Display/Source/LinkHighlightingNode.swift index 8bcd65e0da..e650de2c46 100644 --- a/submodules/Display/Source/LinkHighlightingNode.swift +++ b/submodules/Display/Source/LinkHighlightingNode.swift @@ -52,7 +52,7 @@ private func drawConnectingCorner(context: CGContext, color: UIColor, at point: } } -private func generateRectsImage(color: UIColor, rects: [CGRect], inset: CGFloat, outerRadius: CGFloat, innerRadius: CGFloat, useModernPathCalculation: Bool) -> (CGPoint, UIImage?) { +public func generateRectsImage(color: UIColor, rects: [CGRect], inset: CGFloat, outerRadius: CGFloat, innerRadius: CGFloat, stroke: Bool = false, useModernPathCalculation: Bool) -> (CGPoint, UIImage?) { if rects.isEmpty { return (CGPoint(), nil) } @@ -179,12 +179,25 @@ private func generateRectsImage(color: UIColor, rects: [CGRect], inset: CGFloat, context.addArc(tangent1End: rects[0].topLeft, tangent2End: CGPoint(x: rects[0].minX + outerRadius, y: rects[0].minY), radius: outerRadius) context.addLine(to: CGPoint(x: rects[0].midX, y: rects[0].minY)) - context.fillPath() + if stroke { + context.setStrokeColor(color.cgColor) + context.setLineWidth(2.0) + context.strokePath() + } else { + context.fillPath() + } return } else { let path = UIBezierPath(roundedRect: rects[0], cornerRadius: outerRadius).cgPath context.addPath(path) - context.fillPath() + + if stroke { + context.setStrokeColor(color.cgColor) + context.setLineWidth(2.0) + context.strokePath() + } else { + context.fillPath() + } return } } diff --git a/submodules/GalleryData/Sources/GalleryData.swift b/submodules/GalleryData/Sources/GalleryData.swift index 21bde1bc46..931fecacc6 100644 --- a/submodules/GalleryData/Sources/GalleryData.swift +++ b/submodules/GalleryData/Sources/GalleryData.swift @@ -120,7 +120,7 @@ public func chatMessageGalleryControllerData(context: AccountContext, chatLocati if case .suggestedProfilePhoto = action.action { isSuggested = true } - let promise: Promise<[AvatarGalleryEntry]> = Promise([AvatarGalleryEntry.image(image.imageId, image.reference, image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: .media(media: .message(message: MessageReference(message), media: media), resource: $0.resource)) }), image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: .media(media: .message(message: MessageReference(message), media: media), resource: $0.resource)) }), peer._asPeer(), message.timestamp, nil, message.id, image.immediateThumbnailData, "action", false)]) + let promise: Promise<[AvatarGalleryEntry]> = Promise([AvatarGalleryEntry.image(image.imageId, image.reference, image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: .media(media: .message(message: MessageReference(message), media: media), resource: $0.resource)) }), image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: .media(media: .message(message: MessageReference(message), media: media), resource: $0.resource)) }), peer._asPeer(), message.timestamp, nil, message.id, image.immediateThumbnailData, "action", false, nil)]) let sourceCorners: AvatarGalleryController.SourceCorners if case .photoUpdated = action.action { diff --git a/submodules/GalleryUI/Sources/GalleryControllerNode.swift b/submodules/GalleryUI/Sources/GalleryControllerNode.swift index 9872517b61..6c30bd7a04 100644 --- a/submodules/GalleryUI/Sources/GalleryControllerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryControllerNode.swift @@ -4,6 +4,7 @@ import AsyncDisplayKit import Display import Postbox import SwipeToDismissGesture +import AccountContext open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { public var statusBar: StatusBar? @@ -361,9 +362,17 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture } else if useSimpleAnimation { self.scrollView.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration) } + + if let chatController = self.baseNavigationController()?.topViewController as? ChatController { + chatController.updateIsPushed(true) + } } open func animateOut(animateContent: Bool, completion: @escaping () -> Void) { + if let chatController = self.baseNavigationController()?.topViewController as? ChatController { + chatController.updateIsPushed(false) + } + self.isDismissed = true self.pager.isScrollEnabled = false diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 2b9ff18c30..ad7f810aec 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -1355,13 +1355,13 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { } if let undoOverlayController = strongSelf.undoOverlayController { - undoOverlayController.content = .image(image: image ?? UIImage(), title: nil, text: text, round: false, undo: true) + undoOverlayController.content = .image(image: image ?? UIImage(), title: nil, text: text, round: false, undoText: presentationData.strings.Undo_Undo) } else { var elevatedLayout = true if let layout = strongSelf.validLayout, case .regular = layout.metrics.widthClass { elevatedLayout = false } - let undoOverlayController = UndoOverlayController(presentationData: presentationData, content: .image(image: image ?? UIImage(), title: nil, text: text, round: false, undo: true), elevatedLayout: elevatedLayout, action: { [weak self] action in + let undoOverlayController = UndoOverlayController(presentationData: presentationData, content: .image(image: image ?? UIImage(), title: nil, text: text, round: false, undoText: presentationData.strings.Undo_Undo), elevatedLayout: elevatedLayout, action: { [weak self] action in guard let strongSelf = self else { return true } diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift index a06d161be3..ae27ca2e8c 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift @@ -85,7 +85,7 @@ public func peerInfoProfilePhotosWithCache(context: AccountContext, peerId: Peer public enum AvatarGalleryEntry: Equatable { case topImage([ImageRepresentationWithReference], [VideoRepresentationWithReference], Peer?, GalleryItemIndexData?, Data?, String?) - case image(MediaId, TelegramMediaImageReference?, [ImageRepresentationWithReference], [VideoRepresentationWithReference], Peer?, Int32?, GalleryItemIndexData?, MessageId?, Data?, String?, Bool) + case image(MediaId, TelegramMediaImageReference?, [ImageRepresentationWithReference], [VideoRepresentationWithReference], Peer?, Int32?, GalleryItemIndexData?, MessageId?, Data?, String?, Bool, TelegramMediaImage.EmojiMarkup?) public init(representation: TelegramMediaImageRepresentation, peer: Peer) { self = .topImage([ImageRepresentationWithReference(representation: representation, reference: MediaResourceReference.standalone(resource: representation.resource))], [], peer, nil, nil, nil) @@ -98,7 +98,7 @@ public enum AvatarGalleryEntry: Equatable { return .resource(last.representation.resource.id.stringRepresentation) } return .topImage - case let .image(id, _, representations, _, _, _, _, _, _, _, _): + case let .image(id, _, representations, _, _, _, _, _, _, _, _, _): if let last = representations.last { return .resource(last.representation.resource.id.stringRepresentation) } @@ -110,7 +110,7 @@ public enum AvatarGalleryEntry: Equatable { switch self { case let .topImage(_, _, peer, _, _, _): return peer - case let .image(_, _, _, _, peer, _, _, _, _, _, _): + case let .image(_, _, _, _, peer, _, _, _, _, _, _, _): return peer } } @@ -119,7 +119,7 @@ public enum AvatarGalleryEntry: Equatable { switch self { case let .topImage(representations, _, _, _, _, _): return representations - case let .image(_, _, representations, _, _, _, _, _, _, _, _): + case let .image(_, _, representations, _, _, _, _, _, _, _, _, _): return representations } } @@ -128,7 +128,7 @@ public enum AvatarGalleryEntry: Equatable { switch self { case let .topImage(_, _, _, _, immediateThumbnailData, _): return immediateThumbnailData - case let .image(_, _, _, _, _, _, _, _, immediateThumbnailData, _, _): + case let .image(_, _, _, _, _, _, _, _, immediateThumbnailData, _, _, _): return immediateThumbnailData } } @@ -137,7 +137,7 @@ public enum AvatarGalleryEntry: Equatable { switch self { case let .topImage(_, videoRepresentations, _, _, _, _): return videoRepresentations - case let .image(_, _, _, videoRepresentations, _, _, _, _, _, _, _): + case let .image(_, _, _, videoRepresentations, _, _, _, _, _, _, _, _): return videoRepresentations } } @@ -146,7 +146,7 @@ public enum AvatarGalleryEntry: Equatable { switch self { case let .topImage(_, _, _, indexData, _, _): return indexData - case let .image(_, _, _, _, _, _, indexData, _, _, _, _): + case let .image(_, _, _, _, _, _, indexData, _, _, _, _, _): return indexData } } @@ -159,8 +159,8 @@ public enum AvatarGalleryEntry: Equatable { } else { return false } - case let .image(lhsId, lhsImageReference, lhsRepresentations, lhsVideoRepresentations, lhsPeer, lhsDate, lhsIndexData, lhsMessageId, lhsImmediateThumbnailData, lhsCategory, lhsIsFallback): - if case let .image(rhsId, rhsImageReference, rhsRepresentations, rhsVideoRepresentations, rhsPeer, rhsDate, rhsIndexData, rhsMessageId, rhsImmediateThumbnailData, rhsCategory, rhsIsFallback) = rhs, lhsId == rhsId, lhsImageReference == rhsImageReference, lhsRepresentations == rhsRepresentations, lhsVideoRepresentations == rhsVideoRepresentations, arePeersEqual(lhsPeer, rhsPeer), lhsDate == rhsDate, lhsIndexData == rhsIndexData, lhsMessageId == rhsMessageId, lhsImmediateThumbnailData == rhsImmediateThumbnailData, lhsCategory == rhsCategory, lhsIsFallback == rhsIsFallback { + case let .image(lhsId, lhsImageReference, lhsRepresentations, lhsVideoRepresentations, lhsPeer, lhsDate, lhsIndexData, lhsMessageId, lhsImmediateThumbnailData, lhsCategory, lhsIsFallback, lhsEmojiMarkup): + if case let .image(rhsId, rhsImageReference, rhsRepresentations, rhsVideoRepresentations, rhsPeer, rhsDate, rhsIndexData, rhsMessageId, rhsImmediateThumbnailData, rhsCategory, rhsIsFallback, rhsEmojiMarkup) = rhs, lhsId == rhsId, lhsImageReference == rhsImageReference, lhsRepresentations == rhsRepresentations, lhsVideoRepresentations == rhsVideoRepresentations, arePeersEqual(lhsPeer, rhsPeer), lhsDate == rhsDate, lhsIndexData == rhsIndexData, lhsMessageId == rhsMessageId, lhsImmediateThumbnailData == rhsImmediateThumbnailData, lhsCategory == rhsCategory, lhsIsFallback == rhsIsFallback, lhsEmojiMarkup == rhsEmojiMarkup { return true } else { return false @@ -187,8 +187,8 @@ public func normalizeEntries(_ entries: [AvatarGalleryEntry]) -> [AvatarGalleryE let indexData = GalleryItemIndexData(position: index, totalCount: count) if case let .topImage(representations, videoRepresentations, peer, _, immediateThumbnailData, category) = entry { updatedEntries.append(.topImage(representations, videoRepresentations, peer, indexData, immediateThumbnailData, category)) - } else if case let .image(id, reference, representations, videoRepresentations, peer, date, _, messageId, immediateThumbnailData, category, isFallback) = entry { - updatedEntries.append(.image(id, reference, representations, videoRepresentations, peer, date, indexData, messageId, immediateThumbnailData, category, isFallback)) + } else if case let .image(id, reference, representations, videoRepresentations, peer, date, _, messageId, immediateThumbnailData, category, isFallback, emojiMarkup) = entry { + updatedEntries.append(.image(id, reference, representations, videoRepresentations, peer, date, indexData, messageId, immediateThumbnailData, category, isFallback, emojiMarkup)) } index += 1 } @@ -214,7 +214,7 @@ public func initialAvatarGalleryEntries(account: Account, engine: TelegramEngine if photo.immediateThumbnailData == nil, let firstEntry = initialEntries.first, let firstRepresentation = firstEntry.representations.first { representations.insert(firstRepresentation, at: 0) } - return [.image(photo.imageId, photo.reference, representations, photo.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, nil, nil, nil, photo.immediateThumbnailData, nil, false)] + return [.image(photo.imageId, photo.reference, representations, photo.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, nil, nil, nil, photo.immediateThumbnailData, nil, false, photo.emojiMarkup)] } else { if case .known = peerPhoto { return [] @@ -246,7 +246,7 @@ public func fetchedAvatarGalleryEntries(engine: TelegramEngine, account: Account if [Namespaces.Peer.CloudGroup, Namespaces.Peer.CloudChannel].contains(peer.id.namespace) { var initialMediaIds = Set() for entry in initialEntries { - if case let .image(mediaId, _, _, _, _, _, _, _, _, _, _) = entry { + if case let .image(mediaId, _, _, _, _, _, _, _, _, _, _, _) = entry { initialMediaIds.insert(mediaId) } } @@ -258,24 +258,24 @@ public func fetchedAvatarGalleryEntries(engine: TelegramEngine, account: Account photosCount += 1 for entry in initialEntries { let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photosCount)) - if case let .image(mediaId, imageReference, representations, videoRepresentations, peer, _, _, _, thumbnailData, _, _) = entry { - result.append(.image(mediaId, imageReference, representations, videoRepresentations, peer, nil, indexData, nil, thumbnailData, nil, false)) + if case let .image(mediaId, imageReference, representations, videoRepresentations, peer, _, _, _, thumbnailData, _, _, emojiMarkup) = entry { + result.append(.image(mediaId, imageReference, representations, videoRepresentations, peer, nil, indexData, nil, thumbnailData, nil, false, emojiMarkup)) index += 1 } } } let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photosCount)) - result.append(.image(photo.image.imageId, photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false)) + result.append(.image(photo.image.imageId, photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false, photo.image.emojiMarkup)) index += 1 } } else { for photo in photos { let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photos.count)) if result.isEmpty, let first = initialEntries.first { - result.append(.image(photo.image.imageId, photo.image.reference, first.representations, photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false)) + result.append(.image(photo.image.imageId, photo.image.reference, first.representations, photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false, photo.image.emojiMarkup)) } else { - result.append(.image(photo.image.imageId, photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false)) + result.append(.image(photo.image.imageId, photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false, photo.image.emojiMarkup)) } index += 1 } @@ -303,7 +303,7 @@ public func fetchedAvatarGalleryEntries(engine: TelegramEngine, account: Account if [Namespaces.Peer.CloudGroup, Namespaces.Peer.CloudChannel].contains(peer.id.namespace) { var initialMediaIds = Set() for entry in initialEntries { - if case let .image(mediaId, _, _, _, _, _, _, _, _, _, _) = entry { + if case let .image(mediaId, _, _, _, _, _, _, _, _, _, _, _) = entry { initialMediaIds.insert(mediaId) } } @@ -317,8 +317,8 @@ public func fetchedAvatarGalleryEntries(engine: TelegramEngine, account: Account photosCount += 1 for entry in initialEntries { let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photosCount)) - if case let .image(mediaId, imageReference, representations, videoRepresentations, peer, _, _, _, thumbnailData, _, _) = entry { - result.append(.image(mediaId, imageReference, representations, videoRepresentations, peer, nil, indexData, nil, thumbnailData, nil, false)) + if case let .image(mediaId, imageReference, representations, videoRepresentations, peer, _, _, _, thumbnailData, _, _, emojiMarkup) = entry { + result.append(.image(mediaId, imageReference, representations, videoRepresentations, peer, nil, indexData, nil, thumbnailData, nil, false, emojiMarkup)) index += 1 } } @@ -328,7 +328,7 @@ public func fetchedAvatarGalleryEntries(engine: TelegramEngine, account: Account } let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photosCount)) - result.append(.image(photo.image.imageId, photo.image.reference, representations, photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false)) + result.append(.image(photo.image.imageId, photo.image.reference, representations, photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false, photo.image.emojiMarkup)) index += 1 } } else { @@ -347,9 +347,9 @@ public func fetchedAvatarGalleryEntries(engine: TelegramEngine, account: Account if videoRepresentations.isEmpty, !isPersonal { videoRepresentations = photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }) } - result.append(.image(photo.image.imageId, photo.image.reference, first.representations, videoRepresentations, peer, secondEntry != nil ? 0 : photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false)) + result.append(.image(photo.image.imageId, photo.image.reference, first.representations, videoRepresentations, peer, secondEntry != nil ? 0 : photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false, photo.image.emojiMarkup)) } else { - result.append(.image(photo.image.imageId, photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, photo.image.id == lastEntry?.id)) + result.append(.image(photo.image.imageId, photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, photo.image.id == lastEntry?.id, photo.image.emojiMarkup)) } index += 1 } @@ -462,8 +462,8 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr let isFirstTime = strongSelf.entries.isEmpty var entries = entries - if !isFirstTime, let updated = entries.first, case let .image(mediaId, imageReference, _, videoRepresentations, peer, index, indexData, messageId, thumbnailData, caption, _) = updated, !videoRepresentations.isEmpty, let previous = strongSelf.entries.first, case let .topImage(representations, _, _, _, _, _) = previous { - let firstEntry = AvatarGalleryEntry.image(mediaId, imageReference, representations, videoRepresentations, peer, index, indexData, messageId, thumbnailData, caption, false) + if !isFirstTime, let updated = entries.first, case let .image(mediaId, imageReference, _, videoRepresentations, peer, index, indexData, messageId, thumbnailData, caption, _, emojiMarkup) = updated, !videoRepresentations.isEmpty, let previous = strongSelf.entries.first, case let .topImage(representations, _, _, _, _, _) = previous { + let firstEntry = AvatarGalleryEntry.image(mediaId, imageReference, representations, videoRepresentations, peer, index, indexData, messageId, thumbnailData, caption, false, emojiMarkup) entries.remove(at: 0) entries.insert(firstEntry, at: 0) } @@ -784,13 +784,13 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr if self.peer.id == self.context.account.peerId { } else { } - case let .image(_, reference, _, _, _, _, _, _, _, _, _): + case let .image(_, reference, _, _, _, _, _, _, _, _, _, _): if self.peer.id == self.context.account.peerId, let peerReference = PeerReference(self.peer) { if let reference = reference { let _ = (self.context.engine.accountData.updatePeerPhotoExisting(reference: reference) |> deliverOnMainQueue).start(next: { [weak self] photo in - if let strongSelf = self, let photo = photo, let firstEntry = strongSelf.entries.first, case let .image(_, _, _, _, _, index, indexData, messageId, _, caption, _) = firstEntry { - let updatedEntry = AvatarGalleryEntry.image(photo.imageId, photo.reference, photo.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatar(peer: peerReference, resource: $0.resource)) }), photo.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), strongSelf.peer, index, indexData, messageId, photo.immediateThumbnailData, caption, false) + if let strongSelf = self, let photo = photo, let firstEntry = strongSelf.entries.first, case let .image(_, _, _, _, _, index, indexData, messageId, _, caption, _, emojiMarkup) = firstEntry { + let updatedEntry = AvatarGalleryEntry.image(photo.imageId, photo.reference, photo.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatar(peer: peerReference, resource: $0.resource)) }), photo.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), strongSelf.peer, index, indexData, messageId, photo.immediateThumbnailData, caption, false, emojiMarkup) for (lhs, rhs) in zip(firstEntry.representations, updatedEntry.representations) { if lhs.representation.dimensions == rhs.representation.dimensions { @@ -849,7 +849,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr })) var isFallback = false - if case let .image(_, _, _, _, _, _, _, _, _, _, isFallbackValue) = rawEntry { + if case let .image(_, _, _, _, _, _, _, _, _, _, isFallbackValue, _) = rawEntry { isFallback = isFallbackValue } @@ -913,7 +913,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr } } } - case let .image(_, reference, _, _, _, _, _, messageId, _, _, isFallback): + case let .image(_, reference, _, _, _, _, _, messageId, _, _, isFallback, _): if self.peer.id == self.context.account.peerId { if isFallback { let _ = self.context.engine.accountData.updateFallbackPhoto(resource: nil, videoResource: nil, videoStartTimestamp: nil, fileId: nil, backgroundColors: nil, mapResourceToAvatarSizes: { _, _ in .single([:]) }).start() diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryItemFooterContentNode.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryItemFooterContentNode.swift index 6278a700e1..f744ae4558 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryItemFooterContentNode.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryItemFooterContentNode.swift @@ -107,7 +107,7 @@ final class AvatarGalleryItemFooterContentNode: GalleryFooterContentNode { var buttonText: String? var canShare = true switch entry { - case let .image(_, _, _, videoRepresentations, peer, date, _, _, _, _, isFallback): + case let .image(_, _, _, videoRepresentations, peer, date, _, _, _, _, isFallback, _): if date != 0 || isFallback { nameText = peer.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "" } diff --git a/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift b/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift index 514902f468..ad32448449 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift @@ -106,7 +106,7 @@ class PeerAvatarImageGalleryItem: GalleryItem { switch self.entry { case let .topImage(representations, _, _, _, _, _): content = representations - case let .image(_, _, representations, _, _, _, _, _, _, _, _): + case let .image(_, _, representations, _, _, _, _, _, _, _, _, _): content = representations } @@ -268,7 +268,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode { var id: Int64 var category: String? - if case let .image(mediaId, _, _, _, _, _, _, _, _, categoryValue, _) = entry { + if case let .image(mediaId, _, _, _, _, _, _, _, _, categoryValue, _, _) = entry { id = mediaId.id category = categoryValue } else { @@ -608,7 +608,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode { switch entry { case let .topImage(topRepresentations, _, _, _, _, _): representations = topRepresentations - case let .image(_, _, imageRepresentations, _, _, _, _, _, _, _, _): + case let .image(_, _, imageRepresentations, _, _, _, _, _, _, _, _, _): representations = imageRepresentations } diff --git a/submodules/PeerInfoAvatarListNode/Sources/PeerInfoAvatarListNode.swift b/submodules/PeerInfoAvatarListNode/Sources/PeerInfoAvatarListNode.swift index f101006af6..66f903f369 100644 --- a/submodules/PeerInfoAvatarListNode/Sources/PeerInfoAvatarListNode.swift +++ b/submodules/PeerInfoAvatarListNode/Sources/PeerInfoAvatarListNode.swift @@ -91,7 +91,7 @@ private struct CustomListItemResourceId { public enum PeerInfoAvatarListItem: Equatable { case custom(ASDisplayNode) case topImage([ImageRepresentationWithReference], [VideoRepresentationWithReference], Data?) - case image(TelegramMediaImageReference?, [ImageRepresentationWithReference], [VideoRepresentationWithReference], Data?, Bool) + case image(TelegramMediaImageReference?, [ImageRepresentationWithReference], [VideoRepresentationWithReference], Data?, Bool, TelegramMediaImage.EmojiMarkup?) var id: MediaResourceId { switch self { @@ -100,7 +100,7 @@ public enum PeerInfoAvatarListItem: Equatable { case let .topImage(representations, _, _): let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation return representation.resource.id - case let .image(_, representations, _, _, _): + case let .image(_, representations, _, _, _, _): let representation = largestImageRepresentation(representations.map { $0.representation }) ?? representations[representations.count - 1].representation return representation.resource.id } @@ -115,7 +115,7 @@ public enum PeerInfoAvatarListItem: Equatable { } else { return false } - } else if case let .image(_, rhsRepresentations, _, _, _) = self { + } else if case let .image(_, rhsRepresentations, _, _, _, _) = self { if let lhsRepresentation = largestImageRepresentation(lhsRepresentations.map { $0.representation }), let rhsRepresentation = largestImageRepresentation(rhsRepresentations.map { $0.representation }) { return lhsRepresentation.isSemanticallyEqual(to: rhsRepresentation) @@ -125,7 +125,7 @@ public enum PeerInfoAvatarListItem: Equatable { } else { return false } - } else if case let .image(_, lhsRepresentations, _, _, _) = self { + } else if case let .image(_, lhsRepresentations, _, _, _, _) = self { if case let .topImage(rhsRepresentations, _, _) = self { if let lhsRepresentation = largestImageRepresentation(lhsRepresentations.map { $0.representation }), let rhsRepresentation = largestImageRepresentation(rhsRepresentations.map { $0.representation }) { @@ -133,7 +133,7 @@ public enum PeerInfoAvatarListItem: Equatable { } else { return false } - } else if case let .image(_, rhsRepresentations, _, _, _) = self { + } else if case let .image(_, rhsRepresentations, _, _, _, _) = self { if let lhsRepresentation = largestImageRepresentation(lhsRepresentations.map { $0.representation }), let rhsRepresentation = largestImageRepresentation(rhsRepresentations.map { $0.representation }) { return lhsRepresentation.isSemanticallyEqual(to: rhsRepresentation) @@ -154,7 +154,7 @@ public enum PeerInfoAvatarListItem: Equatable { return [] case let .topImage(representations, _, _): return representations - case let .image(_, representations, _, _, _): + case let .image(_, representations, _, _, _, _): return representations } } @@ -166,7 +166,7 @@ public enum PeerInfoAvatarListItem: Equatable { return [] case let .topImage(_, videoRepresentations, _): return videoRepresentations - case let .image(_, _, videoRepresentations, _, _): + case let .image(_, _, videoRepresentations, _, _, _): return videoRepresentations } } @@ -175,20 +175,29 @@ public enum PeerInfoAvatarListItem: Equatable { switch self { case .custom, .topImage: return false - case let .image(_, _, _, _, isFallback): + case let .image(_, _, _, _, isFallback, _): return isFallback } } + var emojiMarkup: TelegramMediaImage.EmojiMarkup? { + switch self { + case let .image(_, _, _, _, _, emojiMarkup): + return emojiMarkup + default: + return nil + } + } + public init?(entry: AvatarGalleryEntry) { switch entry { case let .topImage(representations, videoRepresentations, _, _, immediateThumbnailData, _): self = .topImage(representations, videoRepresentations, immediateThumbnailData) - case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _, isFallback): + case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _, isFallback, emojiMarkup): if representations.isEmpty { return nil } - self = .image(reference, representations, videoRepresentations, immediateThumbnailData, isFallback) + self = .image(reference, representations, videoRepresentations, immediateThumbnailData, isFallback, emojiMarkup) } } } @@ -451,7 +460,7 @@ public final class PeerInfoAvatarListItemNode: ASDisplayNode { if let resource = videoRepresentations.first?.representation.resource as? CloudPhotoSizeMediaResource { id = id &+ resource.photoId } - case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail, _): + case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail, _, _): representations = imageRepresentations videoRepresentations = videoRepresentationsValue immediateThumbnailData = immediateThumbnail @@ -1000,7 +1009,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode { } func setMainItem(_ item: PeerInfoAvatarListItem) { - guard case let .image(imageReference, _, _, _, _) = item else { + guard case let .image(imageReference, _, _, _, _, _) = item else { return } var items: [PeerInfoAvatarListItem] = [] @@ -1010,16 +1019,16 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode { case let .topImage(representations, videoRepresentations, _, _, immediateThumbnailData, _): entries.append(entry) items.append(.topImage(representations, videoRepresentations, immediateThumbnailData)) - case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _, isFallback): + case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _, isFallback, emojiMarkup): if representations.isEmpty { continue } if imageReference == reference { entries.insert(entry, at: 0) - items.insert(.image(reference, representations, videoRepresentations, immediateThumbnailData, isFallback), at: 0) + items.insert(.image(reference, representations, videoRepresentations, immediateThumbnailData, isFallback, emojiMarkup), at: 0) } else { entries.append(entry) - items.append(.image(reference, representations, videoRepresentations, immediateThumbnailData, isFallback)) + items.append(.image(reference, representations, videoRepresentations, immediateThumbnailData, isFallback, emojiMarkup)) } } } @@ -1038,7 +1047,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode { } public func deleteItem(_ item: PeerInfoAvatarListItem) -> Bool { - guard case let .image(imageReference, _, _, _, _) = item else { + guard case let .image(imageReference, _, _, _, _, _) = item else { return false } @@ -1053,13 +1062,13 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode { case let .topImage(representations, videoRepresentations, _, _, immediateThumbnailData, _): entries.append(entry) items.append(.topImage(representations, videoRepresentations, immediateThumbnailData)) - case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _, isFallback): + case let .image(_, reference, representations, videoRepresentations, _, _, _, _, immediateThumbnailData, _, isFallback, emojiMarkup): if representations.isEmpty { continue } if imageReference != reference { entries.append(entry) - items.append(.image(reference, representations, videoRepresentations, immediateThumbnailData, isFallback)) + items.append(.image(reference, representations, videoRepresentations, immediateThumbnailData, isFallback, emojiMarkup)) } else { deletedIndex = index } @@ -1125,8 +1134,8 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode { } var synchronous = false - if !strongSelf.galleryEntries.isEmpty, let updated = entries.first, case let .image(mediaId, reference, _, videoRepresentations, peer, index, indexData, messageId, thumbnailData, caption, _) = updated, !videoRepresentations.isEmpty, let previous = strongSelf.galleryEntries.first, case let .topImage(representations, _, _, _, _, _) = previous { - let firstEntry = AvatarGalleryEntry.image(mediaId, reference, representations, videoRepresentations, peer, index, indexData, messageId, thumbnailData, caption, false) + if !strongSelf.galleryEntries.isEmpty, let updated = entries.first, case let .image(mediaId, reference, _, videoRepresentations, peer, index, indexData, messageId, thumbnailData, caption, _, emojiMarkup) = updated, !videoRepresentations.isEmpty, let previous = strongSelf.galleryEntries.first, case let .topImage(representations, _, _, _, _, _) = previous { + let firstEntry = AvatarGalleryEntry.image(mediaId, reference, representations, videoRepresentations, peer, index, indexData, messageId, thumbnailData, caption, false, emojiMarkup) entries.remove(at: 0) entries.insert(firstEntry, at: 0) synchronous = true diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/ColorPickerComponent.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/ColorPickerComponent.swift index 851f611299..4138eb00ff 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/ColorPickerComponent.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/ColorPickerComponent.swift @@ -79,6 +79,8 @@ final class ColorPickerComponent: Component { private let topSeparatorView: UIView private let separatorView: UIView + private var changingColor = false + init(theme: PresentationTheme, strings: PresentationStrings) { self.addButton = HighlightableButtonNode() @@ -190,9 +192,10 @@ final class ColorPickerComponent: Component { }, animated: strongSelf.state.colors.count >= 2) } } - + self.colorPickerNode.colorChanged = { [weak self] color in if let strongSelf = self { + strongSelf.changingColor = true strongSelf.updateState({ current in var updated = current updated.preview = true @@ -205,6 +208,7 @@ final class ColorPickerComponent: Component { } self.colorPickerNode.colorChangeEnded = { [weak self] color in if let strongSelf = self { + strongSelf.changingColor = false strongSelf.updateState({ current in var updated = current updated.preview = false @@ -416,18 +420,20 @@ final class ColorPickerComponent: Component { transition.setFrame(view: self.topSeparatorView, frame: CGRect(x: 0.0, y: size.height, width: availableSize.width, height: UIScreenPixel)) transition.setFrame(view: self.separatorView, frame: CGRect(x: size.width / 2.0, y: size.height, width: UIScreenPixel, height: buttonHeight)) - self.updateState({ current in - var updated = current - updated.colors = component.colors.map { HSBColor(rgb: $0) } - - if component.isVisible != previousIsVisible && component.isVisible { - updated.selection = 0 - } - - return updated - }, updateLayout: true, notify: false, animated: false) + if !self.changingColor { + self.updateState({ current in + var updated = current + updated.colors = component.colors.map { HSBColor(rgb: $0) } + + if component.isVisible != previousIsVisible && component.isVisible { + updated.selection = 0 + } + + return updated + }, updateLayout: true, notify: false, animated: false) - self.updateLayout(size: size, transition: transition.containedViewLayoutTransition) + self.updateLayout(size: size, transition: transition.containedViewLayoutTransition) + } return panelSize } } @@ -588,7 +594,7 @@ private final class WallpaperColorHueSaturationNode: ASDisplayNode { let context = UIGraphicsGetCurrentContext()! let colorSpace = CGColorSpaceCreateDeviceRGB() - let colors = [UIColor(rgb: 0xff0000).cgColor, UIColor(rgb: 0xffff00).cgColor, UIColor(rgb: 0x00ff00).cgColor, UIColor(rgb: 0x00ffff).cgColor, UIColor(rgb: 0x0000ff).cgColor, UIColor(rgb: 0xff00ff).cgColor, UIColor(rgb: 0xff0000).cgColor] + let colors = [UIColor(rgb: 0xff0000).cgColor, UIColor(rgb: 0xffff00).cgColor, UIColor(rgb: 0x00ff00).cgColor, UIColor(rgb: 0x00ffff).cgColor, UIColor(rgb: 0x0000ff).cgColor, UIColor(rgb: 0xff00ff).cgColor, UIColor(rgb: 0xfe0000).cgColor] var locations: [CGFloat] = [0.0, 0.16667, 0.33333, 0.5, 0.66667, 0.83334, 1.0] let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: bounds.width, y: 0.0), options: CGGradientDrawingOptions()) diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Contents.json index 38f0c81fc2..6e965652df 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Contents.json @@ -1,9 +1,9 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 }, "properties" : { "provides-namespace" : true } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Translate.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Translate.imageset/Contents.json new file mode 100644 index 0000000000..b0911cb948 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Translate.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "translate.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Translate.imageset/translate.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Translate.imageset/translate.pdf new file mode 100644 index 0000000000..8a83de2bb1 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Title Panels/Translate.imageset/translate.pdf @@ -0,0 +1,129 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 10.418762 9.436401 cm +0.000000 0.000000 0.000000 scn +6.301464 17.283901 m +6.041765 17.543600 5.620710 17.543600 5.361012 17.283901 c +5.101313 17.024202 5.101313 16.603148 5.361012 16.343449 c +7.861012 13.843449 l +8.120710 13.583750 8.541765 13.583750 8.801464 13.843449 c +9.061163 14.103148 9.061163 14.524202 8.801464 14.783901 c +6.301464 17.283901 l +h +14.581238 11.148675 m +12.736396 11.148675 l +12.630251 7.613420 11.663549 4.830535 9.738964 2.905949 c +9.646558 2.813542 9.552173 2.723344 9.455821 2.635344 c +11.064666 1.712594 13.173446 1.228676 15.831238 1.228676 c +16.198507 1.228676 16.496239 0.930944 16.496239 0.563675 c +16.496239 0.196405 16.198507 -0.101326 15.831238 -0.101326 c +12.784251 -0.101326 10.263335 0.501429 8.331239 1.764598 c +6.399143 0.501429 3.878224 -0.101326 0.831238 -0.101326 c +0.463968 -0.101326 0.166238 0.196405 0.166238 0.563675 c +0.166238 0.930944 0.463968 1.228676 0.831238 1.228676 c +3.489030 1.228676 5.597812 1.712595 7.206657 2.635345 c +7.110305 2.723345 7.015918 2.813542 6.923512 2.905949 c +4.998926 4.830535 4.032225 7.613420 3.926080 11.148675 c +2.081238 11.148675 l +1.713968 11.148675 1.416238 11.446405 1.416238 11.813675 c +1.416238 12.180944 1.713968 12.478675 2.081238 12.478675 c +4.581238 12.478675 l +12.081238 12.478675 l +14.581238 12.478675 l +14.948507 12.478675 15.246238 12.180944 15.246238 11.813675 c +15.246238 11.446405 14.948507 11.148675 14.581238 11.148675 c +h +5.256671 11.148675 m +11.405805 11.148675 l +11.300447 7.846343 10.399273 5.447162 8.798512 3.846401 c +8.649684 3.697574 8.493955 3.554793 8.331240 3.418138 c +8.168525 3.554793 8.012792 3.697574 7.863964 3.846401 c +6.263203 5.447162 5.362030 7.846343 5.256671 11.148675 c +h +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 2.918579 4.411682 cm +0.000000 0.000000 0.000000 scn +7.071909 14.590109 m +6.969668 14.840033 6.726449 15.003318 6.456421 15.003318 c +6.186393 15.003318 5.943174 14.840033 5.840932 14.590109 c +0.215932 0.840109 l +0.076872 0.500184 0.239705 0.111890 0.579630 -0.027171 c +0.919555 -0.166231 1.307849 -0.003398 1.446910 0.336527 c +3.323344 4.923366 l +3.326032 4.923333 3.328725 4.923318 3.331421 4.923318 c +9.581421 4.923318 l +9.584117 4.923318 9.586809 4.923333 9.589498 4.923366 c +11.465932 0.336527 l +11.604993 -0.003398 11.993287 -0.166231 12.333212 -0.027171 c +12.673137 0.111890 12.835970 0.500184 12.696910 0.840109 c +7.071909 14.590109 l +h +9.045426 6.253318 m +6.456421 12.581999 l +3.867415 6.253318 l +9.045426 6.253318 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 2538 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000002628 00000 n +0000002651 00000 n +0000002824 00000 n +0000002898 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +2957 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 6d7b66f68e..2dc7c3487c 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -520,7 +520,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - private var importStateDisposable: Disposable? + private var translationStateDisposable: Disposable? private var nextChannelToReadDisposable: Disposable? @@ -4147,10 +4147,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } let peerName = EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder) - let text: String + let attributedTitle: NSAttributedString? + let attributedText: NSAttributedString + + let theme = AlertControllerTheme(presentationData: strongSelf.presentationData) if case .user = peerType { - text = strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationText(peerName, botName).string + attributedTitle = nil + attributedText = NSAttributedString(string: strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationTitle(peerName, botName).string, font: Font.medium(17.0), textColor: theme.primaryColor, paragraphAlignment: .center) + } else { + attributedTitle = NSAttributedString(string: strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationTitle(peerName, botName).string, font: Font.semibold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center) + var botAdminRights: TelegramChatAdminRights? switch peerType { case let .group(group): @@ -4161,16 +4168,27 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G break } if let botAdminRights { - text = strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationInviteWithRightsText(peerName, botName, botName, peerName, stringForAdminRights(strings: strongSelf.presentationData.strings, adminRights: botAdminRights)).string + let stringWithRanges = strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationInviteWithRightsText(botName, peerName, stringForAdminRights(strings: strongSelf.presentationData.strings, adminRights: botAdminRights)) + let formattedString = NSMutableAttributedString(string: stringWithRanges.string, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center) + for range in stringWithRanges.ranges.prefix(2) { + formattedString.addAttribute(.font, value: Font.semibold(13.0), range: range.range) + } + attributedText = formattedString } else { - text = strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationInviteText(peerName, botName, botName, peerName).string + let stringWithRanges = strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationInviteText(botName, peerName) + let formattedString = NSMutableAttributedString(string: stringWithRanges.string, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center) + for range in stringWithRanges.ranges.prefix(2) { + formattedString.addAttribute(.font, value: Font.semibold(13.0), range: range.range) + } + attributedText = formattedString } } - - strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationSend, action: { [weak controller] in + + let controller = richTextAlertController(context: context, title: attributedTitle, text: attributedText, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationSend, action: { [weak controller] in let _ = context.engine.peers.sendBotRequestedPeer(messageId: messageId, buttonId: buttonId, requestedPeerId: peer.id).start() controller?.dismiss() - })]), in: .window(.root)) + })]) + strongSelf.present(controller, in: .window(.root)) } createNewGroupImpl = { [weak controller] in switch peerType { @@ -5783,12 +5801,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.peerSuggestionsDismissDisposable.dispose() self.selectAddMemberDisposable.dispose() self.addMemberDisposable.dispose() - self.importStateDisposable?.dispose() self.nextChannelToReadDisposable?.dispose() self.inviteRequestsDisposable.dispose() self.sendAsPeersDisposable?.dispose() self.preloadAttachBotIconsDisposables?.dispose() self.keepMessageCountersSyncrhonizedDisposable?.dispose() + self.translationStateDisposable?.dispose() } deallocate() } @@ -6552,6 +6570,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G threadData = .single(nil) } + if peerId.namespace == Namespaces.Peer.CloudChannel { + self.translationStateDisposable = (chatTranslationState(context: self.context, peerId: peerId) + |> deliverOnMainQueue).start(next: { [weak self] translationState in + if let strongSelf = self { + var chatTranslationState: ChatPresentationTranslationState? + if let translationState, translationState.isHidden != true && !translationState.fromLang.isEmpty { + chatTranslationState = ChatPresentationTranslationState(isEnabled: translationState.isEnabled, fromLang: translationState.fromLang, toLang: translationState.toLang ?? strongSelf.presentationData.strings.baseLanguageCode) + } + strongSelf.updateChatPresentationInterfaceState(animated: strongSelf.willAppear, interactive: strongSelf.willAppear, { state in + return state.updatedTranslationState(chatTranslationState) + }) + } + }) + } + self.cachedDataDisposable = combineLatest(queue: .mainQueue(), self.chatDisplayNode.historyNode.cachedPeerDataAndMessages, hasPendingMessages, isTopReplyThreadMessageShown, @@ -9746,6 +9779,80 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } let _ = strongSelf.context.engine.peers.setForumChannelTopicClosed(id: peerId, threadId: threadId, isClosed: false).start() + }, toggleTranslation: { [weak self] type in + guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else { + return + } + let _ = (updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: peerId, { current in + return current?.withIsEnabled(type == .translated) + }) + |> deliverOnMainQueue).start(completed: { [weak self] in + if let strongSelf = self, type == .translated { + Queue.mainQueue().after(0.3) { + strongSelf.chatDisplayNode.historyNode.refreshPollActionsForVisibleMessages() + } + } + }) + }, changeTranslationLanguage: { [weak self] langCode in + guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else { + return + } + let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: peerId, { current in + return current?.withToLang(langCode).withIsEnabled(true) + }).start() + }, addDoNotTranslateLanguage: { [weak self] langCode in + guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else { + return + } + let _ = updateTranslationSettingsInteractively(accountManager: strongSelf.context.sharedContext.accountManager, { current in + var updated = current + if var ignoredLanguages = updated.ignoredLanguages { + ignoredLanguages.append(langCode) + updated.ignoredLanguages = ignoredLanguages + } else { + updated.ignoredLanguages = [strongSelf.presentationData.strings.baseLanguageCode, langCode] + } + return updated + }).start() + let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: peerId, { current in + return nil + }).start() + + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } + var languageCode = presentationData.strings.baseLanguageCode + let rawSuffix = "-raw" + if languageCode.hasSuffix(rawSuffix) { + languageCode = String(languageCode.dropLast(rawSuffix.count)) + } + let locale = Locale(identifier: languageCode) + let fromLanguage: String = locale.localizedString(forLanguageCode: langCode) ?? "" + + strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .image(image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/Translate"), color: .white)!, title: nil, text: presentationData.strings.Conversation_Translation_AddedToDoNotTranslateText(fromLanguage).string, round: false, undoText: "Settings"), elevatedLayout: false, animateInAsReplacement: false, action: { [weak self] action in + if case .undo = action, let strongSelf = self { + let controller = translationSettingsController(context: strongSelf.context) + controller.navigationPresentation = .modal + strongSelf.push(controller) + } + return true + }), in: .current) + }, hideTranslationPanel: { [weak self] in + guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else { + return + } + let context = strongSelf.context + let _ = updateChatTranslationStateInteractively(engine: context.engine, peerId: peerId, { current in + return current?.withIsHidden(true) + }).start() + + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } + strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .image(image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/Translate"), color: .white)!, title: nil, text: presentationData.strings.Conversation_Translation_TranslationBarHiddenText, round: false, undoText: presentationData.strings.Undo_Undo), elevatedLayout: false, animateInAsReplacement: false, action: { action in + if case .undo = action { + let _ = updateChatTranslationStateInteractively(engine: context.engine, peerId: peerId, { current in + return current?.withIsHidden(false) + }).start() + } + return true + }), in: .current) }, requestLayout: { [weak self] transition in if let strongSelf = self, let layout = strongSelf.validLayout { strongSelf.containerLayoutUpdated(layout, transition: transition) diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index cb6c037705..311ad495a3 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -130,6 +130,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { private let titleAccessoryPanelContainer: ChatControllerTitlePanelNodeContainer private var titleAccessoryPanelNode: ChatTitleAccessoryPanelNode? + private var chatTranslationPanel: ChatTranslationPanelNode? + private var inputPanelNode: ChatInputPanelNode? private(set) var inputPanelOverscrollNode: ChatInputPanelOverscrollNode? private weak var currentDismissedInputPanelNode: ChatInputPanelNode? @@ -1091,6 +1093,42 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.titleAccessoryPanelNode = nil } + var dismissedTranslationPanelNode: ChatTranslationPanelNode? + var immediatelyLayoutTranslationPanelNodeAndAnimateAppearance = false + var translationPanelHeight: CGFloat? + if let _ = self.chatPresentationInterfaceState.translationState { + let translationPanelNode: ChatTranslationPanelNode + if let current = self.chatTranslationPanel { + translationPanelNode = current + } else { + translationPanelNode = ChatTranslationPanelNode(context: self.context) + } + translationPanelNode.interfaceInteraction = self.interfaceInteraction + + if self.chatTranslationPanel != translationPanelNode { + dismissedTranslationPanelNode = self.chatTranslationPanel + self.chatTranslationPanel = translationPanelNode + immediatelyLayoutTranslationPanelNodeAndAnimateAppearance = true + self.titleAccessoryPanelContainer.addSubnode(translationPanelNode) + + translationPanelNode.clipsToBounds = true + if transition.isAnimated { + extraTransition = .animated(duration: 0.2, curve: .easeInOut) + } + } + + let height = translationPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, transition: immediatelyLayoutTitleAccessoryPanelNodeAndAnimateAppearance ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState) + translationPanelHeight = height + if immediatelyLayoutTranslationPanelNodeAndAnimateAppearance { + translationPanelNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + translationPanelNode.subnodeTransform = CATransform3DMakeTranslation(0.0, -height, 0.0) + extraTransition.updateSublayerTransformOffset(layer: translationPanelNode.layer, offset: CGPoint()) + } + } else if let chatTranslationPanel = self.chatTranslationPanel { + dismissedTranslationPanelNode = chatTranslationPanel + self.chatTranslationPanel = nil + } + var dismissedImportStatusPanelNode: ChatImportStatusPanel? var importStatusPanelHeight: CGFloat? if let importState = self.chatPresentationInterfaceState.importState { @@ -1409,13 +1447,22 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { transition.updateFrame(node: self.inputContextPanelContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: layout.size.height))) transition.updateFrame(node: self.inputContextOverTextPanelContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: layout.size.height))) + var extraNavigationBarHeight: CGFloat = 0.0 var titleAccessoryPanelFrame: CGRect? if let _ = self.titleAccessoryPanelNode, let panelHeight = titleAccessoryPanelHeight { titleAccessoryPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: panelHeight)) insets.top += panelHeight + extraNavigationBarHeight += titleAccessoryPanelBackgroundHeight ?? 0.0 + } + + var translationPanelFrame: CGRect? + if let _ = self.chatTranslationPanel, let panelHeight = translationPanelHeight { + translationPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: extraNavigationBarHeight), size: CGSize(width: layout.size.width, height: panelHeight)) + insets.top += panelHeight + extraNavigationBarHeight += panelHeight } - updateExtraNavigationBarBackgroundHeight(titleAccessoryPanelBackgroundHeight ?? 0.0, extraTransition) + updateExtraNavigationBarBackgroundHeight(extraNavigationBarHeight, extraTransition) var importStatusPanelFrame: CGRect? if let _ = self.chatImportStatusPanel, let panelHeight = importStatusPanelHeight { @@ -1793,6 +1840,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { transition.animatePositionAdditive(node: titleAccessoryPanelNode, offset: CGPoint(x: 0.0, y: -titleAccessoryPanelFrame.height)) } + if let chatTranslationPanel = self.chatTranslationPanel, let translationPanelFrame = translationPanelFrame, !chatTranslationPanel.frame.equalTo(translationPanelFrame) { + chatTranslationPanel.frame = translationPanelFrame + transition.animatePositionAdditive(node: chatTranslationPanel, offset: CGPoint(x: 0.0, y: -translationPanelFrame.height)) + } + if let chatImportStatusPanel = self.chatImportStatusPanel, let importStatusPanelFrame = importStatusPanelFrame, !chatImportStatusPanel.frame.equalTo(importStatusPanelFrame) { chatImportStatusPanel.frame = importStatusPanelFrame //transition.animatePositionAdditive(node: chatImportStatusPanel, offset: CGPoint(x: 0.0, y: -titleAccessoryPanelFrame.height)) @@ -1889,6 +1941,14 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { }) } + if let dismissedTranslationPanelNode = dismissedTranslationPanelNode { + var dismissedPanelFrame = dismissedTranslationPanelNode.frame + dismissedPanelFrame.origin.y = -dismissedPanelFrame.size.height + transition.updateFrame(node: dismissedTranslationPanelNode, frame: dismissedPanelFrame, completion: { [weak dismissedTranslationPanelNode] _ in + dismissedTranslationPanelNode?.removeFromSupernode() + }) + } + if let dismissedImportStatusPanelNode = dismissedImportStatusPanelNode { var dismissedPanelFrame = dismissedImportStatusPanelNode.frame dismissedPanelFrame.origin.y = -dismissedPanelFrame.size.height diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index e7faec0700..4c04ffeeff 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -22,6 +22,7 @@ import ReactionSelectionNode import ChatPresentationInterfaceState import TelegramNotices import ChatControllerInteraction +import TranslateUI extension ChatReplyThreadMessage { var effectiveTopId: MessageId { @@ -317,7 +318,7 @@ private final class ChatHistoryTransactionOpaqueState { } } -private func extractAssociatedData(chatLocation: ChatLocation, view: MessageHistoryView, automaticDownloadNetworkType: MediaAutoDownloadNetworkType, animatedEmojiStickers: [String: [StickerPackItem]], additionalAnimatedEmojiStickers: [String: [Int: StickerPackItem]], subject: ChatControllerSubject?, currentlyPlayingMessageId: MessageIndex?, isCopyProtectionEnabled: Bool, availableReactions: AvailableReactions?, defaultReaction: MessageReaction.Reaction?, isPremium: Bool, alwaysDisplayTranscribeButton: ChatMessageItemAssociatedData.DisplayTranscribeButton, accountPeer: EnginePeer?, topicAuthorId: EnginePeer.Id?, hasBots: Bool) -> ChatMessageItemAssociatedData { +private func extractAssociatedData(chatLocation: ChatLocation, view: MessageHistoryView, automaticDownloadNetworkType: MediaAutoDownloadNetworkType, animatedEmojiStickers: [String: [StickerPackItem]], additionalAnimatedEmojiStickers: [String: [Int: StickerPackItem]], subject: ChatControllerSubject?, currentlyPlayingMessageId: MessageIndex?, isCopyProtectionEnabled: Bool, availableReactions: AvailableReactions?, defaultReaction: MessageReaction.Reaction?, isPremium: Bool, alwaysDisplayTranscribeButton: ChatMessageItemAssociatedData.DisplayTranscribeButton, accountPeer: EnginePeer?, topicAuthorId: EnginePeer.Id?, hasBots: Bool, translateToLanguage: String?) -> ChatMessageItemAssociatedData { var automaticDownloadPeerId: EnginePeer.Id? var automaticMediaDownloadPeerType: MediaAutoDownloadPeerType = .channel var contactsPeerIds: Set = Set() @@ -369,7 +370,7 @@ private func extractAssociatedData(chatLocation: ChatLocation, view: MessageHist } } - return ChatMessageItemAssociatedData(automaticDownloadPeerType: automaticMediaDownloadPeerType, automaticDownloadPeerId: automaticDownloadPeerId, automaticDownloadNetworkType: automaticDownloadNetworkType, isRecentActions: false, subject: subject, contactsPeerIds: contactsPeerIds, channelDiscussionGroup: channelDiscussionGroup, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, currentlyPlayingMessageId: currentlyPlayingMessageId, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, defaultReaction: defaultReaction, isPremium: isPremium, accountPeer: accountPeer, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, topicAuthorId: topicAuthorId, hasBots: hasBots) + return ChatMessageItemAssociatedData(automaticDownloadPeerType: automaticMediaDownloadPeerType, automaticDownloadPeerId: automaticDownloadPeerId, automaticDownloadNetworkType: automaticDownloadNetworkType, isRecentActions: false, subject: subject, contactsPeerIds: contactsPeerIds, channelDiscussionGroup: channelDiscussionGroup, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, currentlyPlayingMessageId: currentlyPlayingMessageId, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, defaultReaction: defaultReaction, isPremium: isPremium, accountPeer: accountPeer, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, topicAuthorId: topicAuthorId, hasBots: hasBots, translateToLanguage: translateToLanguage) } private extension ChatHistoryLocationInput { @@ -519,6 +520,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { private let messageMentionProcessingManager = ChatMessageThrottledProcessingManager(delay: 0.2) private let unseenReactionsProcessingManager = ChatMessageThrottledProcessingManager(delay: 0.2, submitInterval: 0.0) private let extendedMediaProcessingManager = ChatMessageVisibleThrottledProcessingManager(interval: 5.0) + private let translationProcessingManager = ChatMessageThrottledProcessingManager(submitInterval: 1.0) let prefetchManager: InChatPrefetchManager private var currentEarlierPrefetchMessages: [(Message, Media)] = [] @@ -658,6 +660,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { private let clientId: Atomic + private var toLang: String? + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal), chatLocation: ChatLocation, chatLocationContextHolder: Atomic, tagMask: MessageTags?, source: ChatHistoryListSource = .default, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, selectedMessages: Signal?, NoError>, mode: ChatHistoryListMode = .bubbles, messageTransitionNode: @escaping () -> ChatMessageTransitionNode? = { nil }) { var tagMask = tagMask var appendMessagesFromTheSameGroup = false @@ -787,6 +791,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { self.refreshMediaProcessingManager.process = { [weak context] messageIds in context?.account.viewTracker.refreshSecretMediaMediaForMessageIds(messageIds: messageIds) } + self.translationProcessingManager.process = { [weak self, weak context] messageIds in + if let context = context, let toLang = self?.toLang { + let _ = translateMessageIds(context: context, messageIds: Array(messageIds), toLang: toLang).start() + } + } self.messageMentionProcessingManager.process = { [weak self, weak context] messageIds in if let strongSelf = self { @@ -1109,6 +1118,13 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { self.justSentTextMessagePromise.get() ) + let translationState: Signal + if let peerId = chatLocation.peerId, peerId.namespace == Namespaces.Peer.CloudChannel { + translationState = chatTranslationState(context: context, peerId: peerId) + } else { + translationState = .single(nil) + } + let promises = combineLatest( self.historyAppearsClearedPromise.get(), self.pendingUnpinnedAllMessagesPromise.get(), @@ -1134,8 +1150,9 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { audioTranscriptionSuggestion, promises, topicAuthorId, - self.allAdMessagesPromise.get() - ).start(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, animatedEmojiStickers, additionalAnimatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState, availableReactions, defaultReaction, accountPeer, suggestAudioTranscription, promises, topicAuthorId, allAdMessages in + self.allAdMessagesPromise.get(), + translationState + ).start(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, animatedEmojiStickers, additionalAnimatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState, availableReactions, defaultReaction, accountPeer, suggestAudioTranscription, promises, topicAuthorId, allAdMessages, translationState in let (historyAppearsCleared, pendingUnpinnedAllMessages, pendingRemovedMessages, currentlyPlayingMessageIdAndType, scrollToMessageId, chatHasBots) = promises let currentlyPlayingMessageId = currentlyPlayingMessageIdAndType?.0 @@ -1275,7 +1292,12 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { displayForNotConsumed: suggestAudioTranscription.1 ) - let associatedData = extractAssociatedData(chatLocation: chatLocation, view: view, automaticDownloadNetworkType: networkType, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, subject: subject, currentlyPlayingMessageId: currentlyPlayingMessageId, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, defaultReaction: defaultReaction, isPremium: isPremium, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, accountPeer: accountPeer, topicAuthorId: topicAuthorId, hasBots: chatHasBots) + var translateToLanguage: String? + if let translationState, translationState.isEnabled { + translateToLanguage = translationState.toLang ?? presentationData.strings.baseLanguageCode + } + + let associatedData = extractAssociatedData(chatLocation: chatLocation, view: view, automaticDownloadNetworkType: networkType, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, subject: subject, currentlyPlayingMessageId: currentlyPlayingMessageId, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, defaultReaction: defaultReaction, isPremium: isPremium, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, accountPeer: accountPeer, topicAuthorId: topicAuthorId, hasBots: chatHasBots, translateToLanguage: translateToLanguage) let filteredEntries = chatHistoryEntriesForView( location: chatLocation, @@ -1362,6 +1384,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { var scrollAnimationCurve: ListViewAnimationCurve? = nil if let strongSelf = self, case .default = source { + strongSelf.toLang = translateToLanguage if strongSelf.appliedScrollToMessageId == nil, let scrollToMessageId = scrollToMessageId { updatedScrollPosition = .index(index: .message(scrollToMessageId), position: .center(.top), directionHint: .Up, animated: true, highlight: false, displayLink: true) scrollAnimationCurve = .Spring(duration: 0.4) @@ -2003,6 +2026,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { var messageIdsWithUnseenPersonalMention: [MessageId] = [] var messageIdsWithUnseenReactions: [MessageId] = [] var messageIdsWithInactiveExtendedMedia = Set() + var messageIdsToTranslate: [MessageId] = [] var downloadableResourceIds: [(messageId: MessageId, resourceId: String)] = [] var allVisibleAnchorMessageIds: [(MessageId, Int)] = [] var visibleAdOpaqueIds: [Data] = [] @@ -2170,6 +2194,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } } + let translateToLanguage = transactionState.historyView.associatedData.translateToLanguage var messageIdsWithPossibleReactions: [MessageId] = [] for entry in historyView.filteredEntries { switch entry { @@ -2187,6 +2212,13 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { default: break } + + if let translateToLanguage { + if let translation = message.attributes.first(where: { $0 is TranslationMessageAttribute }) as? TranslationMessageAttribute, translation.toLang == translateToLanguage { + } else { + messageIdsToTranslate.append(message.id) + } + } } case let .MessageGroupEntry(_, messages, _): for (message, _, _, _, _) in messages { @@ -2304,6 +2336,9 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { if !messageIdsWithInactiveExtendedMedia.isEmpty { self.extendedMediaProcessingManager.update(messageIdsWithInactiveExtendedMedia) } + if !messageIdsToTranslate.isEmpty { + self.translationProcessingManager.add(messageIdsToTranslate) + } if !visibleAdOpaqueIds.isEmpty { for opaqueId in visibleAdOpaqueIds { self.markAdAsSeen(opaqueId: opaqueId) diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index 00a2c7b10a..6ff743a4a9 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -210,7 +210,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { statusType = nil } - let rawText: String + var rawText: String var attributedText: NSAttributedString var messageEntities: [MessageTextEntity]? @@ -228,6 +228,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } } + var isTranslating = false if isUnsupportedMedia { rawText = item.presentationData.strings.Conversation_UnsupportedMediaPlaceholder messageEntities = [MessageTextEntity(range: 0.. CGFloat { + let previousIsEnabled = self.chatInterfaceState?.translationState?.isEnabled + self.chatInterfaceState = interfaceState + + var themeUpdated = false + if interfaceState.theme !== self.theme { + themeUpdated = true + self.theme = interfaceState.theme + } + + var isEnabledUpdated = false + if previousIsEnabled != interfaceState.translationState?.isEnabled { + isEnabledUpdated = true + } + + if themeUpdated { + self.buttonIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/Translate"), color: interfaceState.theme.chat.inputPanel.panelControlAccentColor) + self.moreButton.theme = interfaceState.theme + self.separatorNode.backgroundColor = interfaceState.theme.rootController.navigationBar.separatorColor + } + + if themeUpdated || isEnabledUpdated { + var languageCode = interfaceState.strings.baseLanguageCode + let rawSuffix = "-raw" + if languageCode.hasSuffix(rawSuffix) { + languageCode = String(languageCode.dropLast(rawSuffix.count)) + } + let locale = Locale(identifier: languageCode) + let toLang = interfaceState.translationState?.toLang ?? languageCode + let toLanguage: String = locale.localizedString(forLanguageCode: toLang) ?? "" + + let buttonText = interfaceState.translationState?.isEnabled == true ? interfaceState.strings.Conversation_Translation_ShowOriginal : interfaceState.strings.Conversation_Translation_TranslateTo(toLanguage).string + self.buttonTextNode.attributedText = NSAttributedString(string: buttonText, font: Font.regular(17.0), textColor: interfaceState.theme.rootController.navigationBar.accentTextColor) + } + + let panelHeight: CGFloat = 44.0 + + let contentRightInset: CGFloat = 14.0 + rightInset + + let moreButtonSize = self.moreButton.measure(CGSize(width: 100.0, height: panelHeight)) + self.moreButton.frame = CGRect(origin: CGPoint(x: width - contentRightInset - moreButtonSize.width, y: floorToScreenPixels((panelHeight - moreButtonSize.height) / 2.0)), size: moreButtonSize) + + let buttonSpacing: CGFloat = 10.0 + let buttonTextSize = self.buttonTextNode.updateLayout(CGSize(width: width - contentRightInset - moreButtonSize.width, height: panelHeight)) + if let icon = self.buttonIconNode.image { + let buttonSize = CGSize(width: buttonTextSize.width + icon.size.width + buttonSpacing, height: panelHeight) + self.button.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - buttonSize.width) / 2.0), y: 0.0), size: buttonSize) + self.buttonIconNode.frame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((buttonSize.height - icon.size.height) / 2.0)), size: icon.size) + self.buttonTextNode.frame = CGRect(origin: CGPoint(x: icon.size.width + buttonSpacing, y: floorToScreenPixels((buttonSize.height - buttonTextSize.height) / 2.0)), size: buttonTextSize) + } + + transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: UIScreenPixel))) + + return panelHeight + } + + @objc private func buttonPressed() { + guard let translationState = self.chatInterfaceState?.translationState else { + return + } + + self.interfaceInteraction?.toggleTranslation(translationState.isEnabled ? .original : .translated) + } + + @objc private func morePressed(node: ContextReferenceContentNode, gesture: ContextGesture?) { + guard let translationState = self.chatInterfaceState?.translationState else { + return + } + + let context = self.context + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + + var languageCode = presentationData.strings.baseLanguageCode + let rawSuffix = "-raw" + if languageCode.hasSuffix(rawSuffix) { + languageCode = String(languageCode.dropLast(rawSuffix.count)) + } + let locale = Locale(identifier: languageCode) + let fromLanguage: String = locale.localizedString(forLanguageCode: translationState.fromLang) ?? "" + + var items: [ContextMenuItem] = [] + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_Translation_ChooseLanguage, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Translate"), color: theme.contextMenu.primaryColor) + }, action: { c, _ in + var subItems: [ContextMenuItem] = [] + + subItems.append(.action(ContextMenuActionItem(text: presentationData.strings.Common_Back, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) + }, action: { c, _ in + c.popItems() + }))) + subItems.append(.separator) + + let enLocale = Locale(identifier: "en") + var languages: [(String, String, String)] = [] + var addedLanguages = Set() + for code in popularTranslationLanguages { + if let title = enLocale.localizedString(forLanguageCode: code) { + let languageLocale = Locale(identifier: code) + let subtitle = languageLocale.localizedString(forLanguageCode: code) ?? title + let value = (code, title.capitalized, subtitle.capitalized) + if code == languageCode { + languages.insert(value, at: 0) + } else { + languages.append(value) + } + addedLanguages.insert(code) + } + } + +// for code in supportedTranslationLanguages { +// if !addedLanguages.contains(code), let title = enLocale.localizedString(forLanguageCode: code) { +// let languageLocale = Locale(identifier: code) +// let subtitle = languageLocale.localizedString(forLanguageCode: code) ?? title +// let value = (code, title.capitalized, subtitle.capitalized) +// if code == languageCode { +// languages.insert(value, at: 0) +// } else { +// languages.append(value) +// } +// } +// } + + for (langCode, title, _) in languages { + subItems.append(.action(ContextMenuActionItem(text: title , icon: { theme in + if translationState.toLang == langCode { + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) + } else { + return nil + } + }, action: { [weak self] _, f in + f(.default) + + self?.interfaceInteraction?.changeTranslationLanguage(langCode) + }))) + } + + c.pushItems(items: .single(ContextController.Items(content: .list(subItems)))) + }))) + + items.append(.separator) + + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_Translation_DoNotTranslate(fromLanguage).string, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Restrict"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] c, _ in + c.dismiss(completion: nil) + + self?.interfaceInteraction?.addDoNotTranslateLanguage(translationState.fromLang) + }))) + + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_Translation_Hide, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] c, _ in + c.dismiss(completion: nil) + + self?.interfaceInteraction?.hideTranslationPanel() + }))) + + if let controller = self.interfaceInteraction?.chatController() { + let contextController = ContextController(account: self.context.account, presentationData: presentationData, source: .reference(TranslationContextReferenceContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) + self.interfaceInteraction?.presentGlobalOverlayController(contextController, nil) + } + } +} + +private final class TranslationContextReferenceContentSource: ContextReferenceContentSource { + private let controller: ViewController + private let sourceNode: ContextReferenceContentNode + + init(controller: ViewController, sourceNode: ContextReferenceContentNode) { + self.controller = controller + self.sourceNode = sourceNode + } + + func transitionInfo() -> ContextControllerReferenceViewInfo? { + return ContextControllerReferenceViewInfo(referenceView: self.sourceNode.view, contentAreaInScreenSpace: UIScreen.main.bounds) + } +} diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index ec9341bbf6..8131da8fec 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -399,7 +399,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { if peer.isDeleted { overrideImage = .deletedIcon } else if let previousItem = previousItem, item == nil { - if case let .image(_, representations, _, _, _) = previousItem, let rep = representations.last { + if case let .image(_, representations, _, _, _, _) = previousItem, let rep = representations.last { self.removedPhotoResourceIds.insert(rep.representation.resource.id.stringRepresentation) } overrideImage = AvatarNodeImageOverride.none @@ -499,7 +499,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { if let resource = videoRepresentations.first?.representation.resource as? CloudPhotoSizeMediaResource { videoId = videoId &+ resource.photoId } - case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail, _): + case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail, _, _): representations = imageRepresentations videoRepresentations = videoRepresentationsValue immediateThumbnailData = immediateThumbnail @@ -784,7 +784,7 @@ final class PeerInfoEditingAvatarNode: ASDisplayNode { if canEdit, peer.profileImageRepresentations.isEmpty { overrideImage = .editAvatarIcon(forceNone: true) } else if let previousItem = previousItem, item == nil { - if case let .image(_, representations, _, _, _) = previousItem, let rep = representations.last { + if case let .image(_, representations, _, _, _, _) = previousItem, let rep = representations.last { self.removedPhotoResourceIds.insert(rep.representation.resource.id.stringRepresentation) } overrideImage = canEdit ? .editAvatarIcon(forceNone: true) : AvatarNodeImageOverride.none @@ -831,7 +831,7 @@ final class PeerInfoEditingAvatarNode: ASDisplayNode { if let resource = videoRepresentations.first?.representation.resource as? CloudPhotoSizeMediaResource { id = id &+ resource.photoId } - case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail, _): + case let .image(reference, imageRepresentations, videoRepresentationsValue, immediateThumbnail, _, _): representations = imageRepresentations videoRepresentations = videoRepresentationsValue immediateThumbnailData = immediateThumbnail diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 1fb590520c..fc6402548b 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -386,6 +386,10 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode { }, insertText: { _ in }, backwardsDeleteText: { }, restartTopic: { + }, toggleTranslation: { _ in + }, changeTranslationLanguage: { _ in + }, addDoNotTranslateLanguage: { _ in + }, hideTranslationPanel: { }, requestLayout: { _ in }, chatController: { return nil @@ -2023,6 +2027,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate private var forumTopicNotificationExceptions: [EngineMessageHistoryThread.NotificationException] = [] private var forumTopicNotificationExceptionsDisposable: Disposable? + private var translationState: ChatTranslationState? + private var translationStateDisposable: Disposable? + private let _ready = Promise() var ready: Promise { return self._ready @@ -3539,7 +3546,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate var isPersonal = false var currentIsVideo = false let item = strongSelf.headerNode.avatarListNode.listContainerNode.currentItemNode?.item - if let item = item, case let .image(_, representations, videoRepresentations, _, _) = item { + if let item = item, case let .image(_, representations, videoRepresentations, _, _, _) = item { if representations.first?.representation.isPersonal == true { isPersonal = true } @@ -3650,6 +3657,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }) self.refreshMessageTagStatsDisposable = context.engine.messages.refreshMessageTagStats(peerId: peerId, threadId: chatLocation.threadId, tags: [.video, .photo, .gif, .music, .voiceOrInstantVideo, .webPage, .file]).start() + + if peerId.namespace == Namespaces.Peer.CloudChannel { + self.translationStateDisposable = (chatTranslationState(context: context, peerId: peerId) + |> deliverOnMainQueue).start(next: { [weak self] translationState in + self?.translationState = translationState + }) + } } deinit { @@ -3673,6 +3687,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate self.customStatusDisposable?.dispose() self.refreshMessageTagStatsDisposable?.dispose() self.forumTopicNotificationExceptionsDisposable?.dispose() + self.translationStateDisposable?.dispose() self.copyProtectionTooltipController?.dismiss() } @@ -4844,6 +4859,23 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }))) } + if let _ = strongSelf.translationState { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ContextMenuTranslate, icon: { theme in + generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Translate"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] _, f in + f(.dismissWithoutContent) + + if let strongSelf = self { + Queue.mainQueue().after(0.3, { + let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: strongSelf.peerId, { state in + return state?.withIsHidden(false) + }).start() + }) + self?.openChatForTranslation() + } + }))) + } + var canReport = true if channel.adminRights != nil { canReport = false @@ -5191,6 +5223,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } } + private func openChatForTranslation() { + if let peer = self.data?.peer, let navigationController = (self.controller?.navigationController as? NavigationController) { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(EnginePeer(peer)), keepStack: .default, changeColors: false, completion: { _ in + })) + } + } + private func openAutoremove(currentValue: Int32?) { let controller = ChatTimerScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, style: .default, mode: .autoremove, currentTime: currentValue, dismissByTapOutside: true, completion: { [weak self] value in guard let strongSelf = self else { @@ -6824,11 +6863,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate let signal: Signal if self.isSettings { if case .fallback = mode { - signal = self.context.engine.accountData.updateFallbackPhoto(resource: resource, videoResource: nil, videoStartTimestamp: nil, mapResourceToAvatarSizes: { resource, representations in + signal = self.context.engine.accountData.updateFallbackPhoto(resource: resource, videoResource: nil, videoStartTimestamp: nil, fileId: nil, backgroundColors: nil, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) }) } else { - signal = self.context.engine.accountData.updateAccountPhoto(resource: resource, videoResource: nil, videoStartTimestamp: nil, mapResourceToAvatarSizes: { resource, representations in + signal = self.context.engine.accountData.updateAccountPhoto(resource: resource, videoResource: nil, videoStartTimestamp: nil, fileId: nil, backgroundColors: nil, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations) }) } @@ -6887,7 +6926,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate if let strongSelf = self, let peer { switch mode { case .fallback: - (strongSelf.controller?.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: nil, text: strongSelf.presentationData.strings.Privacy_ProfilePhoto_PublicPhotoSuccess, round: true, undo: false), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current) + (strongSelf.controller?.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: nil, text: strongSelf.presentationData.strings.Privacy_ProfilePhoto_PublicPhotoSuccess, round: true, undoText: nil), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current) case .custom: strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, text: strongSelf.presentationData.strings.UserInfo_SetCustomPhoto_SuccessPhotoText(peer.compactDisplayTitle).string, action: nil, duration: 5), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current) @@ -6898,7 +6937,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate })) } case .accept: - (strongSelf.controller?.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: strongSelf.presentationData.strings.Conversation_SuggestedPhotoSuccess, text: strongSelf.presentationData.strings.Conversation_SuggestedPhotoSuccessText, round: true, undo: false), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] action in + (strongSelf.controller?.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: strongSelf.presentationData.strings.Conversation_SuggestedPhotoSuccess, text: strongSelf.presentationData.strings.Conversation_SuggestedPhotoSuccessText, round: true, undoText: nil), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] action in if case .info = action { self?.controller?.parentController?.openSettings() } @@ -7048,12 +7087,14 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate self.updateAvatarDisposable.set((signal |> mapToSignal { videoResource -> Signal in if isSettings { + let fileId = adjustments?.documentId + let backgroundColors = adjustments?.colors as? [Int32] if case .fallback = mode { - return context.engine.accountData.updateFallbackPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in + return context.engine.accountData.updateFallbackPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, fileId: fileId, backgroundColors: backgroundColors, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations) }) } else { - return context.engine.accountData.updateAccountPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mapResourceToAvatarSizes: { resource, representations in + return context.engine.accountData.updateAccountPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, fileId: nil, backgroundColors: nil, mapResourceToAvatarSizes: { resource, representations in return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations) }) } @@ -7093,7 +7134,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate if let strongSelf = self, let peer { switch mode { case .fallback: - (strongSelf.controller?.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: nil, text: strongSelf.presentationData.strings.Privacy_ProfilePhoto_PublicVideoSuccess, round: true, undo: false), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current) + (strongSelf.controller?.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: nil, text: strongSelf.presentationData.strings.Privacy_ProfilePhoto_PublicVideoSuccess, round: true, undoText: nil), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current) case .custom: strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .invitedToVoiceChat(context: strongSelf.context, peer: peer, text: strongSelf.presentationData.strings.UserInfo_SetCustomPhoto_SuccessVideoText(peer.compactDisplayTitle).string, action: nil, duration: 5), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current) @@ -7104,7 +7145,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate })) } case .accept: - (strongSelf.controller?.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: strongSelf.presentationData.strings.Conversation_SuggestedVideoSuccess, text: strongSelf.presentationData.strings.Conversation_SuggestedVideoSuccessText, round: true, undo: false), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] action in + (strongSelf.controller?.parentController?.topViewController as? ViewController)?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .image(image: image, title: strongSelf.presentationData.strings.Conversation_SuggestedVideoSuccess, text: strongSelf.presentationData.strings.Conversation_SuggestedVideoSuccessText, round: true, undoText: nil), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] action in if case .info = action { self?.controller?.parentController?.openSettings() } @@ -7125,9 +7166,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } var currentIsVideo = false + var emojiMarkup: TelegramMediaImage.EmojiMarkup? let item = self.headerNode.avatarListNode.listContainerNode.currentItemNode?.item - if let item = item, case let .image(_, _, videoRepresentations, _, _) = item { + if let item = item, case let .image(_, _, videoRepresentations, _, _, emojiMarkupValue) = item { currentIsVideo = !videoRepresentations.isEmpty + emojiMarkup = emojiMarkupValue } let peerId = self.peerId @@ -7221,7 +7264,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate return } - let controller = AvatarEditorScreen(context: strongSelf.context) + let controller = AvatarEditorScreen(context: strongSelf.context, initialFileId: emojiMarkup?.fileId, initialBackgroundColors: emojiMarkup?.backgroundColors) controller.completion = completion (strongSelf.controller?.navigationController?.topViewController as? ViewController)?.push(controller) } diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index a7f3d28bb8..12cc9148d1 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -455,6 +455,10 @@ final class PeerSelectionControllerNode: ASDisplayNode { }, insertText: { _ in }, backwardsDeleteText: { }, restartTopic: { + }, toggleTranslation: { _ in + }, changeTranslationLanguage: { _ in + }, addDoNotTranslateLanguage: { _ in + }, hideTranslationPanel: { }, requestLayout: { _ in }, chatController: { return nil @@ -1062,41 +1066,45 @@ final class PeerSelectionControllerNode: ASDisplayNode { func stringForAdminRights(strings: PresentationStrings, adminRights: TelegramChatAdminRights) -> String { var rights: [String] = [] + func append(_ string: String) { + rights.append("• \(string)") + } + if adminRights.rights.contains(.canChangeInfo) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_Info) + append(strings.RequestPeer_Requirement_Group_Rights_Info) } if adminRights.rights.contains(.canPostMessages) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_Send) + append(strings.RequestPeer_Requirement_Group_Rights_Send) } if adminRights.rights.contains(.canDeleteMessages) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_Delete) + append(strings.RequestPeer_Requirement_Group_Rights_Delete) } if adminRights.rights.contains(.canEditMessages) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_Edit) + append(strings.RequestPeer_Requirement_Group_Rights_Edit) } if adminRights.rights.contains(.canBanUsers) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_Ban) + append(strings.RequestPeer_Requirement_Group_Rights_Ban) } if adminRights.rights.contains(.canInviteUsers) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_Invite) + append(strings.RequestPeer_Requirement_Group_Rights_Invite) } if adminRights.rights.contains(.canPinMessages) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_Pin) + append(strings.RequestPeer_Requirement_Group_Rights_Pin) } if adminRights.rights.contains(.canManageTopics) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_Topics) + append(strings.RequestPeer_Requirement_Group_Rights_Topics) } if adminRights.rights.contains(.canManageCalls) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_VideoChats) + append(strings.RequestPeer_Requirement_Group_Rights_VideoChats) } if adminRights.rights.contains(.canBeAnonymous) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_Anonymous) + append(strings.RequestPeer_Requirement_Group_Rights_Anonymous) } if adminRights.rights.contains(.canAddAdmins) { - rights.append(strings.RequestPeer_Requirement_Group_Rights_AddAdmins) + append(strings.RequestPeer_Requirement_Group_Rights_AddAdmins) } if !rights.isEmpty { - return String(rights.joined(separator: ", ")) + return String(rights.joined(separator: "\n")) } else { return "" } diff --git a/submodules/TelegramUI/Sources/ShimmeringLinkNode.swift b/submodules/TelegramUI/Sources/ShimmeringLinkNode.swift new file mode 100644 index 0000000000..790633cf21 --- /dev/null +++ b/submodules/TelegramUI/Sources/ShimmeringLinkNode.swift @@ -0,0 +1,99 @@ +import Foundation +import UIKit +import AsyncDisplayKit +import Display +import ShimmerEffect + +final class ShimmeringLinkNode: ASDisplayNode { + private let shimmerEffectNode: ShimmerEffectForegroundNode + private let borderShimmerEffectNode: ShimmerEffectForegroundNode + + private let maskNode: ASImageNode + private let borderMaskNode: ASImageNode + + private(set) var rects: [CGRect] = [] + var color: UIColor { + didSet { + self.backgroundColor = color + } + } + + var innerRadius: CGFloat = 4.0 + var outerRadius: CGFloat = 4.0 + var inset: CGFloat = 2.0 + + init(color: UIColor) { + self.color = color + + self.shimmerEffectNode = ShimmerEffectForegroundNode() + self.borderShimmerEffectNode = ShimmerEffectForegroundNode() + + self.maskNode = ASImageNode() + self.maskNode.displaysAsynchronously = false + self.maskNode.displayWithoutProcessing = true + + self.borderMaskNode = ASImageNode() + self.borderMaskNode.displaysAsynchronously = false + self.borderMaskNode.displayWithoutProcessing = true + + super.init() + + self.isLayerBacked = true + + self.shimmerEffectNode.backgroundColor = color.withAlphaComponent(color.alpha * 0.6) + + self.addSubnode(self.shimmerEffectNode) + //self.addSubnode(self.borderShimmerEffectNode) + } + + override func didLoad() { + super.didLoad() + + self.shimmerEffectNode.layer.mask = self.maskNode.layer + self.borderShimmerEffectNode.layer.mask = self.borderMaskNode.layer + } + + func updateRects(_ rects: [CGRect], color: UIColor? = nil) { + var updated = false + if self.rects != rects { + updated = true + self.rects = rects + } + + if let color, !color.isEqual(self.color) { + updated = true + self.color = color + } + + if updated { + self.updateMasks() + } + } + + private func updateMasks() { + let (offset, image) = generateRectsImage(color: .white, rects: self.rects, inset: self.inset, outerRadius: self.outerRadius, innerRadius: self.innerRadius, useModernPathCalculation: true) + + let (borderOffset, borderImage) = generateRectsImage(color: .white, rects: self.rects.map { $0.insetBy(dx: 0.0, dy: 0.0) }, inset: self.inset, outerRadius: self.outerRadius, innerRadius: self.innerRadius, stroke: true, useModernPathCalculation: true) + + if let image = image { + self.maskNode.frame = CGRect(origin: offset, size: image.size) + self.maskNode.image = image + } + + if let borderImage = borderImage { + self.borderMaskNode.frame = CGRect(origin: borderOffset, size: borderImage.size) + self.borderMaskNode.image = borderImage + } + } + + func updateLayout(_ size: CGSize) { + self.shimmerEffectNode.frame = CGRect(origin: .zero, size: size) + self.borderShimmerEffectNode.frame = CGRect(origin: .zero, size: size) + + self.shimmerEffectNode.updateAbsoluteRect(CGRect(origin: .zero, size: size), within: size) + self.borderShimmerEffectNode.updateAbsoluteRect(CGRect(origin: .zero, size: size), within: size) + + self.shimmerEffectNode.update(backgroundColor: .clear, foregroundColor: self.color.withAlphaComponent(min(1.0, self.color.alpha * 1.2)), horizontal: true, effectSize: nil, globalTimeOffset: false, duration: nil) + self.borderShimmerEffectNode.update(backgroundColor: .clear, foregroundColor: self.color.withAlphaComponent(min(1.0, self.color.alpha * 1.5)), horizontal: true, effectSize: nil, globalTimeOffset: false, duration: nil) + } +} diff --git a/submodules/TranslateUI/BUILD b/submodules/TranslateUI/BUILD index 537f55593b..e96f5e190c 100644 --- a/submodules/TranslateUI/BUILD +++ b/submodules/TranslateUI/BUILD @@ -13,6 +13,7 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", + "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/AccountContext:AccountContext", diff --git a/submodules/TranslateUI/Sources/ChatTranslation.swift b/submodules/TranslateUI/Sources/ChatTranslation.swift new file mode 100644 index 0000000000..6f7289a4b2 --- /dev/null +++ b/submodules/TranslateUI/Sources/ChatTranslation.swift @@ -0,0 +1,224 @@ +import Foundation +import NaturalLanguage +import SwiftSignalKit +import TelegramCore +import Postbox +import AccountContext +import TelegramUIPreferences + +public struct ChatTranslationState: Codable { + enum CodingKeys: String, CodingKey { + case baseLang + case fromLang + case forcedFromLang + case toLang + case isEnabled + case isHidden + } + + public let baseLang: String + public let fromLang: String + public let forcedFromLang: String? + public let toLang: String? + public let isEnabled: Bool + public let isHidden: Bool? + + public init( + baseLang: String, + fromLang: String, + forcedFromLang: String?, + toLang: String?, + isEnabled: Bool, + isHidden: Bool? + ) { + self.baseLang = baseLang + self.fromLang = fromLang + self.forcedFromLang = forcedFromLang + self.toLang = toLang + self.isEnabled = isEnabled + self.isHidden = isHidden + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + self.baseLang = try container.decode(String.self, forKey: .baseLang) + self.fromLang = try container.decode(String.self, forKey: .fromLang) + self.forcedFromLang = try container.decodeIfPresent(String.self, forKey: .forcedFromLang) + self.toLang = try container.decodeIfPresent(String.self, forKey: .toLang) + self.isEnabled = try container.decode(Bool.self, forKey: .isEnabled) + self.isHidden = try container.decodeIfPresent(Bool.self, forKey: .isHidden) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(self.baseLang, forKey: .baseLang) + try container.encode(self.fromLang, forKey: .fromLang) + try container.encodeIfPresent(self.forcedFromLang, forKey: .forcedFromLang) + try container.encodeIfPresent(self.toLang, forKey: .toLang) + try container.encode(self.isEnabled, forKey: .isEnabled) + try container.encodeIfPresent(self.isHidden, forKey: .isHidden) + } + + public func withToLang(_ toLang: String?) -> ChatTranslationState { + return ChatTranslationState( + baseLang: self.baseLang, + fromLang: self.fromLang, + forcedFromLang: self.forcedFromLang, + toLang: toLang, + isEnabled: self.isEnabled, + isHidden: self.isHidden + ) + } + + public func withIsEnabled(_ isEnabled: Bool) -> ChatTranslationState { + return ChatTranslationState( + baseLang: self.baseLang, + fromLang: self.fromLang, + forcedFromLang: self.forcedFromLang, + toLang: self.toLang, + isEnabled: isEnabled, + isHidden: self.isHidden + ) + } + + public func withIsHidden(_ isHidden: Bool) -> ChatTranslationState { + return ChatTranslationState( + baseLang: self.baseLang, + fromLang: self.fromLang, + forcedFromLang: self.forcedFromLang, + toLang: self.toLang, + isEnabled: self.isEnabled, + isHidden: isHidden + ) + } +} + +private func cachedChatTranslationState(engine: TelegramEngine, peerId: EnginePeer.Id) -> Signal { + let key = ValueBoxKey(length: 8) + key.setInt64(0, value: peerId.id._internalGetInt64Value()) + + return engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.translationState, id: key)) + |> map { entry -> ChatTranslationState? in + return entry?.get(ChatTranslationState.self) + } +} + +private func updateChatTranslationState(engine: TelegramEngine, peerId: EnginePeer.Id, state: ChatTranslationState?) -> Signal { + let key = ValueBoxKey(length: 8) + key.setInt64(0, value: peerId.id._internalGetInt64Value()) + + if let state { + return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.translationState, id: key, item: state) + } else { + return engine.itemCache.remove(collectionId: ApplicationSpecificItemCacheCollectionId.translationState, id: key) + } +} + +public func updateChatTranslationStateInteractively(engine: TelegramEngine, peerId: EnginePeer.Id, _ f: @escaping (ChatTranslationState?) -> ChatTranslationState?) -> Signal { + let key = ValueBoxKey(length: 8) + key.setInt64(0, value: peerId.id._internalGetInt64Value()) + + return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.translationState, id: key)) + |> map { entry -> ChatTranslationState? in + return entry?.get(ChatTranslationState.self) + } + |> mapToSignal { current -> Signal in + if let current { + return updateChatTranslationState(engine: engine, peerId: peerId, state: f(current)) + } else { + return .never() + } + } +} + + +@available(iOS 12.0, *) +private let languageRecognizer = NLLanguageRecognizer() + +public func translateMessageIds(context: AccountContext, messageIds: [EngineMessage.Id], toLang: String) -> Signal { + return context.account.postbox.transaction { transaction -> Signal in + var messageIdsToTranslate: [EngineMessage.Id] = [] + for messageId in messageIds { + if let message = transaction.getMessage(messageId), let translation = message.attributes.first(where: { $0 is TranslationMessageAttribute }) as? TranslationMessageAttribute, translation.toLang == toLang { + } else { + messageIdsToTranslate.append(messageId) + } + } + return context.engine.messages.translateMessages(messageIds: messageIdsToTranslate, toLang: toLang) + } |> switchToLatest +} + +public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id) -> Signal { + if #available(iOS 12.0, *) { + let baseLang = context.sharedContext.currentPresentationData.with { $0 }.strings.baseLanguageCode + return cachedChatTranslationState(engine: context.engine, peerId: peerId) + |> mapToSignal { cached in + if let cached, cached.baseLang == baseLang { + return .single(cached) + } else { + return .single(nil) + |> then( + context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings]) + |> mapToSignal { sharedData in + let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.translationSettings]?.get(TranslationSettings.self) ?? TranslationSettings.defaultSettings + + var dontTranslateLanguages: [String] = [] + if let ignoredLanguages = settings.ignoredLanguages { + dontTranslateLanguages = ignoredLanguages + } else { + dontTranslateLanguages = [baseLang] + } + + return context.account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId: peerId, threadId: nil), index: .upperBound, anchorIndex: .upperBound, count: 10, fixedCombinedReadStates: nil) + |> filter { messageHistoryView -> Bool in + return messageHistoryView.0.entries.count > 1 + } + |> take(1) + |> map { messageHistoryView, _, _ -> ChatTranslationState in + let messages = messageHistoryView.entries.map(\.message) + + var fromLangs: [String: Int] = [:] + var count = 0 + for message in messages { + if message.text.count > 10 { + let text = String(message.text.prefix(64)) + languageRecognizer.processString(text) + let hypotheses = languageRecognizer.languageHypotheses(withMaximum: 3) + languageRecognizer.reset() + + let filteredLanguages = hypotheses.filter { supportedTranslationLanguages.contains($0.key.rawValue) }.sorted(by: { $0.value > $1.value }) + if let language = filteredLanguages.first(where: { supportedTranslationLanguages.contains($0.key.rawValue) }), !dontTranslateLanguages.contains(language.key.rawValue) { + let fromLang = language.key.rawValue + fromLangs[fromLang] = (fromLangs[fromLang] ?? 0) + 1 + } + count += 1 + } + + if count >= 5 { + break + } + } + + var mostFrequent: (String, Int)? + for (lang, count) in fromLangs { + if let current = mostFrequent, count > current.1 { + mostFrequent = (lang, count) + } else { + mostFrequent = (lang, count) + } + } + let fromLang = mostFrequent?.0 ?? "" + let state = ChatTranslationState(baseLang: baseLang, fromLang: fromLang, forcedFromLang: nil, toLang: nil, isEnabled: false, isHidden: false) + let _ = updateChatTranslationState(engine: context.engine, peerId: peerId, state: state).start() + return state + } + } + ) + } + } + } else { + return .single(nil) + } +} diff --git a/submodules/TranslateUI/Sources/Translate.swift b/submodules/TranslateUI/Sources/Translate.swift index b7ba2f43e8..88e7bdd4a4 100644 --- a/submodules/TranslateUI/Sources/Translate.swift +++ b/submodules/TranslateUI/Sources/Translate.swift @@ -127,7 +127,6 @@ public var popularTranslationLanguages = [ "en", "ar", "zh", -// "zh-Hant", "fr", "de", "it", @@ -135,7 +134,8 @@ public var popularTranslationLanguages = [ "ko", "pt", "ru", - "es" + "es", + "uk" ] @available(iOS 12.0, *) diff --git a/submodules/UndoUI/Sources/UndoOverlayController.swift b/submodules/UndoUI/Sources/UndoOverlayController.swift index da49acb4a5..13392ae062 100644 --- a/submodules/UndoUI/Sources/UndoOverlayController.swift +++ b/submodules/UndoUI/Sources/UndoOverlayController.swift @@ -39,7 +39,7 @@ public enum UndoOverlayContent { case mediaSaved(text: String) case paymentSent(currencyValue: String, itemTitle: String) case inviteRequestSent(title: String, text: String) - case image(image: UIImage, title: String?, text: String, round: Bool, undo: Bool) + case image(image: UIImage, title: String?, text: String, round: Bool, undoText: String?) case notificationSoundAdded(title: String, text: String, action: (() -> Void)?) case universal(animation: String, scale: CGFloat, colors: [String: UIColor], title: String?, text: String, customUndoText: String?) case peers(context: AccountContext, peers: [EnginePeer], title: String?, text: String, customUndoText: String?) diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index 361ca0493a..0b00c2c95f 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -860,7 +860,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { } else { displayUndo = false } - case let .image(image, title, text, round, undo): + case let .image(image, title, text, round, customUndoText): self.avatarNode = nil self.iconNode = ASImageNode() self.iconNode?.clipsToBounds = true @@ -885,8 +885,13 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { }), textAlignment: .natural) self.textNode.attributedText = attributedText - displayUndo = undo - self.originalRemainingSeconds = undo ? 5 : 3 + if let customUndoText = customUndoText { + undoText = customUndoText + displayUndo = true + } else { + displayUndo = false + } + self.originalRemainingSeconds = displayUndo ? 5 : 3 if text.contains("](") { isUserInteractionEnabled = true From 86ee12c1c89cd9f1f65ff7aafcfe3c61ad6b0ca7 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 18 Jan 2023 16:11:11 +0400 Subject: [PATCH 02/10] Various fixes --- .../Telegram-iOS/Base.lproj/LaunchScreen.xib | 14 +- .../Resources/intro/telegram_sphere@2x.png | Bin 9153 -> 7872 bytes ...ationSequenceCodeEntryControllerNode.swift | 2 +- ...tionSequencePhoneEntryControllerNode.swift | 7 +- .../Sources/ChatListController.swift | 12 +- submodules/Display/Source/TextFieldNode.swift | 6 +- .../Sources/DrawingStickerEntity.swift | 2 +- .../Sources/StickerPickerScreen.swift | 19 +- .../Sources/LegacyPaintStickersContext.swift | 7 +- .../Sources/PhoneInputNode.swift | 2 - .../platform/ios/RMIntroViewController.m | 2 +- submodules/TelegramApi/Sources/Api0.swift | 7 + submodules/TelegramApi/Sources/Api26.swift | 156 +++++++---------- submodules/TelegramApi/Sources/Api27.swift | 162 +++++++++++------- submodules/TelegramApi/Sources/Api28.swift | 64 +++++++ submodules/TelegramApi/Sources/Api30.swift | 50 +++++- submodules/TelegramApi/Sources/Api5.swift | 94 +++++----- submodules/TelegramApi/Sources/Api6.swift | 44 +++++ .../Peers/PeerPhotoUpdater.swift | 4 +- .../Sources/AvatarEditorScreen.swift | 21 ++- .../Sources/AvatarPreviewComponent.swift | 5 + .../LaunchLogo.imageset/Contents.json | 22 +++ .../LaunchLogo.imageset/LaunchLogo@2x.png | Bin 0 -> 7927 bytes .../LaunchLogo.imageset/LaunchLogo@3x.png | Bin 0 -> 12725 bytes .../TelegramUI/Sources/AppDelegate.swift | 4 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 2 +- 26 files changed, 468 insertions(+), 240 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Components/LaunchLogo.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Components/LaunchLogo.imageset/LaunchLogo@2x.png create mode 100644 submodules/TelegramUI/Images.xcassets/Components/LaunchLogo.imageset/LaunchLogo@3x.png diff --git a/Telegram/Telegram-iOS/Base.lproj/LaunchScreen.xib b/Telegram/Telegram-iOS/Base.lproj/LaunchScreen.xib index 2e8de3f955..c8bc1ddd72 100644 --- a/Telegram/Telegram-iOS/Base.lproj/LaunchScreen.xib +++ b/Telegram/Telegram-iOS/Base.lproj/LaunchScreen.xib @@ -1,6 +1,6 @@ - + @@ -10,14 +10,14 @@ - + - - + + - - + + @@ -30,7 +30,7 @@ - + diff --git a/Telegram/Telegram-iOS/Resources/intro/telegram_sphere@2x.png b/Telegram/Telegram-iOS/Resources/intro/telegram_sphere@2x.png index 5048850c0ba9310ad063f19387c19df0ba71ca2b..826d68b263e7fed924f965fec089733cc2d96594 100644 GIT binary patch literal 7872 zcmbVx2{@Ep*#A5;7`tR&6IrtiGqypE7?hJ6E)42sEC86-=M zlvfOZ)W zXzXEvVNwhkL_;9fyOYSlAyEXX+F?Ri1j$ByrR%o3T12Rgy0@t-!j)`C2#;_|i6
    0*$mpqfl!9{M5na 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 diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift index 4e3badd9bc..7fe7482657 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift @@ -414,7 +414,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF prefix: codePrefix, count: codeLength, width: maximumWidth - 28.0, - compact: layout.size.width <= 320.0 + compact: layout.size.width <= 320.0 || (layout.size.width <= 375.0 && codeLength > 5) ) var items: [AuthorizationLayoutItem] = [] diff --git a/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift b/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift index baf313b0fc..aaf572aa59 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationSequencePhoneEntryControllerNode.swift @@ -968,7 +968,12 @@ final class PhoneConfirmationController: ViewController { if case .regular = layout.metrics.widthClass { originY = floorToScreenPixels((layout.size.height - backgroundSize.height) / 2.0) } else { - originY = layout.size.height - backgroundSize.height - 260.0 + let hasOnScreenNavigation = layout.deviceMetrics.onScreenNavigationHeight(inLandscape: false, systemOnScreenNavigationHeight: nil) != nil + if hasOnScreenNavigation || layout.deviceMetrics.hasTopNotch || layout.deviceMetrics.hasDynamicIsland { + originY = layout.size.height - backgroundSize.height - 260.0 + } else { + originY = floorToScreenPixels((layout.size.height - backgroundSize.height) / 2.0) + } } let backgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - backgroundSize.width) / 2.0), y: originY), size: backgroundSize) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index c0f5faa412..0bb0ea591e 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -2131,12 +2131,20 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } @objc fileprivate func reorderingDonePressed() { - if !self.chatListDisplayNode.isReorderingFilters { + guard let defaultFilters = self.tabContainerData else { return } + let defaultFilterIds = defaultFilters.0.compactMap { entry -> Int32? in + switch entry { + case .all: + return 0 + case let .filter(id, _, _): + return id + } + } var reorderedFilterIdsValue: [Int32]? - if let reorderedFilterIds = self.tabContainerNode.reorderedFilterIds { + if let reorderedFilterIds = self.tabContainerNode.reorderedFilterIds, reorderedFilterIds != defaultFilterIds { reorderedFilterIdsValue = reorderedFilterIds } diff --git a/submodules/Display/Source/TextFieldNode.swift b/submodules/Display/Source/TextFieldNode.swift index 6908acface..a111b12442 100644 --- a/submodules/Display/Source/TextFieldNode.swift +++ b/submodules/Display/Source/TextFieldNode.swift @@ -8,15 +8,15 @@ public final class TextFieldNodeView: UITextField { var fixOffset: Bool = true override public func editingRect(forBounds bounds: CGRect) -> CGRect { - return bounds.offsetBy(dx: 0.0, dy: 0.0).integral + return bounds.integral } override public func textRect(forBounds bounds: CGRect) -> CGRect { - return bounds.offsetBy(dx: 0.0, dy: 0.0).integral + return bounds.integral } override public func placeholderRect(forBounds bounds: CGRect) -> CGRect { - return self.editingRect(forBounds: bounds.offsetBy(dx: 0.0, dy: 0.0)) + return self.editingRect(forBounds: bounds) } override public func deleteBackward() { diff --git a/submodules/DrawingUI/Sources/DrawingStickerEntity.swift b/submodules/DrawingUI/Sources/DrawingStickerEntity.swift index 55332c1705..1d22294a9d 100644 --- a/submodules/DrawingUI/Sources/DrawingStickerEntity.swift +++ b/submodules/DrawingUI/Sources/DrawingStickerEntity.swift @@ -48,7 +48,7 @@ public final class DrawingStickerEntity: DrawingEntity, Codable { public var isAnimated: Bool { switch self.content { case let .file(file): - return file.isAnimatedSticker || file.isVideoSticker + return file.isAnimatedSticker || file.isVideoSticker || file.mimeType == "video/webm" case .image: return false } diff --git a/submodules/DrawingUI/Sources/StickerPickerScreen.swift b/submodules/DrawingUI/Sources/StickerPickerScreen.swift index fc76d525f9..67d4c400f2 100644 --- a/submodules/DrawingUI/Sources/StickerPickerScreen.swift +++ b/submodules/DrawingUI/Sources/StickerPickerScreen.swift @@ -318,11 +318,24 @@ class StickerPickerScreen: ViewController { guard let strongSelf = self, let controller = strongSelf.controller else { return } - if groupId == AnyHashable("popular") { - let presentationData = controller.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkColorPresentationTheme) + let presentationData = controller.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkColorPresentationTheme) + let context = controller.context + if groupId == AnyHashable("recent") { + let actionSheet = ActionSheetController(theme: ActionSheetControllerTheme(presentationTheme: presentationData.theme, fontSize: presentationData.listsFontSize)) + var items: [ActionSheetItem] = [] + items.append(ActionSheetButtonItem(title: presentationData.strings.Emoji_ClearRecent, color: .destructive, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + let _ = context.engine.stickers.clearRecentlyUsedEmoji().start() + })) + actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ])]) + context.sharedContext.mainWindow?.presentInGlobalOverlay(actionSheet) + } else if groupId == AnyHashable("popular") { let actionSheet = ActionSheetController(theme: ActionSheetControllerTheme(presentationTheme: presentationData.theme, fontSize: presentationData.listsFontSize)) var items: [ActionSheetItem] = [] - let context = controller.context items.append(ActionSheetTextItem(title: presentationData.strings.Chat_ClearReactionsAlertText, parseMarkdown: true)) items.append(ActionSheetButtonItem(title: presentationData.strings.Chat_ClearReactionsAlertAction, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift index f0533842ef..65841ad319 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift @@ -101,7 +101,7 @@ private class LegacyPaintStickerEntity: LegacyPaintEntity { case let .file(file): self.file = file if file.isAnimatedSticker || file.isVideoSticker || file.mimeType == "video/webm" { - self.source = AnimatedStickerResourceSource(account: account, resource: file.resource, isVideo: file.isVideoSticker) + self.source = AnimatedStickerResourceSource(account: account, resource: file.resource, isVideo: file.isVideoSticker || file.mimeType == "video/webm") if let source = self.source { let dimensions = file.dimensions ?? PixelDimensions(width: 512, height: 512) let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 384, height: 384)) @@ -406,10 +406,13 @@ public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRender private let originalSize: CGSize private let cropRect: CGRect? + private let isAvatar: Bool + public init(account: Account?, adjustments: TGMediaEditAdjustments) { self.account = account self.originalSize = adjustments.originalSize self.cropRect = adjustments.cropRect.isEmpty ? nil : adjustments.cropRect + self.isAvatar = ((adjustments as? TGVideoEditAdjustments)?.documentId ?? 0) != 0 var renderEntities: [LegacyPaintEntity] = [] if let account = account, let paintingData = adjustments.paintingData, let entitiesData = paintingData.entitiesData { @@ -477,7 +480,7 @@ public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRender } else { result = minDuration } - if result < minDuration { + if result < minDuration && !self.isAvatar { if result > 0 { result = result * ceil(minDuration / result) } else { diff --git a/submodules/PhoneInputNode/Sources/PhoneInputNode.swift b/submodules/PhoneInputNode/Sources/PhoneInputNode.swift index 2b5283a3e4..76b745cd23 100644 --- a/submodules/PhoneInputNode/Sources/PhoneInputNode.swift +++ b/submodules/PhoneInputNode/Sources/PhoneInputNode.swift @@ -198,7 +198,6 @@ public final class PhoneInputNode: ASDisplayNode, UITextFieldDelegate { self.countryCodeField.textField.returnKeyType = .next if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { self.countryCodeField.textField.keyboardType = .asciiCapableNumberPad -// self.countryCodeField.textField.textContentType = .telephoneNumber } else { self.countryCodeField.textField.keyboardType = .numberPad } @@ -209,7 +208,6 @@ public final class PhoneInputNode: ASDisplayNode, UITextFieldDelegate { self.numberField.textField.font = font if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { self.numberField.textField.keyboardType = .asciiCapableNumberPad -// self.numberField.textField.textContentType = .telephoneNumber } else { self.numberField.textField.keyboardType = .numberPad } diff --git a/submodules/RMIntro/Sources/platform/ios/RMIntroViewController.m b/submodules/RMIntro/Sources/platform/ios/RMIntroViewController.m index 4e8be0d8df..249ca084ca 100644 --- a/submodules/RMIntro/Sources/platform/ios/RMIntroViewController.m +++ b/submodules/RMIntro/Sources/platform/ios/RMIntroViewController.m @@ -243,7 +243,7 @@ typedef enum { CGPoint buttonTargetPosition = _startButton.center; _startButton.center = CGPointMake(buttonTargetPosition.x, buttonTargetPosition.y + 220.0); - _glkView.transform = CGAffineTransformMakeScale(0.68, 0.68); + _glkView.transform = CGAffineTransformMakeScale(0.66, 0.66); [UIView animateWithDuration:0.65 delay:0.15 usingSpringWithDamping:1.2f initialSpringVelocity:0.0 options:kNilOptions animations:^{ _glkView.center = logoTargetPosition; diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index cee0bc09a6..4de19de1e5 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -207,6 +207,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1383932651] = { return Api.EmailVerifyPurpose.parse_emailVerifyPurposeLoginChange($0) } dict[1128644211] = { return Api.EmailVerifyPurpose.parse_emailVerifyPurposeLoginSetup($0) } dict[-1141565819] = { return Api.EmailVerifyPurpose.parse_emailVerifyPurposePassport($0) } + dict[2056961449] = { return Api.EmojiGroup.parse_emojiGroup($0) } dict[-709641735] = { return Api.EmojiKeyword.parse_emojiKeyword($0) } dict[594408994] = { return Api.EmojiKeyword.parse_emojiKeywordDeleted($0) } dict[1556570557] = { return Api.EmojiKeywordsDifference.parse_emojiKeywordsDifference($0) } @@ -1031,6 +1032,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-253500010] = { return Api.messages.Dialogs.parse_dialogsNotModified($0) } dict[1910543603] = { return Api.messages.Dialogs.parse_dialogsSlice($0) } dict[-1506535550] = { return Api.messages.DiscussionMessage.parse_discussionMessage($0) } + dict[-2011186869] = { return Api.messages.EmojiGroups.parse_emojiGroups($0) } + dict[1874111879] = { return Api.messages.EmojiGroups.parse_emojiGroupsNotModified($0) } dict[410107472] = { return Api.messages.ExportedChatInvite.parse_exportedChatInvite($0) } dict[572915951] = { return Api.messages.ExportedChatInvite.parse_exportedChatInviteReplaced($0) } dict[-1111085620] = { return Api.messages.ExportedChatInvites.parse_exportedChatInvites($0) } @@ -1295,6 +1298,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.EmailVerifyPurpose: _1.serialize(buffer, boxed) + case let _1 as Api.EmojiGroup: + _1.serialize(buffer, boxed) case let _1 as Api.EmojiKeyword: _1.serialize(buffer, boxed) case let _1 as Api.EmojiKeywordsDifference: @@ -1823,6 +1828,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.messages.DiscussionMessage: _1.serialize(buffer, boxed) + case let _1 as Api.messages.EmojiGroups: + _1.serialize(buffer, boxed) case let _1 as Api.messages.ExportedChatInvite: _1.serialize(buffer, boxed) case let _1 as Api.messages.ExportedChatInvites: diff --git a/submodules/TelegramApi/Sources/Api26.swift b/submodules/TelegramApi/Sources/Api26.swift index f7e40833c8..8ad3ca293a 100644 --- a/submodules/TelegramApi/Sources/Api26.swift +++ b/submodules/TelegramApi/Sources/Api26.swift @@ -800,6 +800,64 @@ public extension Api.messages { } } +public extension Api.messages { + enum EmojiGroups: TypeConstructorDescription { + case emojiGroups(hash: Int32, groups: [Api.EmojiGroup]) + case emojiGroupsNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .emojiGroups(let hash, let groups): + if boxed { + buffer.appendInt32(-2011186869) + } + serializeInt32(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(groups.count)) + for item in groups { + item.serialize(buffer, true) + } + break + case .emojiGroupsNotModified: + if boxed { + buffer.appendInt32(1874111879) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .emojiGroups(let hash, let groups): + return ("emojiGroups", [("hash", hash as Any), ("groups", groups as Any)]) + case .emojiGroupsNotModified: + return ("emojiGroupsNotModified", []) + } + } + + public static func parse_emojiGroups(_ reader: BufferReader) -> EmojiGroups? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.EmojiGroup]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.EmojiGroup.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.EmojiGroups.emojiGroups(hash: _1!, groups: _2!) + } + else { + return nil + } + } + public static func parse_emojiGroupsNotModified(_ reader: BufferReader) -> EmojiGroups? { + return Api.messages.EmojiGroups.emojiGroupsNotModified + } + + } +} public extension Api.messages { enum ExportedChatInvite: TypeConstructorDescription { case exportedChatInvite(invite: Api.ExportedChatInvite, users: [Api.User]) @@ -1364,101 +1422,3 @@ public extension Api.messages { } } -public extension Api.messages { - enum InactiveChats: TypeConstructorDescription { - case inactiveChats(dates: [Int32], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inactiveChats(let dates, let chats, let users): - if boxed { - buffer.appendInt32(-1456996667) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(dates.count)) - for item in dates { - serializeInt32(item, buffer: buffer, boxed: false) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inactiveChats(let dates, let chats, let users): - return ("inactiveChats", [("dates", dates as Any), ("chats", chats as Any), ("users", users as Any)]) - } - } - - public static func parse_inactiveChats(_ reader: BufferReader) -> InactiveChats? { - var _1: [Int32]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.InactiveChats.inactiveChats(dates: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum MessageEditData: TypeConstructorDescription { - case messageEditData(flags: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageEditData(let flags): - if boxed { - buffer.appendInt32(649453030) - } - serializeInt32(flags, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .messageEditData(let flags): - return ("messageEditData", [("flags", flags as Any)]) - } - } - - public static func parse_messageEditData(_ reader: BufferReader) -> MessageEditData? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.messages.MessageEditData.messageEditData(flags: _1!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index ba46e29edf..42309a4b33 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -1,3 +1,101 @@ +public extension Api.messages { + enum InactiveChats: TypeConstructorDescription { + case inactiveChats(dates: [Int32], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inactiveChats(let dates, let chats, let users): + if boxed { + buffer.appendInt32(-1456996667) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(dates.count)) + for item in dates { + serializeInt32(item, buffer: buffer, boxed: false) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inactiveChats(let dates, let chats, let users): + return ("inactiveChats", [("dates", dates as Any), ("chats", chats as Any), ("users", users as Any)]) + } + } + + public static func parse_inactiveChats(_ reader: BufferReader) -> InactiveChats? { + var _1: [Int32]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.InactiveChats.inactiveChats(dates: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum MessageEditData: TypeConstructorDescription { + case messageEditData(flags: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .messageEditData(let flags): + if boxed { + buffer.appendInt32(649453030) + } + serializeInt32(flags, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .messageEditData(let flags): + return ("messageEditData", [("flags", flags as Any)]) + } + } + + public static func parse_messageEditData(_ reader: BufferReader) -> MessageEditData? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.messages.MessageEditData.messageEditData(flags: _1!) + } + else { + return nil + } + } + + } +} public extension Api.messages { enum MessageReactionsList: TypeConstructorDescription { case messageReactionsList(flags: Int32, count: Int32, reactions: [Api.MessagePeerReaction], chats: [Api.Chat], users: [Api.User], nextOffset: String?) @@ -1318,67 +1416,3 @@ public extension Api.messages { } } -public extension Api.messages { - enum VotesList: TypeConstructorDescription { - case votesList(flags: Int32, count: Int32, votes: [Api.MessageUserVote], users: [Api.User], nextOffset: String?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .votesList(let flags, let count, let votes, let users, let nextOffset): - if boxed { - buffer.appendInt32(136574537) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(votes.count)) - for item in votes { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .votesList(let flags, let count, let votes, let users, let nextOffset): - return ("votesList", [("flags", flags as Any), ("count", count as Any), ("votes", votes as Any), ("users", users as Any), ("nextOffset", nextOffset as Any)]) - } - } - - public static func parse_votesList(_ reader: BufferReader) -> VotesList? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: [Api.MessageUserVote]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageUserVote.self) - } - var _4: [Api.User]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - var _5: String? - if Int(_1!) & Int(1 << 0) != 0 {_5 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.messages.VotesList.votesList(flags: _1!, count: _2!, votes: _3!, users: _4!, nextOffset: _5) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api28.swift b/submodules/TelegramApi/Sources/Api28.swift index 508590d536..7a33c0f4b4 100644 --- a/submodules/TelegramApi/Sources/Api28.swift +++ b/submodules/TelegramApi/Sources/Api28.swift @@ -1,3 +1,67 @@ +public extension Api.messages { + enum VotesList: TypeConstructorDescription { + case votesList(flags: Int32, count: Int32, votes: [Api.MessageUserVote], users: [Api.User], nextOffset: String?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .votesList(let flags, let count, let votes, let users, let nextOffset): + if boxed { + buffer.appendInt32(136574537) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(votes.count)) + for item in votes { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .votesList(let flags, let count, let votes, let users, let nextOffset): + return ("votesList", [("flags", flags as Any), ("count", count as Any), ("votes", votes as Any), ("users", users as Any), ("nextOffset", nextOffset as Any)]) + } + } + + public static func parse_votesList(_ reader: BufferReader) -> VotesList? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: [Api.MessageUserVote]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageUserVote.self) + } + var _4: [Api.User]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + var _5: String? + if Int(_1!) & Int(1 << 0) != 0 {_5 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.messages.VotesList.votesList(flags: _1!, count: _2!, votes: _3!, users: _4!, nextOffset: _5) + } + else { + return nil + } + } + + } +} public extension Api.payments { enum BankCardData: TypeConstructorDescription { case bankCardData(title: String, openUrls: [Api.BankCardOpenUrl]) diff --git a/submodules/TelegramApi/Sources/Api30.swift b/submodules/TelegramApi/Sources/Api30.swift index a34000dc6e..700b36a3d5 100644 --- a/submodules/TelegramApi/Sources/Api30.swift +++ b/submodules/TelegramApi/Sources/Api30.swift @@ -4564,6 +4564,21 @@ public extension Api.functions.messages { }) } } +public extension Api.functions.messages { + static func getEmojiGroups(hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1955122779) + serializeInt32(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getEmojiGroups", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.EmojiGroups? in + let reader = BufferReader(buffer) + var result: Api.messages.EmojiGroups? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.EmojiGroups + } + return result + }) + } +} public extension Api.functions.messages { static func getEmojiKeywords(langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -4614,6 +4629,21 @@ public extension Api.functions.messages { }) } } +public extension Api.functions.messages { + static func getEmojiStatusGroups(hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(785209037) + serializeInt32(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getEmojiStatusGroups", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.EmojiGroups? in + let reader = BufferReader(buffer) + var result: Api.messages.EmojiGroups? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.EmojiGroups + } + return result + }) + } +} public extension Api.functions.messages { static func getEmojiStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -6027,6 +6057,22 @@ public extension Api.functions.messages { }) } } +public extension Api.functions.messages { + static func searchCustomEmoji(emoticon: String, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(739360983) + serializeString(emoticon, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.searchCustomEmoji", parameters: [("emoticon", String(describing: emoticon)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EmojiList? in + let reader = BufferReader(buffer) + var result: Api.EmojiList? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.EmojiList + } + return result + }) + } +} public extension Api.functions.messages { static func searchGlobal(flags: Int32, folderId: Int32?, q: String, filter: Api.MessagesFilter, minDate: Int32, maxDate: Int32, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -7676,12 +7722,12 @@ public extension Api.functions.photos { public extension Api.functions.photos { static func uploadProfilePhoto(flags: Int32, file: Api.InputFile?, video: Api.InputFile?, videoStartTs: Double?, videoEmojiMarkup: Api.VideoSize?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-771759753) + buffer.appendInt32(154966609) serializeInt32(flags, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 0) != 0 {file!.serialize(buffer, true)} if Int(flags) & Int(1 << 1) != 0 {video!.serialize(buffer, true)} if Int(flags) & Int(1 << 2) != 0 {serializeDouble(videoStartTs!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {videoEmojiMarkup!.serialize(buffer, true)} + if Int(flags) & Int(1 << 4) != 0 {videoEmojiMarkup!.serialize(buffer, true)} return (FunctionDescription(name: "photos.uploadProfilePhoto", parameters: [("flags", String(describing: flags)), ("file", String(describing: file)), ("video", String(describing: video)), ("videoStartTs", String(describing: videoStartTs)), ("videoEmojiMarkup", String(describing: videoEmojiMarkup))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photo? in let reader = BufferReader(buffer) var result: Api.photos.Photo? diff --git a/submodules/TelegramApi/Sources/Api5.swift b/submodules/TelegramApi/Sources/Api5.swift index b3effb2ab1..1d327a9163 100644 --- a/submodules/TelegramApi/Sources/Api5.swift +++ b/submodules/TelegramApi/Sources/Api5.swift @@ -220,6 +220,56 @@ public extension Api { } } +public extension Api { + enum EmojiGroup: TypeConstructorDescription { + case emojiGroup(title: String, iconEmojiId: Int64, emoticons: [String]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .emojiGroup(let title, let iconEmojiId, let emoticons): + if boxed { + buffer.appendInt32(2056961449) + } + serializeString(title, buffer: buffer, boxed: false) + serializeInt64(iconEmojiId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(emoticons.count)) + for item in emoticons { + serializeString(item, buffer: buffer, boxed: false) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .emojiGroup(let title, let iconEmojiId, let emoticons): + return ("emojiGroup", [("title", title as Any), ("iconEmojiId", iconEmojiId as Any), ("emoticons", emoticons as Any)]) + } + } + + public static func parse_emojiGroup(_ reader: BufferReader) -> EmojiGroup? { + var _1: String? + _1 = parseString(reader) + var _2: Int64? + _2 = reader.readInt64() + var _3: [String]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.EmojiGroup.emojiGroup(title: _1!, iconEmojiId: _2!, emoticons: _3!) + } + else { + return nil + } + } + + } +} public extension Api { enum EmojiKeyword: TypeConstructorDescription { case emojiKeyword(keyword: String, emoticons: [String]) @@ -1054,47 +1104,3 @@ public extension Api { } } -public extension Api { - enum FileHash: TypeConstructorDescription { - case fileHash(offset: Int64, limit: Int32, hash: Buffer) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .fileHash(let offset, let limit, let hash): - if boxed { - buffer.appendInt32(-207944868) - } - serializeInt64(offset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeBytes(hash, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .fileHash(let offset, let limit, let hash): - return ("fileHash", [("offset", offset as Any), ("limit", limit as Any), ("hash", hash as Any)]) - } - } - - public static func parse_fileHash(_ reader: BufferReader) -> FileHash? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: Buffer? - _3 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.FileHash.fileHash(offset: _1!, limit: _2!, hash: _3!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api6.swift b/submodules/TelegramApi/Sources/Api6.swift index 69adbb6013..226f3df1a4 100644 --- a/submodules/TelegramApi/Sources/Api6.swift +++ b/submodules/TelegramApi/Sources/Api6.swift @@ -1,3 +1,47 @@ +public extension Api { + enum FileHash: TypeConstructorDescription { + case fileHash(offset: Int64, limit: Int32, hash: Buffer) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .fileHash(let offset, let limit, let hash): + if boxed { + buffer.appendInt32(-207944868) + } + serializeInt64(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeBytes(hash, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .fileHash(let offset, let limit, let hash): + return ("fileHash", [("offset", offset as Any), ("limit", limit as Any), ("hash", hash as Any)]) + } + } + + public static func parse_fileHash(_ reader: BufferReader) -> FileHash? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Buffer? + _3 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.FileHash.fileHash(offset: _1!, limit: _2!, hash: _3!) + } + else { + return nil + } + } + + } +} public extension Api { enum Folder: TypeConstructorDescription { case folder(flags: Int32, id: Int32, title: String, photo: Api.ChatPhoto?) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift index 8a788821e7..31e96678f9 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift @@ -15,7 +15,7 @@ public enum UploadPeerPhotoError { } func _internal_updateAccountPhoto(account: Account, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, fileId: Int64?, backgroundColors: [Int32]?, fallback: Bool, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { - return _internal_updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: account.peerId, photo: resource.flatMap({ _internal_uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: $0) }), video: videoResource.flatMap({ _internal_uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: $0) |> map(Optional.init) }), videoStartTimestamp: videoStartTimestamp, fallback: fallback, mapResourceToAvatarSizes: mapResourceToAvatarSizes) + return _internal_updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: account.peerId, photo: resource.flatMap({ _internal_uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: $0) }), video: videoResource.flatMap({ _internal_uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: $0) |> map(Optional.init) }), videoStartTimestamp: videoStartTimestamp, fileId: fileId, backgroundColors: backgroundColors, fallback: fallback, mapResourceToAvatarSizes: mapResourceToAvatarSizes) } public enum SetCustomPeerPhotoMode { @@ -77,7 +77,7 @@ func _internal_uploadedPeerVideo(postbox: Postbox, network: Network, messageMedi } func _internal_updatePeerPhoto(postbox: Postbox, network: Network, stateManager: AccountStateManager?, accountPeerId: PeerId, peerId: PeerId, photo: Signal?, video: Signal? = nil, videoStartTimestamp: Double? = nil, fileId: Int64? = nil, backgroundColors: [Int32]? = nil, fallback: Bool = false, customPeerPhotoMode: SetCustomPeerPhotoMode? = nil, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { - return _internal_updatePeerPhotoInternal(postbox: postbox, network: network, stateManager: stateManager, accountPeerId: accountPeerId, peer: postbox.loadedPeerWithId(peerId), photo: photo, video: video, videoStartTimestamp: videoStartTimestamp, fallback: fallback, customPeerPhotoMode: customPeerPhotoMode, mapResourceToAvatarSizes: mapResourceToAvatarSizes) + return _internal_updatePeerPhotoInternal(postbox: postbox, network: network, stateManager: stateManager, accountPeerId: accountPeerId, peer: postbox.loadedPeerWithId(peerId), photo: photo, video: video, videoStartTimestamp: videoStartTimestamp, fileId: fileId, backgroundColors: backgroundColors, fallback: fallback, customPeerPhotoMode: customPeerPhotoMode, mapResourceToAvatarSizes: mapResourceToAvatarSizes) } func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager?, accountPeerId: PeerId, peer: Signal, photo: Signal?, video: Signal?, videoStartTimestamp: Double?, fileId: Int64? = nil, backgroundColors: [Int32]? = nil, fallback: Bool = false, customPeerPhotoMode: SetCustomPeerPhotoMode? = nil, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal { diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift index 3c1876b3be..3648e9902b 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift @@ -451,11 +451,24 @@ final class AvatarEditorScreenComponent: Component { guard let strongSelf = self, let controller = strongSelf.controller?() else { return } - if groupId == AnyHashable("popular") { - let presentationData = controller.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkColorPresentationTheme) + let context = controller.context + let presentationData = controller.context.sharedContext.currentPresentationData.with { $0 } + if groupId == AnyHashable("recent") { + let actionSheet = ActionSheetController(theme: ActionSheetControllerTheme(presentationTheme: presentationData.theme, fontSize: presentationData.listsFontSize)) + var items: [ActionSheetItem] = [] + items.append(ActionSheetButtonItem(title: presentationData.strings.Emoji_ClearRecent, color: .destructive, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + let _ = context.engine.stickers.clearRecentlyUsedEmoji().start() + })) + actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ])]) + context.sharedContext.mainWindow?.presentInGlobalOverlay(actionSheet) + } else if groupId == AnyHashable("popular") { let actionSheet = ActionSheetController(theme: ActionSheetControllerTheme(presentationTheme: presentationData.theme, fontSize: presentationData.listsFontSize)) var items: [ActionSheetItem] = [] - let context = controller.context items.append(ActionSheetTextItem(title: presentationData.strings.Chat_ClearReactionsAlertText, parseMarkdown: true)) items.append(ActionSheetButtonItem(title: presentationData.strings.Chat_ClearReactionsAlertAction, color: .destructive, action: { [weak actionSheet] in actionSheet?.dismissAnimated() @@ -574,7 +587,7 @@ final class AvatarEditorScreenComponent: Component { } let context = controller.context if groupId == AnyHashable("recent") { - let presentationData = context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkColorPresentationTheme) + let presentationData = context.sharedContext.currentPresentationData.with { $0 } let actionSheet = ActionSheetController(theme: ActionSheetControllerTheme(presentationTheme: presentationData.theme, fontSize: presentationData.listsFontSize)) var items: [ActionSheetItem] = [] items.append(ActionSheetButtonItem(title: presentationData.strings.Stickers_ClearRecent, color: .destructive, action: { [weak actionSheet] in diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift index fe0de627c7..d02043b8dd 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift @@ -59,6 +59,7 @@ final class AvatarPreviewComponent: Component { private weak var state: EmptyComponentState? private let stickerFetchedDisposable = MetaDisposable() + private let cachedDisposable = MetaDisposable() override init(frame: CGRect) { self.imageView = UIImageView() @@ -84,6 +85,7 @@ final class AvatarPreviewComponent: Component { deinit { self.stickerFetchedDisposable.dispose() + self.cachedDisposable.dispose() } @objc func tapped() { @@ -202,6 +204,9 @@ final class AvatarPreviewComponent: Component { let source = AnimatedStickerResourceSource(account: component.context.account, resource: file.resource, isVideo: file.isVideoSticker || file.mimeType == "video/webm") self.animationNode?.setup(source: source, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .count(2), mode: .direct(cachePathPrefix: nil)) self.animationNode?.visibility = true + + self.cachedDisposable.set((source.cachedDataPath(width: 384, height: 384) + |> deliverOn(Queue.concurrentDefaultQueue())).start()) } } diff --git a/submodules/TelegramUI/Images.xcassets/Components/LaunchLogo.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Components/LaunchLogo.imageset/Contents.json new file mode 100644 index 0000000000..7ef092231a --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Components/LaunchLogo.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "LaunchLogo@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "LaunchLogo@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Components/LaunchLogo.imageset/LaunchLogo@2x.png b/submodules/TelegramUI/Images.xcassets/Components/LaunchLogo.imageset/LaunchLogo@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..674b7bd6fd6a30f966921510a2f821c6b4085ca5 GIT binary patch literal 7927 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 GQU3?_4FBu^ literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Images.xcassets/Components/LaunchLogo.imageset/LaunchLogo@3x.png b/submodules/TelegramUI/Images.xcassets/Components/LaunchLogo.imageset/LaunchLogo@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..dbca014ba4e9a93e61c2aa3a8c638785ebf4bed4 GIT binary patch literal 12725 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 N%Dt1Vkum-J{{gExrX2tP literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index c868643634..700bac95a4 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -316,8 +316,8 @@ private func extractAccountManagerState(records: AccountRecordsView Date: Wed, 18 Jan 2023 16:28:57 +0400 Subject: [PATCH 03/10] Fix build --- .../TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index 6ff743a4a9..96ec6c6b38 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -55,6 +55,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { private let textAccessibilityOverlayNode: TextAccessibilityOverlayNode private let statusNode: ChatMessageDateAndStatusNode private var linkHighlightingNode: LinkHighlightingNode? + private var shimmeringNode: ShimmeringLinkNode? private var textSelectionNode: TextSelectionNode? private var textHighlightingNodes: [LinkHighlightingNode] = [] From 71f367027ddc54a241ad3e40faf5644cec3121a8 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 18 Jan 2023 19:44:24 +0400 Subject: [PATCH 04/10] Various fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 14 +- .../ChatPresentationInterfaceState.swift | 2 +- submodules/TelegramApi/Sources/Api0.swift | 2 - submodules/TelegramApi/Sources/Api27.swift | 84 +++-- submodules/TelegramApi/Sources/Api28.swift | 64 ---- submodules/TelegramApi/Sources/Api30.swift | 16 + .../Messages/TelegramEngineMessages.swift | 10 +- .../TelegramEngine/Messages/Translate.swift | 36 ++- .../Sources/ServiceMessageStrings.swift | 3 +- .../Sources/AvatarEditorScreen.swift | 34 +- .../TelegramUI/Sources/ChatController.swift | 60 +++- .../Sources/ChatControllerNode.swift | 4 +- .../Sources/ChatInterfaceInputNodes.swift | 46 +-- .../Sources/ChatTextInputPanelNode.swift | 6 +- .../Sources/CreateChannelController.swift | 128 ++++---- .../Sources/CreateGroupController.swift | 294 +++++++++--------- .../TranslateUI/Sources/TranslateScreen.swift | 10 +- 17 files changed, 407 insertions(+), 406 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index b322fb591b..85eaa12dba 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8686,13 +8686,14 @@ Sorry for the inconvenience."; "RequestPeer.SelectionConfirmationTitle" = "Are you sure you want to send %1$@ to %2$@?"; "RequestPeer.SelectionConfirmationInviteText" = "This will also add %1$@ to %2$@."; +"RequestPeer.SelectionConfirmationInviteAdminText" = "This will also add %1$@ to %2$@ as an admin."; "RequestPeer.SelectionConfirmationInviteWithRightsText" = "This will also add %1$@ to %2$@ with the following rights:\n\n%3$@"; "RequestPeer.SelectionConfirmationSend" = "Send"; "CreateGroup.PublicLinkTitle" = "SET A PUBLIC LINK"; "CreateGroup.PublicLinkInfo" = "You can use **a-z**, **0-9** and underscores. Minimum length is **5** characters."; -"Notification.RequestedPeer" = "You shared %@ with the bot."; +"Notification.RequestedPeer" = "You shared %1$@ with %2$@."; "Conversation.ViewInChannel" = "View in Channel"; @@ -8706,3 +8707,14 @@ Sorry for the inconvenience."; "Conversation.Translation.Hide" = "Hide"; "Conversation.Translation.AddedToDoNotTranslateText" = "**%@** is added to the Do Not Translate list."; "Conversation.Translation.TranslationBarHiddenText" = "Translation bar is now hidden for this channel."; + +"AvatarEditor.Background" = "BACKGROUND"; +"AvatarEditor.EmojiOrSticker" = "EMOJI OR STICKER"; +"AvatarEditor.Emoji" = "EMOJI"; +"AvatarEditor.Stickers" = "STICKERS"; +"AvatarEditor.SwitchToEmoji" = "SWITCH TO EMOJI"; +"AvatarEditor.SwitchToStickers" = "SWITCH TO STICKERS"; + +"AvatarEditor.SetVideo" = "Set Video"; + +"AvatarEditor.Set" = "Set"; diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift index 1f91bb562b..0e2ee1396e 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift @@ -98,7 +98,7 @@ public enum ChatInputMode: Equatable { case none case text case media(mode: ChatMediaInputMode, expanded: ChatMediaInputExpanded?, focused: Bool) - case inputButtons + case inputButtons(persistent: Bool) } public enum ChatTitlePanelContext: Equatable, Comparable { diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 4de19de1e5..54c8f2eed5 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -1077,9 +1077,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[816245886] = { return Api.messages.Stickers.parse_stickers($0) } dict[-244016606] = { return Api.messages.Stickers.parse_stickersNotModified($0) } dict[-1821037486] = { return Api.messages.TranscribedAudio.parse_transcribedAudio($0) } - dict[1741309751] = { return Api.messages.TranslatedText.parse_translateNoResult($0) } dict[870003448] = { return Api.messages.TranslatedText.parse_translateResult($0) } - dict[-1575684144] = { return Api.messages.TranslatedText.parse_translateResultText($0) } dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) } dict[1042605427] = { return Api.payments.BankCardData.parse_bankCardData($0) } dict[-1362048039] = { return Api.payments.ExportedInvoice.parse_exportedInvoice($0) } diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index 42309a4b33..3713973863 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -1344,18 +1344,10 @@ public extension Api.messages { } public extension Api.messages { enum TranslatedText: TypeConstructorDescription { - case translateNoResult case translateResult(result: [Api.TextWithEntities]) - case translateResultText(text: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .translateNoResult: - if boxed { - buffer.appendInt32(1741309751) - } - - break case .translateResult(let result): if boxed { buffer.appendInt32(870003448) @@ -1366,29 +1358,16 @@ public extension Api.messages { item.serialize(buffer, true) } break - case .translateResultText(let text): - if boxed { - buffer.appendInt32(-1575684144) - } - serializeString(text, buffer: buffer, boxed: false) - break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .translateNoResult: - return ("translateNoResult", []) case .translateResult(let result): return ("translateResult", [("result", result as Any)]) - case .translateResultText(let text): - return ("translateResultText", [("text", text as Any)]) } } - public static func parse_translateNoResult(_ reader: BufferReader) -> TranslatedText? { - return Api.messages.TranslatedText.translateNoResult - } public static func parse_translateResult(_ reader: BufferReader) -> TranslatedText? { var _1: [Api.TextWithEntities]? if let _ = reader.readInt32() { @@ -1402,12 +1381,65 @@ public extension Api.messages { return nil } } - public static func parse_translateResultText(_ reader: BufferReader) -> TranslatedText? { - var _1: String? - _1 = parseString(reader) + + } +} +public extension Api.messages { + enum VotesList: TypeConstructorDescription { + case votesList(flags: Int32, count: Int32, votes: [Api.MessageUserVote], users: [Api.User], nextOffset: String?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .votesList(let flags, let count, let votes, let users, let nextOffset): + if boxed { + buffer.appendInt32(136574537) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(votes.count)) + for item in votes { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .votesList(let flags, let count, let votes, let users, let nextOffset): + return ("votesList", [("flags", flags as Any), ("count", count as Any), ("votes", votes as Any), ("users", users as Any), ("nextOffset", nextOffset as Any)]) + } + } + + public static func parse_votesList(_ reader: BufferReader) -> VotesList? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: [Api.MessageUserVote]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageUserVote.self) + } + var _4: [Api.User]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + var _5: String? + if Int(_1!) & Int(1 << 0) != 0 {_5 = parseString(reader) } let _c1 = _1 != nil - if _c1 { - return Api.messages.TranslatedText.translateResultText(text: _1!) + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.messages.VotesList.votesList(flags: _1!, count: _2!, votes: _3!, users: _4!, nextOffset: _5) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api28.swift b/submodules/TelegramApi/Sources/Api28.swift index 7a33c0f4b4..508590d536 100644 --- a/submodules/TelegramApi/Sources/Api28.swift +++ b/submodules/TelegramApi/Sources/Api28.swift @@ -1,67 +1,3 @@ -public extension Api.messages { - enum VotesList: TypeConstructorDescription { - case votesList(flags: Int32, count: Int32, votes: [Api.MessageUserVote], users: [Api.User], nextOffset: String?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .votesList(let flags, let count, let votes, let users, let nextOffset): - if boxed { - buffer.appendInt32(136574537) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(votes.count)) - for item in votes { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .votesList(let flags, let count, let votes, let users, let nextOffset): - return ("votesList", [("flags", flags as Any), ("count", count as Any), ("votes", votes as Any), ("users", users as Any), ("nextOffset", nextOffset as Any)]) - } - } - - public static func parse_votesList(_ reader: BufferReader) -> VotesList? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: [Api.MessageUserVote]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageUserVote.self) - } - var _4: [Api.User]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - var _5: String? - if Int(_1!) & Int(1 << 0) != 0 {_5 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.messages.VotesList.votesList(flags: _1!, count: _2!, votes: _3!, users: _4!, nextOffset: _5) - } - else { - return nil - } - } - - } -} public extension Api.payments { enum BankCardData: TypeConstructorDescription { case bankCardData(title: String, openUrls: [Api.BankCardOpenUrl]) diff --git a/submodules/TelegramApi/Sources/Api30.swift b/submodules/TelegramApi/Sources/Api30.swift index 700b36a3d5..de241641ea 100644 --- a/submodules/TelegramApi/Sources/Api30.swift +++ b/submodules/TelegramApi/Sources/Api30.swift @@ -6736,6 +6736,22 @@ public extension Api.functions.messages { }) } } +public extension Api.functions.messages { + static func togglePeerTranslations(flags: Int32, peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-461589127) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.togglePeerTranslations", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} public extension Api.functions.messages { static func toggleStickerSets(flags: Int32, stickersets: [Api.InputStickerSet]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index 00c1e83abe..191b3bdce0 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -356,12 +356,16 @@ public extension TelegramEngine { return EngineMessageReactionListContext(account: self.account, message: message, reaction: reaction) } - public func translate(text: String, fromLang: String?, toLang: String) -> Signal { - return _internal_translate(network: self.account.network, text: text, fromLang: fromLang, toLang: toLang) + public func translate(text: String, toLang: String) -> Signal { + return _internal_translate(network: self.account.network, text: text, toLang: toLang) } public func translateMessages(messageIds: [EngineMessage.Id], toLang: String) -> Signal { - return _internal_translateMessages(postbox: self.account.postbox, network: self.account.network, messageIds: messageIds, toLang: toLang) + return _internal_translateMessages(account: self.account, messageIds: messageIds, toLang: toLang) + } + + public func togglePeerMessagesTranslationHidden(peerId: EnginePeer.Id, hidden: Bool) -> Signal { + return _internal_togglePeerMessagesTranslationHidden(account: self.account, peerId: peerId, hidden: hidden) } public func transcribeAudio(messageId: MessageId) -> Signal { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift index f5c1e4f113..e5c08f1c7c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift @@ -4,7 +4,7 @@ import SwiftSignalKit import TelegramApi import MtProtoKit -func _internal_translate(network: Network, text: String, fromLang: String?, toLang: String) -> Signal { +func _internal_translate(network: Network, text: String, toLang: String) -> Signal { var flags: Int32 = 0 flags |= (1 << 1) @@ -18,10 +18,6 @@ func _internal_translate(network: Network, text: String, fromLang: String?, toLa return .complete() } switch result { - case .translateNoResult: - return .single(nil) - case let .translateResultText(text): - return .single(text) case let .translateResult(results): if case let .textWithEntities(text, _) = results.first { return .single(text) @@ -32,11 +28,11 @@ func _internal_translate(network: Network, text: String, fromLang: String?, toLa } } -func _internal_translateMessages(postbox: Postbox, network: Network, messageIds: [EngineMessage.Id], toLang: String) -> Signal { +func _internal_translateMessages(account: Account, messageIds: [EngineMessage.Id], toLang: String) -> Signal { guard let peerId = messageIds.first?.peerId else { return .never() } - return postbox.transaction { transaction -> Api.InputPeer? in + return account.postbox.transaction { transaction -> Api.InputPeer? in return transaction.getPeer(peerId).flatMap(apiInputPeer) } |> mapToSignal { inputPeer -> Signal in @@ -48,7 +44,7 @@ func _internal_translateMessages(postbox: Postbox, network: Network, messageIds: flags |= (1 << 0) let id: [Int32] = messageIds.map { $0.id } - return network.request(Api.functions.messages.translateText(flags: flags, peer: inputPeer, id: id, text: nil, toLang: toLang)) + return account.network.request(Api.functions.messages.translateText(flags: flags, peer: inputPeer, id: id, text: nil, toLang: toLang)) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) @@ -57,7 +53,7 @@ func _internal_translateMessages(postbox: Postbox, network: Network, messageIds: guard let result = result, case let .translateResult(results) = result else { return .complete() } - return postbox.transaction { transaction in + return account.postbox.transaction { transaction in var index = 0 for result in results { let messageId = messageIds[index] @@ -79,6 +75,28 @@ func _internal_translateMessages(postbox: Postbox, network: Network, messageIds: } } +func _internal_togglePeerMessagesTranslationHidden(account: Account, peerId: EnginePeer.Id, hidden: Bool) -> Signal { + return account.postbox.transaction { transaction -> Api.InputPeer? in + return transaction.getPeer(peerId).flatMap(apiInputPeer) + } + |> mapToSignal { inputPeer -> Signal in + guard let inputPeer = inputPeer else { + return .never() + } + var flags: Int32 = 0 + if hidden { + flags |= (1 << 0) + } + + return account.network.request(Api.functions.messages.togglePeerTranslations(flags: flags, peer: inputPeer)) + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + |> ignoreValues + } +} + public enum EngineAudioTranscriptionResult { case success case error diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 4fbb91613c..904571f73e 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -834,8 +834,9 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, case .attachMenuBotAllowed: attributedString = NSAttributedString(string: strings.Notification_BotWriteAllowed, font: titleFont, textColor: primaryTextColor) case let .requestedPeer(_, peerId): + let botName = message.peers[message.id.peerId].flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? "" let peerName = message.peers[peerId].flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? "" - attributedString = addAttributesToStringWithRanges(strings.Notification_RequestedPeer(peerName)._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, peerId)])) + attributedString = addAttributesToStringWithRanges(strings.Notification_RequestedPeer(peerName, botName)._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, peerId), (1, message.id.peerId)])) case .unknown: attributedString = nil } diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift index 3648e9902b..df862dfcba 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift @@ -127,13 +127,13 @@ final class AvatarEditorScreenComponent: Component { super.init() if let initialFileId, let initialBackgroundColors { - let _ = context.engine.stickers.resolveInlineStickers(fileIds: [initialFileId]) - |> map { [weak self] files in + let _ = (context.engine.stickers.resolveInlineStickers(fileIds: [initialFileId]) + |> deliverOnMainQueue).start(next: { [weak self] files in if let strongSelf = self, let file = files.values.first { strongSelf.selectedFile = file strongSelf.updated(transition: .immediate) } - } + }) self.selectedBackground = .gradient(initialBackgroundColors.map { UInt32(bitPattern: $0) }) self.previousColor = self.selectedBackground } else { @@ -227,9 +227,12 @@ final class AvatarEditorScreenComponent: Component { } private func updateData(_ data: KeyboardInputData) { + let wasEmpty = self.data == nil self.data = data - self.state?.selectedFile = data.emoji.panelItemGroups.first?.items.first?.itemFile + if wasEmpty && self.state?.selectedFile == nil { + self.state?.selectedFile = data.emoji.panelItemGroups.first?.items.first?.itemFile + } self.state?.updated(transition: .immediate) let updateSearchQuery: (String, String) -> Void = { [weak self] rawQuery, languageCode in @@ -656,6 +659,7 @@ final class AvatarEditorScreenComponent: Component { self.state = state let environment = environment[ViewControllerComponentContainer.Environment.self].value + let strings = environment.strings let controller = environment.controller self.controller = { @@ -703,7 +707,7 @@ final class AvatarEditorScreenComponent: Component { let navigationDoneButtonSize = self.navigationDoneButton.update( transition: transition, component: AnyComponent(Button( - content: AnyComponent(Text(text: "Set", font: Font.semibold(17.0), color: state.isSearchActive ? environment.theme.rootController.navigationBar.accentTextColor : .white)), + content: AnyComponent(Text(text: strings.AvatarEditor_Set, font: Font.semibold(17.0), color: state.isSearchActive ? environment.theme.rootController.navigationBar.accentTextColor : .white)), action: { [weak self] in guard let self else { return @@ -723,8 +727,8 @@ final class AvatarEditorScreenComponent: Component { } self.backgroundColor = environment.theme.list.blocksBackgroundColor - self.backgroundContainerView.backgroundColor = environment.theme.list.plainBackgroundColor - self.keyboardContainerView.backgroundColor = environment.theme.list.plainBackgroundColor + self.backgroundContainerView.backgroundColor = environment.theme.list.itemBlocksBackgroundColor + self.keyboardContainerView.backgroundColor = environment.theme.list.itemBlocksBackgroundColor self.panelSeparatorView.backgroundColor = environment.theme.list.itemPlainSeparatorColor if self.dataDisposable == nil { @@ -845,7 +849,7 @@ final class AvatarEditorScreenComponent: Component { transition: transition, component: AnyComponent(MultilineTextComponent( text: .markdown( - text: "Background".uppercased(), attributes: MarkdownAttributes( + text: strings.AvatarEditor_Background.uppercased(), attributes: MarkdownAttributes( body: body, bold: bold, link: body, @@ -955,14 +959,14 @@ final class AvatarEditorScreenComponent: Component { let keyboardSwitchTitle: String if state.isSearchActive { - keyboardTitle = "Emoji or Sticker" + keyboardTitle = strings.AvatarEditor_EmojiOrSticker keyboardSwitchTitle = " " } else if state.keyboardContentId == AnyHashable("emoji") { - keyboardTitle = "Emoji" - keyboardSwitchTitle = "Switch to Stickers" + keyboardTitle = strings.AvatarEditor_Emoji + keyboardSwitchTitle = strings.AvatarEditor_SwitchToStickers } else if state.keyboardContentId == AnyHashable("stickers") { - keyboardTitle = "Stickers" - keyboardSwitchTitle = "Switch to Emoji" + keyboardTitle = strings.AvatarEditor_Stickers + keyboardSwitchTitle = strings.AvatarEditor_SwitchToEmoji } else { keyboardTitle = " " keyboardSwitchTitle = " " @@ -1136,7 +1140,7 @@ final class AvatarEditorScreenComponent: Component { transition: transition, component: AnyComponent( SolidRoundedButtonComponent( - title: "Set Video", + title: strings.AvatarEditor_SetVideo, theme: SolidRoundedButtonComponent.Theme(theme: environment.theme), fontSize: 17.0, height: 50.0, @@ -1175,7 +1179,7 @@ final class AvatarEditorScreenComponent: Component { entity.scale = 3.3 var documentId: Int64 = 0 - if case let .file(file) = entity.content { + if case let .file(file) = entity.content, !file.isCustomEmoji { documentId = file.fileId.id } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index b871cbae01..da02b08c4c 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -4155,11 +4155,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let controller = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.excludeRecent, .doNotSearchMessages], requestPeerType: peerType, hasContactSelector: false, createNewGroup: { createNewGroupImpl?() })) - controller.peerSelected = { [weak self, weak controller] peer, _ in + + let presentConfirmation: (String, @escaping () -> Void) -> Void = { [weak self] peerName, completion in guard let strongSelf = self else { return } - let peerName = EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder) + let attributedTitle: NSAttributedString? let attributedText: NSAttributedString @@ -4180,12 +4181,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G break } if let botAdminRights { - let stringWithRanges = strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationInviteWithRightsText(botName, peerName, stringForAdminRights(strings: strongSelf.presentationData.strings, adminRights: botAdminRights)) - let formattedString = NSMutableAttributedString(string: stringWithRanges.string, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center) - for range in stringWithRanges.ranges.prefix(2) { - formattedString.addAttribute(.font, value: Font.semibold(13.0), range: range.range) + if botAdminRights.rights.isEmpty { + let stringWithRanges = strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationInviteAdminText(botName, peerName) + let formattedString = NSMutableAttributedString(string: stringWithRanges.string, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center) + for range in stringWithRanges.ranges.prefix(2) { + formattedString.addAttribute(.font, value: Font.semibold(13.0), range: range.range) + } + attributedText = formattedString + } else { + let stringWithRanges = strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationInviteWithRightsText(botName, peerName, stringForAdminRights(strings: strongSelf.presentationData.strings, adminRights: botAdminRights)) + let formattedString = NSMutableAttributedString(string: stringWithRanges.string, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center) + for range in stringWithRanges.ranges.prefix(2) { + formattedString.addAttribute(.font, value: Font.semibold(13.0), range: range.range) + } + attributedText = formattedString } - attributedText = formattedString } else { let stringWithRanges = strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationInviteText(botName, peerName) let formattedString = NSMutableAttributedString(string: stringWithRanges.string, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center) @@ -4196,28 +4206,46 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - let controller = richTextAlertController(context: context, title: attributedTitle, text: attributedText, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationSend, action: { [weak controller] in - let _ = context.engine.peers.sendBotRequestedPeer(messageId: messageId, buttonId: buttonId, requestedPeerId: peer.id).start() - controller?.dismiss() + let controller = richTextAlertController(context: context, title: attributedTitle, text: attributedText, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.RequestPeer_SelectionConfirmationSend, action: { + + completion() })]) strongSelf.present(controller, in: .window(.root)) } + + controller.peerSelected = { [weak self, weak controller] peer, _ in + guard let strongSelf = self else { + return + } + + let peerName = EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder) + presentConfirmation(peerName, { + let _ = context.engine.peers.sendBotRequestedPeer(messageId: messageId, buttonId: buttonId, requestedPeerId: peer.id).start() + controller?.dismiss() + }) + } createNewGroupImpl = { [weak controller] in switch peerType { case .user: break case let .group(group): - let createGroupController = createGroupControllerImpl(context: context, peerIds: peerId.flatMap { [$0] } ?? [], mode: .requestPeer(group), completion: { peerId, dismiss in + let createGroupController = createGroupControllerImpl(context: context, peerIds: peerId.flatMap { [$0] } ?? [], mode: .requestPeer(group), willComplete: { peerName, complete in + presentConfirmation(peerName, { + complete() + }) + }, completion: { peerId, dismiss in let _ = context.engine.peers.sendBotRequestedPeer(messageId: messageId, buttonId: buttonId, requestedPeerId: peerId).start() - dismiss() }) createGroupController.navigationPresentation = .modal controller?.replace(with: createGroupController) case let .channel(channel): - let createChannelController = createChannelController(context: context, mode: .requestPeer(channel), completion: { peerId, dismiss in + let createChannelController = createChannelController(context: context, mode: .requestPeer(channel), willComplete: { peerName, complete in + presentConfirmation(peerName, { + complete() + }) + }, completion: { peerId, dismiss in let _ = context.engine.peers.sendBotRequestedPeer(messageId: messageId, buttonId: buttonId, requestedPeerId: peerId).start() - dismiss() }) createChannelController.navigationPresentation = .modal @@ -11082,10 +11110,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var temporaryChatPresentationInterfaceState = f(self.presentationInterfaceState) if self.presentationInterfaceState.keyboardButtonsMessage?.visibleButtonKeyboardMarkup != temporaryChatPresentationInterfaceState.keyboardButtonsMessage?.visibleButtonKeyboardMarkup || self.presentationInterfaceState.keyboardButtonsMessage?.id != temporaryChatPresentationInterfaceState.keyboardButtonsMessage?.id { - if let keyboardButtonsMessage = temporaryChatPresentationInterfaceState.keyboardButtonsMessage, let _ = keyboardButtonsMessage.visibleButtonKeyboardMarkup { + if let keyboardButtonsMessage = temporaryChatPresentationInterfaceState.keyboardButtonsMessage, let keyboardMarkup = keyboardButtonsMessage.visibleButtonKeyboardMarkup { if self.presentationInterfaceState.interfaceState.editMessage == nil && self.presentationInterfaceState.interfaceState.composeInputState.inputText.length == 0 && keyboardButtonsMessage.id != temporaryChatPresentationInterfaceState.interfaceState.messageActionsState.closedButtonKeyboardMessageId && keyboardButtonsMessage.id != temporaryChatPresentationInterfaceState.interfaceState.messageActionsState.dismissedButtonKeyboardMessageId && temporaryChatPresentationInterfaceState.botStartPayload == nil { temporaryChatPresentationInterfaceState = temporaryChatPresentationInterfaceState.updatedInputMode({ _ in - return .inputButtons + return .inputButtons(persistent: keyboardMarkup.flags.contains(.persistent)) }) } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 311ad495a3..1b5ab39434 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -2567,7 +2567,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { case .none: break case .inputButtons: - if let peer = self.chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, peer.botInfo != nil { + if let peer = self.chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, peer.botInfo != nil, self.chatPresentationInterfaceState.keyboardButtonsMessage?.visibleButtonKeyboardMarkup?.flags.contains(.persistent) == true { } else { self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in return (.none, state.keyboardButtonsMessage?.id ?? state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) @@ -3041,7 +3041,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } - if let peer = self.chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, peer.botInfo != nil, case .inputButtons = self.chatPresentationInterfaceState.inputMode { + if let peer = self.chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, peer.botInfo != nil, case .inputButtons = self.chatPresentationInterfaceState.inputMode, self.chatPresentationInterfaceState.keyboardButtonsMessage?.visibleButtonKeyboardMarkup?.flags.contains(.persistent) == true { enableGesture = false } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift index ec08704f02..9df65c6b71 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift @@ -15,45 +15,15 @@ func inputNodeForChatPresentationIntefaceState(_ chatPresentationInterfaceState: } switch chatPresentationInterfaceState.inputMode { case .media: - if "".isEmpty { - if let currentNode = currentNode as? ChatEntityKeyboardInputNode { - return currentNode - } else if let inputMediaNode = inputMediaNode { - return inputMediaNode - } else if let inputMediaNode = makeMediaInputNode() { - inputMediaNode.interfaceInteraction = interfaceInteraction - return inputMediaNode - } else { - return nil - } + if let currentNode = currentNode as? ChatEntityKeyboardInputNode { + return currentNode + } else if let inputMediaNode = inputMediaNode { + return inputMediaNode + } else if let inputMediaNode = makeMediaInputNode() { + inputMediaNode.interfaceInteraction = interfaceInteraction + return inputMediaNode } else { - if let currentNode = currentNode as? ChatMediaInputNode { - return currentNode - } else if let inputMediaNode = inputMediaNode { - return inputMediaNode - } else { - var peerId: PeerId? - if case let .peer(id) = chatPresentationInterfaceState.chatLocation { - peerId = id - } - let inputNode = ChatMediaInputNode(context: context, peerId: peerId, chatLocation: chatPresentationInterfaceState.chatLocation, controllerInteraction: controllerInteraction, chatWallpaper: chatPresentationInterfaceState.chatWallpaper, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, gifPaneIsActiveUpdated: { [weak interfaceInteraction] value in - if let interfaceInteraction = interfaceInteraction { - interfaceInteraction.updateInputModeAndDismissedButtonKeyboardMessageId { state in - if case let .media(_, expanded, focused) = state.inputMode { - if value { - return (.media(mode: .gif, expanded: expanded, focused: focused), nil) - } else { - return (.media(mode: .other, expanded: expanded, focused: focused), nil) - } - } else { - return (state.inputMode, nil) - } - } - } - }) - inputNode.interfaceInteraction = interfaceInteraction - return inputNode - } + return nil } case .inputButtons: if chatPresentationInterfaceState.forceInputCommandsHidden { diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 29a72fe0b8..43f586c2d1 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -2970,9 +2970,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.dismissedEmojiSuggestionPosition = nil if let presentationInterfaceState = self.presentationInterfaceState { - if let peer = presentationInterfaceState.renderedPeer?.peer as? TelegramUser, peer.botInfo != nil, presentationInterfaceState.keyboardButtonsMessage != nil { + if let peer = presentationInterfaceState.renderedPeer?.peer as? TelegramUser, peer.botInfo != nil, let keyboardButtonsMessage = presentationInterfaceState.keyboardButtonsMessage, let keyboardMarkup = keyboardButtonsMessage.visibleButtonKeyboardMarkup, keyboardMarkup.flags.contains(.persistent) { self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId { _ in - return (.inputButtons, nil) + return (.inputButtons(persistent: true), nil) } } else { switch presentationInterfaceState.inputMode { @@ -3481,7 +3481,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } case .bot: self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in - return (.inputButtons, nil) + return (.inputButtons(persistent: state.keyboardButtonsMessage?.visibleButtonKeyboardMarkup?.flags.contains(.persistent) ?? false), nil) }) } case .commands: diff --git a/submodules/TelegramUI/Sources/CreateChannelController.swift b/submodules/TelegramUI/Sources/CreateChannelController.swift index 845c541adb..b802d9ab6d 100644 --- a/submodules/TelegramUI/Sources/CreateChannelController.swift +++ b/submodules/TelegramUI/Sources/CreateChannelController.swift @@ -211,8 +211,7 @@ public enum CreateChannelMode { case requestPeer(ReplyMarkupButtonRequestPeerType.Channel) } - -public func createChannelController(context: AccountContext, mode: CreateChannelMode = .generic, completion: ((PeerId, @escaping () -> Void) -> Void)? = nil) -> ViewController { +public func createChannelController(context: AccountContext, mode: CreateChannelMode = .generic, willComplete: @escaping (String, @escaping () -> Void) -> Void = { _, complete in complete() }, completion: ((PeerId, @escaping () -> Void) -> Void)? = nil) -> ViewController { let initialState = CreateChannelState(creating: false, editingName: ItemListAvatarAndNameInfoItemName.title(title: "", type: .channel), editingDescriptionText: "", avatar: nil) let statePromise = ValuePromise(initialState, ignoreRepeated: true) let stateValue = Atomic(value: initialState) @@ -256,53 +255,55 @@ public func createChannelController(context: AccountContext, mode: CreateChannel } if !creating && !title.isEmpty { - updateState { current in - var current = current - current.creating = true - return current - } - - endEditingImpl?() - actionsDisposable.add((context.engine.peers.createChannel(title: title, description: description.isEmpty ? nil : description) - |> deliverOnMainQueue - |> afterDisposed { - Queue.mainQueue().async { - updateState { current in - var current = current - current.creating = false - return current - } - } - }).start(next: { peerId in - let updatingAvatar = stateValue.with { - return $0.avatar - } - if let _ = updatingAvatar { - let _ = context.engine.peers.updatePeerPhoto(peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.0.get(), videoStartTimestamp: uploadedVideoAvatar?.1, mapResourceToAvatarSizes: { resource, representations in - return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) - }).start() + willComplete(title, { + updateState { current in + var current = current + current.creating = true + return current } - let controller = channelVisibilityController(context: context, peerId: peerId, mode: .initialSetup, upgradedToSupergroup: { _, f in f() }) - replaceControllerImpl?(controller) - }, error: { error in - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let text: String? - switch error { - case .generic, .tooMuchLocationBasedGroups: - text = presentationData.strings.Login_UnknownError - case .tooMuchJoined: - pushControllerImpl?(oldChannelsController(context: context, intent: .create)) - return - case .restricted: - text = presentationData.strings.Common_ActionNotAllowedError - default: - text = nil - } - if let text = text { - presentControllerImpl?(textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) - } - })) + endEditingImpl?() + actionsDisposable.add((context.engine.peers.createChannel(title: title, description: description.isEmpty ? nil : description) + |> deliverOnMainQueue + |> afterDisposed { + Queue.mainQueue().async { + updateState { current in + var current = current + current.creating = false + return current + } + } + }).start(next: { peerId in + let updatingAvatar = stateValue.with { + return $0.avatar + } + if let _ = updatingAvatar { + let _ = context.engine.peers.updatePeerPhoto(peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.0.get(), videoStartTimestamp: uploadedVideoAvatar?.1, mapResourceToAvatarSizes: { resource, representations in + return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) + }).start() + } + + let controller = channelVisibilityController(context: context, peerId: peerId, mode: .initialSetup, upgradedToSupergroup: { _, f in f() }) + replaceControllerImpl?(controller) + }, error: { error in + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let text: String? + switch error { + case .generic, .tooMuchLocationBasedGroups: + text = presentationData.strings.Login_UnknownError + case .tooMuchJoined: + pushControllerImpl?(oldChannelsController(context: context, intent: .create)) + return + case .restricted: + text = presentationData.strings.Common_ActionNotAllowedError + default: + text = nil + } + if let text = text { + presentControllerImpl?(textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) + } + })) + }) } }, changeProfilePhoto: { endEditingImpl?() @@ -506,24 +507,23 @@ public func createChannelController(context: AccountContext, mode: CreateChannel }) let signal = combineLatest(context.sharedContext.presentationData, statePromise.get()) - |> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState, Any)) in - - let rightNavigationButton: ItemListNavigationButton - if state.creating { - rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {}) - } else { - rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Next), style: .bold, enabled: !state.editingName.composedTitle.isEmpty, action: { - arguments.done() - }) - } - - let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ChannelIntro_CreateChannel), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: CreateChannelEntries(presentationData: presentationData, state: state), style: .blocks, focusItemTag: CreateChannelEntryTag.info) - - return (controllerState, (listState, arguments)) - } |> afterDisposed { - actionsDisposable.dispose() + |> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState, Any)) in + let rightNavigationButton: ItemListNavigationButton + if state.creating { + rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {}) + } else { + rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Next), style: .bold, enabled: !state.editingName.composedTitle.isEmpty, action: { + arguments.done() + }) } + + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ChannelIntro_CreateChannel), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: CreateChannelEntries(presentationData: presentationData, state: state), style: .blocks, focusItemTag: CreateChannelEntryTag.info) + + return (controllerState, (listState, arguments)) + } |> afterDisposed { + actionsDisposable.dispose() + } let controller = ItemListController(context: context, state: signal) replaceControllerImpl = { [weak controller] value in diff --git a/submodules/TelegramUI/Sources/CreateGroupController.swift b/submodules/TelegramUI/Sources/CreateGroupController.swift index b31eb9f350..0cde5a4f6f 100644 --- a/submodules/TelegramUI/Sources/CreateGroupController.swift +++ b/submodules/TelegramUI/Sources/CreateGroupController.swift @@ -530,7 +530,7 @@ private func createGroupEntries(presentationData: PresentationData, state: Creat return entries } -public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId], initialTitle: String? = nil, mode: CreateGroupMode = .generic, completion: ((PeerId, @escaping () -> Void) -> Void)? = nil) -> ViewController { +public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId], initialTitle: String? = nil, mode: CreateGroupMode = .generic, willComplete: @escaping (String, @escaping () -> Void) -> Void = { _, complete in complete() }, completion: ((PeerId, @escaping () -> Void) -> Void)? = nil) -> ViewController { var location: PeerGeoLocation? if case let .locatedGroup(latitude, longitude, address) = mode { location = PeerGeoLocation(latitude: latitude, longitude: longitude, address: address ?? "") @@ -591,52 +591,26 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] } if !creating && !title.isEmpty { - let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.GlobalAutoremoveTimeout()) - |> deliverOnMainQueue).start(next: { maybeGlobalAutoremoveTimeout in - updateState { current in - var current = current - current.creating = true - return current - } - endEditingImpl?() - - let globalAutoremoveTimeout: Int32 = maybeGlobalAutoremoveTimeout ?? 0 - let autoremoveTimeout = stateValue.with({ $0 }).autoremoveTimeout ?? globalAutoremoveTimeout - let ttlPeriod: Int32? = autoremoveTimeout == 0 ? nil : autoremoveTimeout - - var createSignal: Signal - switch mode { - case .generic: - createSignal = context.engine.peers.createGroup(title: title, peerIds: peerIds, ttlPeriod: ttlPeriod) - case .supergroup: - createSignal = context.engine.peers.createSupergroup(title: title, description: nil) - |> map(Optional.init) - |> mapError { error -> CreateGroupError in - switch error { - case .generic: - return .generic - case .restricted: - return .restricted - case .tooMuchJoined: - return .tooMuchJoined - case .tooMuchLocationBasedGroups: - return .tooMuchLocationBasedGroups - case let .serverProvided(error): - return .serverProvided(error) - } - } - case .locatedGroup: - guard let location = location else { - return + willComplete(title, { + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.GlobalAutoremoveTimeout()) + |> deliverOnMainQueue).start(next: { maybeGlobalAutoremoveTimeout in + updateState { current in + var current = current + current.creating = true + return current } + endEditingImpl?() - createSignal = addressPromise.get() - |> castError(CreateGroupError.self) - |> mapToSignal { address -> Signal in - guard let address = address else { - return .complete() - } - return context.engine.peers.createSupergroup(title: title, description: nil, location: (location.latitude, location.longitude, address)) + let globalAutoremoveTimeout: Int32 = maybeGlobalAutoremoveTimeout ?? 0 + let autoremoveTimeout = stateValue.with({ $0 }).autoremoveTimeout ?? globalAutoremoveTimeout + let ttlPeriod: Int32? = autoremoveTimeout == 0 ? nil : autoremoveTimeout + + var createSignal: Signal + switch mode { + case .generic: + createSignal = context.engine.peers.createGroup(title: title, peerIds: peerIds, ttlPeriod: ttlPeriod) + case .supergroup: + createSignal = context.engine.peers.createSupergroup(title: title, description: nil) |> map(Optional.init) |> mapError { error -> CreateGroupError in switch error { @@ -652,50 +626,18 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] return .serverProvided(error) } } - } - case let .requestPeer(group): - var isForum = false - if let isForumRequested = group.isForum, isForumRequested { - isForum = true - } - - if isForum { - createSignal = context.engine.peers.createSupergroup(title: title, description: nil, isForum: true) - |> map(Optional.init) - |> mapError { error -> CreateGroupError in - switch error { - case .generic: - return .generic - case .restricted: - return .restricted - case .tooMuchJoined: - return .tooMuchJoined - case .tooMuchLocationBasedGroups: - return .tooMuchLocationBasedGroups - case let .serverProvided(error): - return .serverProvided(error) - } + case .locatedGroup: + guard let location = location else { + return } - if let publicLink, !publicLink.isEmpty { - createSignal = createSignal - |> mapToSignal { peerId in - if let peerId = peerId { - return context.engine.peers.updateAddressName(domain: .peer(peerId), name: publicLink) - |> mapError { _ in - return .generic - } - |> map { _ in - return peerId - } - } else { - return .fail(.generic) - } + createSignal = addressPromise.get() + |> castError(CreateGroupError.self) + |> mapToSignal { address -> Signal in + guard let address = address else { + return .complete() } - } - } else { - if let publicLink, !publicLink.isEmpty { - createSignal = context.engine.peers.createSupergroup(title: title, description: nil) + return context.engine.peers.createSupergroup(title: title, description: nil, location: (location.latitude, location.longitude, address)) |> map(Optional.init) |> mapError { error -> CreateGroupError in switch error { @@ -711,6 +653,33 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] return .serverProvided(error) } } + } + case let .requestPeer(group): + var isForum = false + if let isForumRequested = group.isForum, isForumRequested { + isForum = true + } + + let createGroupSignal: (Bool) -> Signal = { isForum in + return context.engine.peers.createSupergroup(title: title, description: nil, isForum: isForum) + |> map(Optional.init) + |> mapError { error -> CreateGroupError in + switch error { + case .generic: + return .generic + case .restricted: + return .restricted + case .tooMuchJoined: + return .tooMuchJoined + case .tooMuchLocationBasedGroups: + return .tooMuchLocationBasedGroups + case let .serverProvided(error): + return .serverProvided(error) + } + } + } + if let publicLink, !publicLink.isEmpty { + createSignal = createGroupSignal(isForum) |> mapToSignal { peerId in if let peerId = peerId { return context.engine.peers.updateAddressName(domain: .peer(peerId), name: publicLink) @@ -724,82 +693,101 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] return .fail(.generic) } } + } else if isForum || group.userAdminRights != nil { + createSignal = createGroupSignal(isForum) } else { createSignal = context.engine.peers.createGroup(title: title, peerIds: peerIds, ttlPeriod: nil) } - } - } - - actionsDisposable.add((createSignal - |> mapToSignal { peerId -> Signal in - guard let peerId = peerId else { - return .single(nil) - } - let updatingAvatar = stateValue.with { - return $0.avatar - } - if let _ = updatingAvatar { - return context.engine.peers.updatePeerPhoto(peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.0.get(), videoStartTimestamp: uploadedVideoAvatar?.1, mapResourceToAvatarSizes: { resource, representations in - return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) - }) - |> ignoreValues - |> `catch` { _ -> Signal in - return .complete() - } - |> mapToSignal { _ -> Signal in - } - |> then(.single(peerId)) - } else { - return .single(peerId) - } - } - |> deliverOnMainQueue - |> afterDisposed { - Queue.mainQueue().async { - updateState { current in - var current = current - current.creating = false - return current + + if group.userAdminRights?.rights.contains(.canBeAnonymous) == true { + createSignal = createSignal + |> mapToSignal { peerId in + if let peerId = peerId { + return context.engine.peers.updateChannelAdminRights(peerId: peerId, adminId: context.account.peerId, rights: TelegramChatAdminRights(rights: .canBeAnonymous), rank: nil) + |> mapError { _ in + return .generic + } + |> map { _ in + return peerId + } + } else { + return .fail(.generic) + } + } } } - }).start(next: { peerId in - if let peerId = peerId { - if let completion = completion { - completion(peerId, { - dismissImpl?() + + actionsDisposable.add((createSignal + |> mapToSignal { peerId -> Signal in + guard let peerId = peerId else { + return .single(nil) + } + let updatingAvatar = stateValue.with { + return $0.avatar + } + if let _ = updatingAvatar { + return context.engine.peers.updatePeerPhoto(peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.0.get(), videoStartTimestamp: uploadedVideoAvatar?.1, mapResourceToAvatarSizes: { resource, representations in + return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) }) + |> ignoreValues + |> `catch` { _ -> Signal in + return .complete() + } + |> mapToSignal { _ -> Signal in + } + |> then(.single(peerId)) } else { - let controller = ChatControllerImpl(context: context, chatLocation: .peer(id: peerId)) - replaceControllerImpl?(controller) + return .single(peerId) } } - }, error: { error in - if case .serverProvided = error { - return - } - - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let text: String? - switch error { - case .privacy: - text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelMultipleError - case .generic: - text = presentationData.strings.Login_UnknownError - case .restricted: - text = presentationData.strings.Common_ActionNotAllowedError - case .tooMuchJoined: - pushImpl?(oldChannelsController(context: context, intent: .create)) - return - case .tooMuchLocationBasedGroups: - text = presentationData.strings.CreateGroup_ErrorLocatedGroupsTooMuch - default: - text = nil - } - - if let text = text { - presentControllerImpl?(textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) - } - })) + |> deliverOnMainQueue + |> afterDisposed { + Queue.mainQueue().async { + updateState { current in + var current = current + current.creating = false + return current + } + } + }).start(next: { peerId in + if let peerId = peerId { + if let completion = completion { + completion(peerId, { + dismissImpl?() + }) + } else { + let controller = ChatControllerImpl(context: context, chatLocation: .peer(id: peerId)) + replaceControllerImpl?(controller) + } + } + }, error: { error in + if case .serverProvided = error { + return + } + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let text: String? + switch error { + case .privacy: + text = presentationData.strings.Privacy_GroupsAndChannels_InviteToChannelMultipleError + case .generic: + text = presentationData.strings.Login_UnknownError + case .restricted: + text = presentationData.strings.Common_ActionNotAllowedError + case .tooMuchJoined: + pushImpl?(oldChannelsController(context: context, intent: .create)) + return + case .tooMuchLocationBasedGroups: + text = presentationData.strings.CreateGroup_ErrorLocatedGroupsTooMuch + default: + text = nil + } + + if let text = text { + presentControllerImpl?(textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) + } + })) + }) }) } }, changeProfilePhoto: { diff --git a/submodules/TranslateUI/Sources/TranslateScreen.swift b/submodules/TranslateUI/Sources/TranslateScreen.swift index b6ad520879..fca8de62e4 100644 --- a/submodules/TranslateUI/Sources/TranslateScreen.swift +++ b/submodules/TranslateUI/Sources/TranslateScreen.swift @@ -99,14 +99,11 @@ private final class TranslateScreenComponent: CombinedComponent { super.init() - self.translationDisposable.set((context.engine.messages.translate(text: text, fromLang: fromLanguage, toLang: toLanguage) |> deliverOnMainQueue).start(next: { [weak self] text in + self.translationDisposable.set((context.engine.messages.translate(text: text, toLang: toLanguage) |> deliverOnMainQueue).start(next: { [weak self] text in guard let strongSelf = self else { return } strongSelf.translatedText = text -// if strongSelf.fromLanguage == nil { -// strongSelf.fromLanguage = result.detectedLanguage -// } strongSelf.updated(transition: .immediate) }, error: { error in @@ -127,14 +124,11 @@ private final class TranslateScreenComponent: CombinedComponent { self.translatedText = nil self.updated(transition: .immediate) - self.translationDisposable.set((self.context.engine.messages.translate(text: text, fromLang: fromLanguage, toLang: toLanguage) |> deliverOnMainQueue).start(next: { [weak self] text in + self.translationDisposable.set((self.context.engine.messages.translate(text: text, toLang: toLanguage) |> deliverOnMainQueue).start(next: { [weak self] text in guard let strongSelf = self else { return } strongSelf.translatedText = text -// if strongSelf.fromLanguage == nil { -// strongSelf.fromLanguage = result.detectedLanguage -// } strongSelf.updated(transition: .immediate) }, error: { error in From 96579d1c80224975ab2544f9fc20313437d73eb3 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 18 Jan 2023 20:35:08 +0400 Subject: [PATCH 05/10] Update API [skip ci] --- .../TelegramCore/Sources/State/FetchChatList.swift | 13 +++++++++++++ submodules/TelegramCore/Sources/State/Holes.swift | 13 +++++++++++++ .../SyncCore/SyncCore_CachedChannelData.swift | 1 + .../Sources/TelegramEngine/Messages/Translate.swift | 13 +++++++++++++ .../TelegramEngine/Peers/UpdateCachedPeerData.swift | 3 +++ 5 files changed, 43 insertions(+) diff --git a/submodules/TelegramCore/Sources/State/FetchChatList.swift b/submodules/TelegramCore/Sources/State/FetchChatList.swift index 4379ac3b1f..b171afcf8f 100644 --- a/submodules/TelegramCore/Sources/State/FetchChatList.swift +++ b/submodules/TelegramCore/Sources/State/FetchChatList.swift @@ -23,6 +23,7 @@ struct ParsedDialogs { let topMessageIds: [PeerId: MessageId] let storeMessages: [StoreMessage] let ttlPeriods: [PeerId: CachedPeerAutoremoveTimeout] + let hiddenTranslations: [PeerId: Bool] let lowerNonPinnedIndex: MessageIndex? let referencedFolders: [PeerGroupId: PeerGroupUnreadCountersSummary] @@ -55,6 +56,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message], var channelStates: [PeerId: Int32] = [:] var topMessageIds: [PeerId: MessageId] = [:] var ttlPeriods: [PeerId: CachedPeerAutoremoveTimeout] = [:] + var hiddenTranslations: [PeerId: Bool] = [:] var storeMessages: [StoreMessage] = [] var nonPinnedDialogsTopMessageIds = Set() @@ -112,6 +114,10 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message], ttlPeriods[peer.peerId] = .known(ttlPeriod.flatMap(CachedPeerAutoremoveTimeout.Value.init(peerValue:))) + if (flags & (1 << 6)) != 0 { + hiddenTranslations[peer.peerId] = true + } + let isPinned = (flags & (1 << 2)) != 0 if !isPinned { nonPinnedDialogsTopMessageIds.insert(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: topMessage)) @@ -190,6 +196,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message], topMessageIds: topMessageIds, storeMessages: storeMessages, ttlPeriods: ttlPeriods, + hiddenTranslations: hiddenTranslations, lowerNonPinnedIndex: lowerNonPinnedIndex, referencedFolders: referencedFolders @@ -208,6 +215,7 @@ struct FetchedChatList { var channelStates: [PeerId: Int32] var storeMessages: [StoreMessage] var topMessageIds: [PeerId: MessageId] + var hiddenTranslations: [PeerId: Bool] var lowerNonPinnedIndex: MessageIndex? @@ -316,6 +324,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo var channelStates: [PeerId: Int32] = [:] var storeMessages: [StoreMessage] = [] var topMessageIds: [PeerId: MessageId] = [:] + var hiddenTranslations: [PeerId: Bool] = [:] peers.append(contentsOf: parsedRemoteChats.peers) peerPresences.merge(parsedRemoteChats.peerPresences, uniquingKeysWith: { _, updated in updated }) @@ -327,6 +336,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo channelStates.merge(parsedRemoteChats.channelStates, uniquingKeysWith: { _, updated in updated }) storeMessages.append(contentsOf: parsedRemoteChats.storeMessages) topMessageIds.merge(parsedRemoteChats.topMessageIds, uniquingKeysWith: { _, updated in updated }) + hiddenTranslations.merge(parsedRemoteChats.hiddenTranslations, uniquingKeysWith: { _, updated in updated }) if let parsedPinnedChats = parsedPinnedChats { peers.append(contentsOf: parsedPinnedChats.peers) @@ -339,6 +349,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo channelStates.merge(parsedPinnedChats.channelStates, uniquingKeysWith: { _, updated in updated }) storeMessages.append(contentsOf: parsedPinnedChats.storeMessages) topMessageIds.merge(parsedPinnedChats.topMessageIds, uniquingKeysWith: { _, updated in updated }) + hiddenTranslations.merge(parsedPinnedChats.hiddenTranslations, uniquingKeysWith: { _, updated in updated }) } var peerGroupIds: [PeerId: PeerGroupId] = [:] @@ -362,6 +373,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo reactionTagSummaries.merge(folderChats.reactionTagSummaries, uniquingKeysWith: { _, updated in updated }) channelStates.merge(folderChats.channelStates, uniquingKeysWith: { _, updated in updated }) storeMessages.append(contentsOf: folderChats.storeMessages) + hiddenTranslations.merge(folderChats.hiddenTranslations, uniquingKeysWith: { _, updated in updated }) } var pinnedItemIds: [PeerId]? @@ -398,6 +410,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo channelStates: channelStates, storeMessages: storeMessages, topMessageIds: topMessageIds, + hiddenTranslations: hiddenTranslations, lowerNonPinnedIndex: parsedRemoteChats.lowerNonPinnedIndex, diff --git a/submodules/TelegramCore/Sources/State/Holes.swift b/submodules/TelegramCore/Sources/State/Holes.swift index e155dfb30e..355764a701 100644 --- a/submodules/TelegramCore/Sources/State/Holes.swift +++ b/submodules/TelegramCore/Sources/State/Holes.swift @@ -835,6 +835,19 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId }) } + for (peerId, _) in fetchedChats.hiddenTranslations { + transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in + if peerId.namespace == Namespaces.Peer.CloudChannel { + let current = (current as? CachedChannelData) ?? CachedChannelData() + var updatedFlags = current.flags + updatedFlags.insert(.translationHidden) + return current.withUpdatedFlags(updatedFlags) + } else { + return current + } + }) + } + transaction.replaceChatListHole(groupId: groupId, index: hole.index, hole: fetchedChats.lowerNonPinnedIndex.flatMap(ChatListHole.init)) for peerId in fetchedChats.chatPeerIds { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift index 74c5dc1432..345e5aea37 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift @@ -19,6 +19,7 @@ public struct CachedChannelFlags: OptionSet { public static let canChangePeerGeoLocation = CachedChannelFlags(rawValue: 1 << 5) public static let canDeleteHistory = CachedChannelFlags(rawValue: 1 << 6) public static let antiSpamEnabled = CachedChannelFlags(rawValue: 1 << 7) + public static let translationHidden = CachedChannelFlags(rawValue: 1 << 8) } public struct CachedChannelParticipantsSummary: PostboxCoding, Equatable { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift index e5c08f1c7c..eb2bf05e97 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift @@ -77,6 +77,19 @@ func _internal_translateMessages(account: Account, messageIds: [EngineMessage.Id func _internal_togglePeerMessagesTranslationHidden(account: Account, peerId: EnginePeer.Id, hidden: Bool) -> Signal { return account.postbox.transaction { transaction -> Api.InputPeer? in + transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in + if let cachedData = cachedData as? CachedChannelData { + var updatedFlags = cachedData.flags + if hidden { + updatedFlags.insert(.translationHidden) + } else { + updatedFlags.remove(.translationHidden) + } + return cachedData.withUpdatedFlags(updatedFlags) + } else { + return cachedData + } + }) return transaction.getPeer(peerId).flatMap(apiInputPeer) } |> mapToSignal { inputPeer -> Signal in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index b7e640e23d..fbaffafd3e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -469,6 +469,9 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee if (flags2 & Int32(1 << 1)) != 0 { channelFlags.insert(.antiSpamEnabled) } + if (flags2 & Int32(1 << 3)) != 0 { + channelFlags.insert(.translationHidden) + } let sendAsPeerId = defaultSendAs?.peerId From 3f13dea5daa9e27a5e17210235d8ac87004de3fd Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Jan 2023 15:34:36 +0400 Subject: [PATCH 06/10] Various fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 22 +++--- .../Sources/TGMediaAvatarMenuMixin.m | 2 +- .../Peers/PeerPhotoUpdater.swift | 52 +++++++++++++- .../Sources/AvatarEditorScreen.swift | 38 +++++++++-- .../Sources/AvatarPreviewComponent.swift | 2 +- .../TelegramUI/Sources/ChatController.swift | 24 ++++--- .../ChatInterfaceStateContextMenus.swift | 52 ++++++++------ .../Sources/PeerInfo/PeerInfoScreen.swift | 68 ++++++++++++------- .../Sources/PeerSelectionControllerNode.swift | 3 + .../TranslateUI/Sources/ChatTranslation.swift | 35 ++-------- 10 files changed, 192 insertions(+), 106 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 85eaa12dba..95fafb72bf 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8648,16 +8648,17 @@ Sorry for the inconvenience."; "RequestPeer.Requirement.Group.HasUsernameOff" = "The group should be private."; "RequestPeer.Requirement.Group.HasUsernameOn" = "The group should be public."; -"RequestPeer.Requirement.Group.ForumOff" = "The group should have topics off."; -"RequestPeer.Requirement.Group.ForumOn" = "The group should have topics on."; +"RequestPeer.Requirement.Group.ForumOff" = "The group should have topics turned off."; +"RequestPeer.Requirement.Group.ForumOn" = "The group should have topics turned on."; +"RequestPeer.Requirement.Group.ParticipantOn" = "Bot should be in the group."; "RequestPeer.Requirement.Group.CreatorOn" = "You should be the owner of the group."; "RequestPeer.Requirement.Group.Rights" = "You have the admin rights to %@."; "RequestPeer.Requirement.Group.Rights.Info" = "change group info"; "RequestPeer.Requirement.Group.Rights.Send" = "post messages"; "RequestPeer.Requirement.Group.Rights.Delete" = "delete messages"; -"RequestPeer.Requirement.Group.Rights.Edit" = "delete messages"; +"RequestPeer.Requirement.Group.Rights.Edit" = "edit messages"; "RequestPeer.Requirement.Group.Rights.Ban" = "ban users"; "RequestPeer.Requirement.Group.Rights.Invite" = "invite users via link"; "RequestPeer.Requirement.Group.Rights.Pin" = "pin messages"; @@ -8672,10 +8673,10 @@ Sorry for the inconvenience."; "RequestPeer.Requirement.Channel.CreatorOn" = "You should be the owner of the channel."; "RequestPeer.Requirement.Channel.Rights" = "You have the admin rights to %@."; -"RequestPeer.Requirement.Channel.Rights.Info" = "change group info"; +"RequestPeer.Requirement.Channel.Rights.Info" = "change channel info"; "RequestPeer.Requirement.Channel.Rights.Send" = "post messages"; "RequestPeer.Requirement.Channel.Rights.Delete" = "delete messages"; -"RequestPeer.Requirement.Channel.Rights.Edit" = "delete messages"; +"RequestPeer.Requirement.Channel.Rights.Edit" = "edit messages"; "RequestPeer.Requirement.Channel.Rights.Ban" = "ban users"; "RequestPeer.Requirement.Channel.Rights.Invite" = "invite users via link"; "RequestPeer.Requirement.Channel.Rights.Pin" = "pin messages"; @@ -8697,7 +8698,6 @@ Sorry for the inconvenience."; "Conversation.ViewInChannel" = "View in Channel"; - "Conversation.HoldForAudioOnly" = "Hold to record audio."; "Conversation.HoldForVideoOnly" = "Hold to record video."; "Conversation.Translation.TranslateTo" = "Translate to %@"; @@ -8708,13 +8708,17 @@ Sorry for the inconvenience."; "Conversation.Translation.AddedToDoNotTranslateText" = "**%@** is added to the Do Not Translate list."; "Conversation.Translation.TranslationBarHiddenText" = "Translation bar is now hidden for this channel."; +"ProfilePhoto.SetEmoji" = "Set Emoji"; + "AvatarEditor.Background" = "BACKGROUND"; "AvatarEditor.EmojiOrSticker" = "EMOJI OR STICKER"; -"AvatarEditor.Emoji" = "EMOJI"; -"AvatarEditor.Stickers" = "STICKERS"; +"AvatarEditor.Emoji" = "Emoji"; +"AvatarEditor.Stickers" = "Stickers"; "AvatarEditor.SwitchToEmoji" = "SWITCH TO EMOJI"; "AvatarEditor.SwitchToStickers" = "SWITCH TO STICKERS"; -"AvatarEditor.SetVideo" = "Set Video"; +"AvatarEditor.SetProfilePhoto" = "Set as Profile Photo"; +"AvatarEditor.SetGroupPhoto" = "Set as Group Photo"; +"AvatarEditor.SetChannelPhoto" = "Set as Group Photo"; "AvatarEditor.Set" = "Set"; diff --git a/submodules/LegacyComponents/Sources/TGMediaAvatarMenuMixin.m b/submodules/LegacyComponents/Sources/TGMediaAvatarMenuMixin.m index b6c3e15132..2761c3bbc8 100644 --- a/submodules/LegacyComponents/Sources/TGMediaAvatarMenuMixin.m +++ b/submodules/LegacyComponents/Sources/TGMediaAvatarMenuMixin.m @@ -194,7 +194,7 @@ [itemViews addObject:galleryItem]; if (!_signup) { - TGMenuSheetButtonItemView *viewItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:@"Emoji or Sticker" type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^ + TGMenuSheetButtonItemView *viewItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"ProfilePhoto.SetEmoji") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^ { __strong TGMediaAvatarMenuMixin *strongSelf = weakSelf; if (strongSelf == nil) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift index 31e96678f9..1357b59f43 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/PeerPhotoUpdater.swift @@ -375,7 +375,56 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state return .generic } |> mapToSignal { photo -> Signal in - if peer.id != accountPeerId { + if peer.id == accountPeerId { + var updatedImage: TelegramMediaImage? + var representations: [TelegramMediaImageRepresentation] = [] + switch photo { + case let .photo(apiPhoto, _): + updatedImage = telegramMediaImageFromApiPhoto(apiPhoto) + switch apiPhoto { + case .photoEmpty: + break + case let .photo(_, id, _, _, _, sizes, _, dcId): + var sizes = sizes + if sizes.count == 3 { + sizes.remove(at: 1) + } + for size in sizes { + switch size { + case let .photoSize(_, w, h, _): + representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: CloudPeerPhotoSizeMediaResource(datacenterId: dcId, photoId: id, sizeSpec: w <= 200 ? .small : .fullSize, volumeId: nil, localId: nil), progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)) + case let .photoSizeProgressive(_, w, h, sizes): + representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: CloudPeerPhotoSizeMediaResource(datacenterId: dcId, photoId: id, sizeSpec: w <= 200 ? .small : .fullSize, volumeId: nil, localId: nil), progressiveSizes: sizes, immediateThumbnailData: nil, hasVideo: false, isPersonal: false)) + default: + break + } + } + } + } + return postbox.transaction { transaction -> UpdatePeerPhotoStatus in + if let peer = transaction.getPeer(peer.id) { + updatePeers(transaction: transaction, peers: [peer], update: { (_, peer) -> Peer? in + if let peer = peer as? TelegramUser { + if customPeerPhotoMode == .suggest || fallback { + return peer + } else { + return peer.withUpdatedPhoto(representations) + } + } else { + return peer + } + }) + transaction.updatePeerCachedData(peerIds: Set([peer.id])) { peerId, cachedPeerData in + if let cachedPeerData = cachedPeerData as? CachedUserData { + return cachedPeerData.withUpdatedPersonalPhoto(.known(updatedImage)) + } else { + return nil + } + } + } + return .complete([]) + } |> mapError { _ -> UploadPeerPhotoError in } + } else { var updatedUsers: [TelegramUser] = [] switch photo { case let .photo(_, apiUsers): @@ -405,7 +454,6 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state return .complete([]) } |> mapError { _ -> UploadPeerPhotoError in } } - return .single(.complete([])) } } else { let request: Signal diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift index df862dfcba..ba48097e27 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarEditorScreen.swift @@ -74,17 +74,20 @@ final class AvatarEditorScreenComponent: Component { let context: AccountContext let ready: Promise + let peerType: AvatarEditorScreen.PeerType let initialFileId: Int64? let initialBackgroundColors: [Int32]? init( context: AccountContext, ready: Promise, + peerType: AvatarEditorScreen.PeerType, initialFileId: Int64?, initialBackgroundColors: [Int32]? ) { self.context = context self.ready = ready + self.peerType = peerType self.initialFileId = initialFileId self.initialBackgroundColors = initialBackgroundColors } @@ -93,6 +96,9 @@ final class AvatarEditorScreenComponent: Component { if lhs.context !== rhs.context { return false } + if lhs.peerType != rhs.peerType { + return false + } if lhs.initialFileId != rhs.initialFileId { return false } @@ -241,6 +247,7 @@ final class AvatarEditorScreenComponent: Component { } let query = rawQuery.trimmingCharacters(in: .whitespacesAndNewlines) + let presentationData = context.sharedContext.currentPresentationData.with { $0 } if query.isEmpty { strongSelf.emojiSearchDisposable.set(nil) @@ -351,7 +358,7 @@ final class AvatarEditorScreenComponent: Component { EmojiPagerContentComponent.ItemGroup( supergroupId: "search", groupId: "emoji", - title: "Emoji", + title: presentationData.strings.AvatarEditor_Emoji, subtitle: nil, actionButtonTitle: nil, isFeatured: false, @@ -370,7 +377,7 @@ final class AvatarEditorScreenComponent: Component { EmojiPagerContentComponent.ItemGroup( supergroupId: "search", groupId: "stickers", - title: "Stickers", + title: presentationData.strings.AvatarEditor_Stickers, subtitle: nil, actionButtonTitle: nil, isFeatured: false, @@ -1136,11 +1143,21 @@ final class AvatarEditorScreenComponent: Component { contentHeight += 16.0 } + let buttonText: String + switch component.peerType { + case .user: + buttonText = strings.AvatarEditor_SetProfilePhoto + case .group: + buttonText = strings.AvatarEditor_SetGroupPhoto + case .channel: + buttonText = strings.AvatarEditor_SetChannelPhoto + } + let buttonSize = self.buttonView.update( transition: transition, component: AnyComponent( SolidRoundedButtonComponent( - title: strings.AvatarEditor_SetVideo, + title: buttonText, theme: SolidRoundedButtonComponent.Theme(theme: environment.theme), fontSize: 17.0, height: 50.0, @@ -1179,7 +1196,7 @@ final class AvatarEditorScreenComponent: Component { entity.scale = 3.3 var documentId: Int64 = 0 - if case let .file(file) = entity.content, !file.isCustomEmoji { + if case let .file(file) = entity.content, file.isCustomEmoji { documentId = file.fileId.id } @@ -1192,7 +1209,7 @@ final class AvatarEditorScreenComponent: Component { entitiesData: entitiesData, image: nil, stillImage: nil, - hasAnimation: true, + hasAnimation: entity.isAnimated, stickers: [] ) @@ -1238,6 +1255,11 @@ final class AvatarEditorScreenComponent: Component { } public final class AvatarEditorScreen: ViewControllerComponentContainer { + public enum PeerType { + case user + case group + case channel + } fileprivate let context: AccountContext private let readyValue = Promise() @@ -1247,16 +1269,18 @@ public final class AvatarEditorScreen: ViewControllerComponentContainer { public var completion: (UIImage, URL, TGVideoEditAdjustments, @escaping () -> Void) -> Void = { _, _, _, _ in } - public init(context: AccountContext, initialFileId: Int64?, initialBackgroundColors: [Int32]?) { + public init(context: AccountContext, peerType: PeerType, initialFileId: Int64?, initialBackgroundColors: [Int32]?) { self.context = context let componentReady = Promise() - super.init(context: context, component: AvatarEditorScreenComponent(context: context, ready: componentReady, initialFileId: initialFileId, initialBackgroundColors: initialBackgroundColors), navigationBarAppearance: .transparent) + super.init(context: context, component: AvatarEditorScreenComponent(context: context, ready: componentReady, peerType: peerType, initialFileId: initialFileId, initialBackgroundColors: initialBackgroundColors), navigationBarAppearance: .transparent) self.navigationPresentation = .modal self.readyValue.set(componentReady.get() |> timeout(0.3, queue: .mainQueue(), alternate: .single(true))) self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: UIView()) + + self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) } required public init(coder aDecoder: NSCoder) { diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift index d02043b8dd..bb4b3e6f47 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift @@ -202,7 +202,7 @@ final class AvatarPreviewComponent: Component { let dimensions = file.dimensions ?? PixelDimensions(width: 512, height: 512) let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 384.0, height: 384.0)) let source = AnimatedStickerResourceSource(account: component.context.account, resource: file.resource, isVideo: file.isVideoSticker || file.mimeType == "video/webm") - self.animationNode?.setup(source: source, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .count(2), mode: .direct(cachePathPrefix: nil)) + self.animationNode?.setup(source: source, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .count(1), mode: .direct(cachePathPrefix: nil)) self.animationNode?.visibility = true self.cachedDisposable.set((source.cachedDataPath(width: 384, height: 384) diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index da02b08c4c..98cb1e4138 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -6699,11 +6699,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } if peerId.namespace == Namespaces.Peer.CloudChannel { - self.translationStateDisposable = (chatTranslationState(context: self.context, peerId: peerId) - |> deliverOnMainQueue).start(next: { [weak self] translationState in + self.translationStateDisposable = combineLatest( + queue: .mainQueue(), + chatTranslationState(context: self.context, peerId: peerId), + self.chatDisplayNode.historyNode.cachedPeerDataAndMessages + ).start(next: { [weak self] translationState, cachedDataAndMessages in if let strongSelf = self { + let (cachedData, _) = cachedDataAndMessages + var isHidden = false + if let cachedData = cachedData as? CachedChannelData, cachedData.flags.contains(.translationHidden) { + isHidden = true + } var chatTranslationState: ChatPresentationTranslationState? - if let translationState, translationState.isHidden != true && !translationState.fromLang.isEmpty { + if let translationState, !isHidden && !translationState.fromLang.isEmpty { chatTranslationState = ChatPresentationTranslationState(isEnabled: translationState.isEnabled, fromLang: translationState.fromLang, toLang: translationState.toLang ?? strongSelf.presentationData.strings.baseLanguageCode) } strongSelf.updateChatPresentationInterfaceState(animated: strongSelf.willAppear, interactive: strongSelf.willAppear, { state in @@ -10055,16 +10063,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } let context = strongSelf.context - let _ = updateChatTranslationStateInteractively(engine: context.engine, peerId: peerId, { current in - return current?.withIsHidden(true) - }).start() - + let _ = context.engine.messages.togglePeerMessagesTranslationHidden(peerId: peerId, hidden: true).start() + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .image(image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/Translate"), color: .white)!, title: nil, text: presentationData.strings.Conversation_Translation_TranslationBarHiddenText, round: false, undoText: presentationData.strings.Undo_Undo), elevatedLayout: false, animateInAsReplacement: false, action: { action in if case .undo = action { - let _ = updateChatTranslationStateInteractively(engine: context.engine, peerId: peerId, { current in - return current?.withIsHidden(false) - }).start() + let _ = context.engine.messages.togglePeerMessagesTranslationHidden(peerId: peerId, hidden: false).start() } return true }), in: .current) diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index cd382d2274..3e32ac62f4 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -444,31 +444,33 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuCopy, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: theme.actionSheet.primaryTextColor) }, action: { _, f in - let copyTextWithEntities = { - var messageEntities: [MessageTextEntity]? - var restrictedText: String? - for attribute in message.attributes { - if let attribute = attribute as? TextEntitiesMessageAttribute { - messageEntities = attribute.entities - } - if let attribute = attribute as? RestrictedContentMessageAttribute { - restrictedText = attribute.platformText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) ?? "" - } + var messageEntities: [MessageTextEntity]? + var restrictedText: String? + for attribute in message.attributes { + if let attribute = attribute as? TextEntitiesMessageAttribute { + messageEntities = attribute.entities } + if let attribute = attribute as? RestrictedContentMessageAttribute { + restrictedText = attribute.platformText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) ?? "" + } + } - if let restrictedText = restrictedText { - storeMessageTextInPasteboard(restrictedText, entities: nil) + if let restrictedText = restrictedText { + storeMessageTextInPasteboard(restrictedText, entities: nil) + } else { + if let translationState = chatPresentationInterfaceState.translationState, translationState.isEnabled, + let translation = message.attributes.first(where: { ($0 as? TranslationMessageAttribute)?.toLang == translationState.toLang }) as? TranslationMessageAttribute, !translation.text.isEmpty { + storeMessageTextInPasteboard(translation.text, entities: translation.entities) } else { storeMessageTextInPasteboard(message.text, entities: messageEntities) } - - Queue.mainQueue().after(0.2, { - let content: UndoOverlayContent = .copy(text: chatPresentationInterfaceState.strings.Conversation_MessageCopied) - controllerInteraction.displayUndo(content) - }) } - copyTextWithEntities() + Queue.mainQueue().after(0.2, { + let content: UndoOverlayContent = .copy(text: chatPresentationInterfaceState.strings.Conversation_MessageCopied) + controllerInteraction.displayUndo(content) + }) + f(.default) }))) } @@ -1093,7 +1095,12 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState if let restrictedText = restrictedText { storeMessageTextInPasteboard(restrictedText, entities: nil) } else { - storeMessageTextInPasteboard(messageText, entities: messageEntities) + if let translationState = chatPresentationInterfaceState.translationState, translationState.isEnabled, + let translation = message.attributes.first(where: { ($0 as? TranslationMessageAttribute)?.toLang == translationState.toLang }) as? TranslationMessageAttribute, !translation.text.isEmpty { + storeMessageTextInPasteboard(translation.text, entities: translation.entities) + } else { + storeMessageTextInPasteboard(messageText, entities: messageEntities) + } } Queue.mainQueue().after(0.2, { @@ -1160,7 +1167,12 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuSpeak, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Message"), color: theme.actionSheet.primaryTextColor) }, action: { _, f in - controllerInteraction.performTextSelectionAction(!isCopyProtected, NSAttributedString(string: messageText), .speak) + var text = messageText + if let translationState = chatPresentationInterfaceState.translationState, translationState.isEnabled, + let translation = message.attributes.first(where: { ($0 as? TranslationMessageAttribute)?.toLang == translationState.toLang }) as? TranslationMessageAttribute, !translation.text.isEmpty { + text = translation.text + } + controllerInteraction.performTextSelectionAction(!isCopyProtected, NSAttributedString(string: text), .speak) f(.default) }))) } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index dc85bd8f76..3a7438e719 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -4849,31 +4849,37 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate items.insert(.separator, at: itemsCount) } } else if let channel = peer as? TelegramChannel { - if let cachedData = strongSelf.data?.cachedData as? CachedChannelData, cachedData.flags.contains(.canViewStats) { - items.append(.action(ContextMenuActionItem(text: presentationData.strings.ChannelInfo_Stats, icon: { theme in - generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Statistics"), color: theme.contextMenu.primaryColor) - }, action: { [weak self] _, f in - f(.dismissWithoutContent) - - self?.openStats() - }))) - } - - if let _ = strongSelf.translationState { - items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ContextMenuTranslate, icon: { theme in - generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Translate"), color: theme.contextMenu.primaryColor) - }, action: { [weak self] _, f in - f(.dismissWithoutContent) - - if let strongSelf = self { - Queue.mainQueue().after(0.3, { - let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: strongSelf.peerId, { state in - return state?.withIsHidden(false) + if let cachedData = strongSelf.data?.cachedData as? CachedChannelData { + if cachedData.flags.contains(.canViewStats) { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.ChannelInfo_Stats, icon: { theme in + generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Statistics"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] _, f in + f(.dismissWithoutContent) + + self?.openStats() + }))) + } + + if cachedData.flags.contains(.translationHidden) { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ContextMenuTranslate, icon: { theme in + generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Translate"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] _, f in + f(.dismissWithoutContent) + + if let strongSelf = self { + let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: strongSelf.peerId, { current in + return current?.withIsEnabled(true) }).start() - }) - self?.openChatForTranslation() - } - }))) + + Queue.mainQueue().after(0.2, { + let _ = (strongSelf.context.engine.messages.togglePeerMessagesTranslationHidden(peerId: strongSelf.peerId, hidden: false) + |> deliverOnMainQueue).start(completed: { [weak self] in + self?.openChatForTranslation() + }) + }) + } + }))) + } } var canReport = true @@ -7263,7 +7269,19 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate guard let strongSelf = self, let completion else { return } - let controller = AvatarEditorScreen(context: strongSelf.context, initialFileId: emojiMarkup?.fileId, initialBackgroundColors: emojiMarkup?.backgroundColors) + let peerType: AvatarEditorScreen.PeerType + if case .legacyGroup = peer { + peerType = .group + } else if case let .channel(channel) = peer { + if case .group = channel.info { + peerType = .group + } else { + peerType = .channel + } + } else { + peerType = .user + } + let controller = AvatarEditorScreen(context: strongSelf.context, peerType: peerType, initialFileId: emojiMarkup?.fileId, initialBackgroundColors: emojiMarkup?.backgroundColors) controller.completion = completion (strongSelf.controller?.navigationController?.topViewController as? ViewController)?.push(controller) } diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index 12cc9148d1..6e7fc1ed8c 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -1148,6 +1148,9 @@ private func stringForRequestPeerType(strings: PresentationStrings, peerType: Re append(strings.RequestPeer_Requirement_Group_ForumOff) } } + if group.botParticipant { + append(strings.RequestPeer_Requirement_Group_ParticipantOn) + } if let adminRights = group.userAdminRights, !group.isCreator { var rights: [String] = [] if adminRights.rights.contains(.canChangeInfo) { diff --git a/submodules/TranslateUI/Sources/ChatTranslation.swift b/submodules/TranslateUI/Sources/ChatTranslation.swift index 6f7289a4b2..1b254eae8c 100644 --- a/submodules/TranslateUI/Sources/ChatTranslation.swift +++ b/submodules/TranslateUI/Sources/ChatTranslation.swift @@ -10,33 +10,25 @@ public struct ChatTranslationState: Codable { enum CodingKeys: String, CodingKey { case baseLang case fromLang - case forcedFromLang case toLang case isEnabled - case isHidden } public let baseLang: String public let fromLang: String - public let forcedFromLang: String? public let toLang: String? public let isEnabled: Bool - public let isHidden: Bool? public init( baseLang: String, fromLang: String, - forcedFromLang: String?, toLang: String?, - isEnabled: Bool, - isHidden: Bool? + isEnabled: Bool ) { self.baseLang = baseLang self.fromLang = fromLang - self.forcedFromLang = forcedFromLang self.toLang = toLang self.isEnabled = isEnabled - self.isHidden = isHidden } public init(from decoder: Decoder) throws { @@ -44,10 +36,8 @@ public struct ChatTranslationState: Codable { self.baseLang = try container.decode(String.self, forKey: .baseLang) self.fromLang = try container.decode(String.self, forKey: .fromLang) - self.forcedFromLang = try container.decodeIfPresent(String.self, forKey: .forcedFromLang) self.toLang = try container.decodeIfPresent(String.self, forKey: .toLang) self.isEnabled = try container.decode(Bool.self, forKey: .isEnabled) - self.isHidden = try container.decodeIfPresent(Bool.self, forKey: .isHidden) } public func encode(to encoder: Encoder) throws { @@ -55,20 +45,16 @@ public struct ChatTranslationState: Codable { try container.encode(self.baseLang, forKey: .baseLang) try container.encode(self.fromLang, forKey: .fromLang) - try container.encodeIfPresent(self.forcedFromLang, forKey: .forcedFromLang) try container.encodeIfPresent(self.toLang, forKey: .toLang) try container.encode(self.isEnabled, forKey: .isEnabled) - try container.encodeIfPresent(self.isHidden, forKey: .isHidden) } public func withToLang(_ toLang: String?) -> ChatTranslationState { return ChatTranslationState( baseLang: self.baseLang, fromLang: self.fromLang, - forcedFromLang: self.forcedFromLang, toLang: toLang, - isEnabled: self.isEnabled, - isHidden: self.isHidden + isEnabled: self.isEnabled ) } @@ -76,21 +62,8 @@ public struct ChatTranslationState: Codable { return ChatTranslationState( baseLang: self.baseLang, fromLang: self.fromLang, - forcedFromLang: self.forcedFromLang, toLang: self.toLang, - isEnabled: isEnabled, - isHidden: self.isHidden - ) - } - - public func withIsHidden(_ isHidden: Bool) -> ChatTranslationState { - return ChatTranslationState( - baseLang: self.baseLang, - fromLang: self.fromLang, - forcedFromLang: self.forcedFromLang, - toLang: self.toLang, - isEnabled: self.isEnabled, - isHidden: isHidden + isEnabled: isEnabled ) } } @@ -210,7 +183,7 @@ public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id) } } let fromLang = mostFrequent?.0 ?? "" - let state = ChatTranslationState(baseLang: baseLang, fromLang: fromLang, forcedFromLang: nil, toLang: nil, isEnabled: false, isHidden: false) + let state = ChatTranslationState(baseLang: baseLang, fromLang: fromLang, toLang: nil, isEnabled: false) let _ = updateChatTranslationState(engine: context.engine, peerId: peerId, state: state).start() return state } From 50a789e9ed53174ed1fcbda65d5c0db97671dbd4 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Jan 2023 15:44:20 +0400 Subject: [PATCH 07/10] Update localization --- Telegram/Telegram-iOS/en.lproj/Localizable.strings | 5 ++--- .../TelegramUI/Sources/PeerSelectionControllerNode.swift | 3 --- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 95fafb72bf..4b4de772b8 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8677,11 +8677,10 @@ Sorry for the inconvenience."; "RequestPeer.Requirement.Channel.Rights.Send" = "post messages"; "RequestPeer.Requirement.Channel.Rights.Delete" = "delete messages"; "RequestPeer.Requirement.Channel.Rights.Edit" = "edit messages"; -"RequestPeer.Requirement.Channel.Rights.Ban" = "ban users"; -"RequestPeer.Requirement.Channel.Rights.Invite" = "invite users via link"; +"RequestPeer.Requirement.Channel.Rights.Invite" = "add subscribers"; "RequestPeer.Requirement.Channel.Rights.Pin" = "pin messages"; "RequestPeer.Requirement.Channel.Rights.Topics" = "manage topics"; -"RequestPeer.Requirement.Channel.Rights.VideoChats" = "manage video chats"; +"RequestPeer.Requirement.Channel.Rights.VideoChats" = "manage live streams"; "RequestPeer.Requirement.Channel.Rights.Anonymous" = "remain anonymous"; "RequestPeer.Requirement.Channel.Rights.AddAdmins" = "add new admins"; diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index 6e7fc1ed8c..2624962d91 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -1216,9 +1216,6 @@ private func stringForRequestPeerType(strings: PresentationStrings, peerType: Re if adminRights.rights.contains(.canEditMessages) { rights.append(strings.RequestPeer_Requirement_Channel_Rights_Edit) } - if adminRights.rights.contains(.canBanUsers) { - rights.append(strings.RequestPeer_Requirement_Channel_Rights_Ban) - } if adminRights.rights.contains(.canInviteUsers) { rights.append(strings.RequestPeer_Requirement_Channel_Rights_Invite) } From ab9d4748ec6329f6baa1949e616b3c724c60f7fc Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Jan 2023 16:14:44 +0400 Subject: [PATCH 08/10] Various fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 +- .../PagerComponent/Sources/PagerComponent.swift | 14 ++++++++++++++ .../Display/Source/TextAlertController.swift | 2 +- .../EntityKeyboard/Sources/EntityKeyboard.swift | 1 + ...EntityKeyboardTopContainerPanelComponent.swift | 7 +++++++ .../Sources/EntityKeyboardTopPanelComponent.swift | 15 ++++++++++++--- 6 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 4b4de772b8..5d23086978 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8677,7 +8677,7 @@ Sorry for the inconvenience."; "RequestPeer.Requirement.Channel.Rights.Send" = "post messages"; "RequestPeer.Requirement.Channel.Rights.Delete" = "delete messages"; "RequestPeer.Requirement.Channel.Rights.Edit" = "edit messages"; -"RequestPeer.Requirement.Channel.Rights.Invite" = "add subscribers"; +"RequestPeer.Requirement.Channel.Rights.Invite" = "invite users via link"; "RequestPeer.Requirement.Channel.Rights.Pin" = "pin messages"; "RequestPeer.Requirement.Channel.Rights.Topics" = "manage topics"; "RequestPeer.Requirement.Channel.Rights.VideoChats" = "manage live streams"; diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index 6897e9c4a2..0c098a7635 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -67,6 +67,7 @@ public final class PagerComponentChildEnvironment: Equatable { } public final class PagerComponentPanelEnvironment: Equatable { + public let isContentInFocus: Bool public let contentOffset: CGFloat public let contentTopPanels: [AnyComponentWithIdentity] public let contentIcons: [PagerComponentContentIcon] @@ -78,6 +79,7 @@ public final class PagerComponentPanelEnvironment: Equatabl public let isExpandedUpdated: (Bool, Transition) -> Void init( + isContentInFocus: Bool, contentOffset: CGFloat, contentTopPanels: [AnyComponentWithIdentity], contentIcons: [PagerComponentContentIcon], @@ -88,6 +90,7 @@ public final class PagerComponentPanelEnvironment: Equatabl visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)>, isExpandedUpdated: @escaping (Bool, Transition) -> Void ) { + self.isContentInFocus = isContentInFocus self.contentOffset = contentOffset self.contentTopPanels = contentTopPanels self.contentIcons = contentIcons @@ -100,6 +103,9 @@ public final class PagerComponentPanelEnvironment: Equatabl } public static func ==(lhs: PagerComponentPanelEnvironment, rhs: PagerComponentPanelEnvironment) -> Bool { + if lhs.isContentInFocus != rhs.isContentInFocus { + return false + } if lhs.contentOffset != rhs.contentOffset { return false } @@ -171,6 +177,7 @@ public final class PagerComponentContentIcon: Equatable { public final class PagerComponent: Component { public typealias EnvironmentType = ChildEnvironmentType + public let isContentInFocus: Bool public let contentInsets: UIEdgeInsets public let contents: [AnyComponentWithIdentity<(ChildEnvironmentType, PagerComponentChildEnvironment)>] public let contentTopPanels: [AnyComponentWithIdentity] @@ -191,6 +198,7 @@ public final class PagerComponent], contentTopPanels: [AnyComponentWithIdentity], @@ -210,6 +218,7 @@ public final class PagerComponent Bool { + if lhs.isContentInFocus != rhs.isContentInFocus { + return false + } if lhs.contentInsets != rhs.contentInsets { return false } @@ -504,6 +516,7 @@ public final class PagerComponent( + isContentInFocus: component.isContentInFocus, contentOffset: 0.0, contentTopPanels: [], contentIcons: component.contentIcons, diff --git a/submodules/Display/Source/TextAlertController.swift b/submodules/Display/Source/TextAlertController.swift index 1a56b9799e..471c993101 100644 --- a/submodules/Display/Source/TextAlertController.swift +++ b/submodules/Display/Source/TextAlertController.swift @@ -190,7 +190,7 @@ public final class TextAlertContentNode: AlertContentNode { titleNode.attributedText = title titleNode.displaysAsynchronously = false titleNode.isUserInteractionEnabled = false - titleNode.maximumNumberOfLines = 2 + titleNode.maximumNumberOfLines = 4 titleNode.truncationType = .end titleNode.isAccessibilityElement = true self.titleNode = titleNode diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 3a6986eddb..49177bee6d 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -706,6 +706,7 @@ public final class EntityKeyboardComponent: Component { let pagerSize = self.pagerView.update( transition: transition, component: AnyComponent(PagerComponent( + isContentInFocus: component.isContentInFocus, contentInsets: component.containerInsets, contents: contents, contentTopPanels: contentTopPanels, diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift index 8d76d38cbc..5e2a9d9d36 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift @@ -8,18 +8,24 @@ import TelegramCore import Postbox public final class EntityKeyboardTopContainerPanelEnvironment: Equatable { + let isContentInFocus: Bool let visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> let isExpandedUpdated: (Bool, Transition) -> Void init( + isContentInFocus: Bool, visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)>, isExpandedUpdated: @escaping (Bool, Transition) -> Void ) { + self.isContentInFocus = isContentInFocus self.visibilityFractionUpdated = visibilityFractionUpdated self.isExpandedUpdated = isExpandedUpdated } public static func ==(lhs: EntityKeyboardTopContainerPanelEnvironment, rhs: EntityKeyboardTopContainerPanelEnvironment) -> Bool { + if lhs.isContentInFocus != rhs.isContentInFocus { + return false + } if lhs.visibilityFractionUpdated !== rhs.visibilityFractionUpdated { return false } @@ -146,6 +152,7 @@ final class EntityKeyboardTopContainerPanelComponent: Component { component: panel.component, environment: { EntityKeyboardTopContainerPanelEnvironment( + isContentInFocus: panelEnvironment.isContentInFocus, visibilityFractionUpdated: panelView.visibilityFractionUpdated, isExpandedUpdated: { [weak self] isExpanded, transition in guard let strongSelf = self else { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 4f5cdf4ca0..ead8df10df 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -167,7 +167,7 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { itemLayer.layerTintColor = component.theme.list.itemAccentColor.cgColor } - itemLayer.isVisibleForAnimations = true + itemLayer.isVisibleForAnimations = itemEnvironment.isContentInFocus } if itemEnvironment.isExpanded { @@ -924,11 +924,13 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { public final class EntityKeyboardTopPanelItemEnvironment: Equatable { public let isExpanded: Bool + public let isContentInFocus: Bool public let isHighlighted: Bool public let highlightedSubgroupId: AnyHashable? - public init(isExpanded: Bool, isHighlighted: Bool, highlightedSubgroupId: AnyHashable?) { + public init(isExpanded: Bool, isContentInFocus: Bool, isHighlighted: Bool, highlightedSubgroupId: AnyHashable?) { self.isExpanded = isExpanded + self.isContentInFocus = isContentInFocus self.isHighlighted = isHighlighted self.highlightedSubgroupId = highlightedSubgroupId } @@ -937,6 +939,9 @@ public final class EntityKeyboardTopPanelItemEnvironment: Equatable { if lhs.isExpanded != rhs.isExpanded { return false } + if lhs.isContentInFocus != rhs.isContentInFocus { + return false + } if lhs.isHighlighted != rhs.isHighlighted { return false } @@ -1798,7 +1803,11 @@ public final class EntityKeyboardTopPanelComponent: Component { transition: itemTransition, component: item.content, environment: { - EntityKeyboardTopPanelItemEnvironment(isExpanded: itemLayout.isExpanded, isHighlighted: self.activeContentItemId == item.id, highlightedSubgroupId: self.activeContentItemId == item.id ? self.activeSubcontentItemId : nil) + EntityKeyboardTopPanelItemEnvironment( + isExpanded: itemLayout.isExpanded, + isContentInFocus: self.environment?.isContentInFocus ?? false, + isHighlighted: self.activeContentItemId == item.id, + highlightedSubgroupId: self.activeContentItemId == item.id ? self.activeSubcontentItemId : nil) }, containerSize: itemOuterFrame.size ) From 587d7009786f7e08ffbd34418742fd846b230b12 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Jan 2023 17:00:41 +0400 Subject: [PATCH 09/10] Various fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 +- .../Sources/ChatListSearchListPaneNode.swift | 16 +- .../Sources/HashtagSearchController.swift | 2 +- .../Sources/CreateChannelController.swift | 221 +++++++++++++++++- .../Sources/CreateGroupController.swift | 11 +- 5 files changed, 232 insertions(+), 20 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 5d23086978..7f9d30e05b 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8660,7 +8660,7 @@ Sorry for the inconvenience."; "RequestPeer.Requirement.Group.Rights.Delete" = "delete messages"; "RequestPeer.Requirement.Group.Rights.Edit" = "edit messages"; "RequestPeer.Requirement.Group.Rights.Ban" = "ban users"; -"RequestPeer.Requirement.Group.Rights.Invite" = "invite users via link"; +"RequestPeer.Requirement.Group.Rights.Invite" = "add members"; "RequestPeer.Requirement.Group.Rights.Pin" = "pin messages"; "RequestPeer.Requirement.Group.Rights.Topics" = "manage topics"; "RequestPeer.Requirement.Group.Rights.VideoChats" = "manage video chats"; diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index f3ce8a1dd7..a674e5befe 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -461,7 +461,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { } } - public func item(context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, location: ChatListControllerLocation, key: ChatListSearchPaneKey, tagMask: EngineMessage.Tags?, interaction: ChatListNodeInteraction, listInteraction: ListMessageItemInteraction, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, toggleExpandLocalResults: @escaping () -> Void, toggleExpandGlobalResults: @escaping () -> Void, searchPeer: @escaping (EnginePeer) -> Void, searchQuery: String?, searchOptions: ChatListSearchOptions?, messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void)?, openClearRecentlyDownloaded: @escaping () -> Void, toggleAllPaused: @escaping () -> Void) -> ListViewItem { + public func item(context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, requestPeerType: ReplyMarkupButtonRequestPeerType?, location: ChatListControllerLocation, key: ChatListSearchPaneKey, tagMask: EngineMessage.Tags?, interaction: ChatListNodeInteraction, listInteraction: ListMessageItemInteraction, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, toggleExpandLocalResults: @escaping () -> Void, toggleExpandGlobalResults: @escaping () -> Void, searchPeer: @escaping (EnginePeer) -> Void, searchQuery: String?, searchOptions: ChatListSearchOptions?, messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void)?, openClearRecentlyDownloaded: @escaping () -> Void, toggleAllPaused: @escaping () -> Void) -> ListViewItem { switch self { case let .topic(peer, threadInfo, _, theme, strings, expandType): let actionTitle: String? @@ -621,7 +621,11 @@ public enum ChatListSearchEntry: Comparable, Identifiable { if filter.contains(.onlyGroups) { headerType = .chats } else { - headerType = .localPeers + if let _ = requestPeerType { + headerType = .chats + } else { + headerType = .localPeers + } } header = ChatListSearchItemHeader(type: headerType, theme: theme, strings: strings, actionTitle: actionTitle, action: actionTitle == nil ? nil : { toggleExpandLocalResults() @@ -826,12 +830,12 @@ private func chatListSearchContainerPreparedRecentTransition(from fromEntries: [ return ChatListSearchContainerRecentTransition(deletions: deletions, insertions: insertions, updates: updates) } -public func chatListSearchContainerPreparedTransition(from fromEntries: [ChatListSearchEntry], to toEntries: [ChatListSearchEntry], displayingResults: Bool, isEmpty: Bool, isLoading: Bool, animated: Bool, context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, location: ChatListControllerLocation, key: ChatListSearchPaneKey, tagMask: EngineMessage.Tags?, interaction: ChatListNodeInteraction, listInteraction: ListMessageItemInteraction, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, toggleExpandLocalResults: @escaping () -> Void, toggleExpandGlobalResults: @escaping () -> Void, searchPeer: @escaping (EnginePeer) -> Void, searchQuery: String?, searchOptions: ChatListSearchOptions?, messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void)?, openClearRecentlyDownloaded: @escaping () -> Void, toggleAllPaused: @escaping () -> Void) -> ChatListSearchContainerTransition { +public func chatListSearchContainerPreparedTransition(from fromEntries: [ChatListSearchEntry], to toEntries: [ChatListSearchEntry], displayingResults: Bool, isEmpty: Bool, isLoading: Bool, animated: Bool, context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, requestPeerType: ReplyMarkupButtonRequestPeerType?, location: ChatListControllerLocation, key: ChatListSearchPaneKey, tagMask: EngineMessage.Tags?, interaction: ChatListNodeInteraction, listInteraction: ListMessageItemInteraction, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, toggleExpandLocalResults: @escaping () -> Void, toggleExpandGlobalResults: @escaping () -> Void, searchPeer: @escaping (EnginePeer) -> Void, searchQuery: String?, searchOptions: ChatListSearchOptions?, messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void)?, openClearRecentlyDownloaded: @escaping () -> Void, toggleAllPaused: @escaping () -> Void) -> ChatListSearchContainerTransition { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } - let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enableHeaders: enableHeaders, filter: filter, location: location, key: key, tagMask: tagMask, interaction: interaction, listInteraction: listInteraction, peerContextAction: peerContextAction, toggleExpandLocalResults: toggleExpandLocalResults, toggleExpandGlobalResults: toggleExpandGlobalResults, searchPeer: searchPeer, searchQuery: searchQuery, searchOptions: searchOptions, messageContextAction: messageContextAction, openClearRecentlyDownloaded: openClearRecentlyDownloaded, toggleAllPaused: toggleAllPaused), directionHint: nil) } - let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enableHeaders: enableHeaders, filter: filter, location: location, key: key, tagMask: tagMask, interaction: interaction, listInteraction: listInteraction, peerContextAction: peerContextAction, toggleExpandLocalResults: toggleExpandLocalResults, toggleExpandGlobalResults: toggleExpandGlobalResults, searchPeer: searchPeer, searchQuery: searchQuery, searchOptions: searchOptions, messageContextAction: messageContextAction, openClearRecentlyDownloaded: openClearRecentlyDownloaded, toggleAllPaused: toggleAllPaused), directionHint: nil) } + let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enableHeaders: enableHeaders, filter: filter, requestPeerType: requestPeerType, location: location, key: key, tagMask: tagMask, interaction: interaction, listInteraction: listInteraction, peerContextAction: peerContextAction, toggleExpandLocalResults: toggleExpandLocalResults, toggleExpandGlobalResults: toggleExpandGlobalResults, searchPeer: searchPeer, searchQuery: searchQuery, searchOptions: searchOptions, messageContextAction: messageContextAction, openClearRecentlyDownloaded: openClearRecentlyDownloaded, toggleAllPaused: toggleAllPaused), directionHint: nil) } + let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enableHeaders: enableHeaders, filter: filter, requestPeerType: requestPeerType, location: location, key: key, tagMask: tagMask, interaction: interaction, listInteraction: listInteraction, peerContextAction: peerContextAction, toggleExpandLocalResults: toggleExpandLocalResults, toggleExpandGlobalResults: toggleExpandGlobalResults, searchPeer: searchPeer, searchQuery: searchQuery, searchOptions: searchOptions, messageContextAction: messageContextAction, openClearRecentlyDownloaded: openClearRecentlyDownloaded, toggleAllPaused: toggleAllPaused), directionHint: nil) } return ChatListSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, displayingResults: displayingResults, isEmpty: isEmpty, isLoading: isLoading, query: searchQuery, animated: animated) } @@ -2269,7 +2273,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { let animated = selectionChanged || expandGlobalSearchChanged let firstTime = previousEntries == nil - var transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: newEntries, displayingResults: entriesAndFlags != nil, isEmpty: !isSearching && (entriesAndFlags?.isEmpty ?? false), isLoading: isSearching, animated: animated, context: context, presentationData: strongSelf.presentationData, enableHeaders: true, filter: peersFilter, location: location, key: strongSelf.key, tagMask: tagMask, interaction: chatListInteraction, listInteraction: listInteraction, peerContextAction: { message, node, rect, gesture, location in + var transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: newEntries, displayingResults: entriesAndFlags != nil, isEmpty: !isSearching && (entriesAndFlags?.isEmpty ?? false), isLoading: isSearching, animated: animated, context: context, presentationData: strongSelf.presentationData, enableHeaders: true, filter: peersFilter, requestPeerType: requestPeerType, location: location, key: strongSelf.key, tagMask: tagMask, interaction: chatListInteraction, listInteraction: listInteraction, peerContextAction: { message, node, rect, gesture, location in interaction.peerContextAction?(message, node, rect, gesture, location) }, toggleExpandLocalResults: { guard let strongSelf = self else { diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift index dae69edd03..b03a9f40f0 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift @@ -113,7 +113,7 @@ public final class HashtagSearchController: TelegramBaseController { }) let firstTime = previousEntries == nil - let transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: entries, displayingResults: true, isEmpty: entries.isEmpty, isLoading: false, animated: false, context: strongSelf.context, presentationData: strongSelf.presentationData, enableHeaders: false, filter: [], location: .chatList(groupId: .root), key: .chats, tagMask: nil, interaction: interaction, listInteraction: listInteraction, peerContextAction: nil, toggleExpandLocalResults: { + let transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: entries, displayingResults: true, isEmpty: entries.isEmpty, isLoading: false, animated: false, context: strongSelf.context, presentationData: strongSelf.presentationData, enableHeaders: false, filter: [], requestPeerType: nil, location: .chatList(groupId: .root), key: .chats, tagMask: nil, interaction: interaction, listInteraction: listInteraction, peerContextAction: nil, toggleExpandLocalResults: { }, toggleExpandGlobalResults: { }, searchPeer: { _ in }, searchQuery: "", searchOptions: nil, messageContextAction: nil, openClearRecentlyDownloaded: {}, toggleAllPaused: {}) diff --git a/submodules/TelegramUI/Sources/CreateChannelController.swift b/submodules/TelegramUI/Sources/CreateChannelController.swift index b802d9ab6d..68eddf4b0a 100644 --- a/submodules/TelegramUI/Sources/CreateChannelController.swift +++ b/submodules/TelegramUI/Sources/CreateChannelController.swift @@ -17,6 +17,7 @@ import WebSearchUI import PeerInfoUI import MapResourceToAvatarSizes import LegacyMediaPickerUI +import TextFormat private struct CreateChannelArguments { let context: AccountContext @@ -26,11 +27,14 @@ private struct CreateChannelArguments { let done: () -> Void let changeProfilePhoto: () -> Void let focusOnDescription: () -> Void + let updatePublicLinkText: (String) -> Void + let openAuction: (String) -> Void } private enum CreateChannelSection: Int32 { case info case description + case username } private enum CreateChannelEntryTag: ItemListItemTag { @@ -62,16 +66,23 @@ private enum CreateChannelEntryTag: ItemListItemTag { private enum CreateChannelEntry: ItemListNodeEntry { case channelInfo(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer?, ItemListAvatarAndNameInfoItemState, ItemListAvatarAndNameInfoItemUpdatingAvatar?) case setProfilePhoto(PresentationTheme, String) - + case descriptionSetup(PresentationTheme, String, String) case descriptionInfo(PresentationTheme, String) + case usernameHeader(PresentationTheme, String) + case username(PresentationTheme, String, String) + case usernameStatus(PresentationTheme, String, AddressNameValidationStatus, String, String) + case usernameInfo(PresentationTheme, String) + var section: ItemListSectionId { switch self { case .channelInfo, .setProfilePhoto: return CreateChannelSection.info.rawValue case .descriptionSetup, .descriptionInfo: return CreateChannelSection.description.rawValue + case .usernameHeader, .username, .usernameStatus, .usernameInfo: + return CreateChannelSection.username.rawValue } } @@ -85,6 +96,14 @@ private enum CreateChannelEntry: ItemListNodeEntry { return 2 case .descriptionInfo: return 3 + case .usernameHeader: + return 4 + case .username: + return 5 + case .usernameStatus: + return 6 + case .usernameInfo: + return 7 } } @@ -136,6 +155,30 @@ private enum CreateChannelEntry: ItemListNodeEntry { } else { return false } + case let .usernameHeader(lhsTheme, lhsText): + if case let .usernameHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } + case let .username(lhsTheme, lhsText, lhsValue): + if case let .username(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { + return true + } else { + return false + } + case let .usernameStatus(lhsTheme, lhsAddressName, lhsStatus, lhsText, lhsUsername): + if case let .usernameStatus(rhsTheme, rhsAddressName, rhsStatus, rhsText, rhsUsername) = rhs, lhsTheme === rhsTheme, lhsAddressName == rhsAddressName, lhsStatus == rhsStatus, lhsText == rhsText, lhsUsername == rhsUsername { + return true + } else { + return false + } + case let .usernameInfo(lhsTheme, lhsText): + if case let .usernameInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } } } @@ -164,6 +207,37 @@ private enum CreateChannelEntry: ItemListNodeEntry { }, tag: CreateChannelEntryTag.description) case let .descriptionInfo(_, text): return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) + case let .usernameHeader(_, title): + return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section) + case let .username(theme, placeholder, text): + return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(string: "t.me/", textColor: theme.list.itemPrimaryTextColor), text: text, placeholder: placeholder, type: .username, clearType: .always, tag: nil, sectionId: self.section, textUpdated: { updatedText in + arguments.updatePublicLinkText(updatedText) + }, action: { + }) + case let .usernameStatus(_, _, status, text, username): + var displayActivity = false + let textColor: ItemListActivityTextItem.TextColor + switch status { + case .invalidFormat: + textColor = .destructive + case let .availability(availability): + switch availability { + case .available: + textColor = .constructive + case .purchaseAvailable: + textColor = .generic + case .invalid, .taken: + textColor = .destructive + } + case .checking: + textColor = .generic + displayActivity = true + } + return ItemListActivityTextItem(displayActivity: displayActivity, presentationData: presentationData, text: text, color: textColor, linkAction: { _ in + arguments.openAuction(username) + }, sectionId: self.section) + case let .usernameInfo(_, text): + return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section) } } } @@ -173,6 +247,8 @@ private struct CreateChannelState: Equatable { var editingName: ItemListAvatarAndNameInfoItemName var editingDescriptionText: String var avatar: ItemListAvatarAndNameInfoItemUpdatingAvatar? + var editingPublicLinkText: String? + var addressNameValidationStatus: AddressNameValidationStatus? static func ==(lhs: CreateChannelState, rhs: CreateChannelState) -> Bool { if lhs.creating != rhs.creating { @@ -187,11 +263,17 @@ private struct CreateChannelState: Equatable { if lhs.avatar != rhs.avatar { return false } + if lhs.editingPublicLinkText != rhs.editingPublicLinkText { + return false + } + if lhs.addressNameValidationStatus != rhs.addressNameValidationStatus { + return false + } return true } } -private func CreateChannelEntries(presentationData: PresentationData, state: CreateChannelState) -> [CreateChannelEntry] { +private func CreateChannelEntries(presentationData: PresentationData, state: CreateChannelState, requestPeer: ReplyMarkupButtonRequestPeerType.Channel?) -> [CreateChannelEntry] { var entries: [CreateChannelEntry] = [] let groupInfoState = ItemListAvatarAndNameInfoItemState(editingName: state.editingName, updatingName: nil) @@ -203,6 +285,55 @@ private func CreateChannelEntries(presentationData: PresentationData, state: Cre entries.append(.descriptionSetup(presentationData.theme, presentationData.strings.Channel_Edit_AboutItem, state.editingDescriptionText)) entries.append(.descriptionInfo(presentationData.theme, presentationData.strings.Channel_About_Help)) + if let requestPeer { + if let hasUsername = requestPeer.hasUsername, hasUsername { + let currentUsername = state.editingPublicLinkText ?? "" + entries.append(.usernameHeader(presentationData.theme, presentationData.strings.CreateGroup_PublicLinkTitle.uppercased())) + entries.append(.username(presentationData.theme, presentationData.strings.Group_PublicLink_Placeholder, currentUsername)) + + if let status = state.addressNameValidationStatus { + let statusText: String + switch status { + case let .invalidFormat(error): + switch error { + case .startsWithDigit: + statusText = presentationData.strings.Username_InvalidStartsWithNumber + case .startsWithUnderscore: + statusText = presentationData.strings.Username_InvalidStartsWithUnderscore + case .endsWithUnderscore: + statusText = presentationData.strings.Username_InvalidEndsWithUnderscore + case .invalidCharacters: + statusText = presentationData.strings.Username_InvalidCharacters + case .tooShort: + statusText = presentationData.strings.Username_InvalidTooShort + } + case let .availability(availability): + switch availability { + case .available: + statusText = presentationData.strings.Username_UsernameIsAvailable(currentUsername).string + case .invalid: + statusText = presentationData.strings.Username_InvalidCharacters + case .taken: + statusText = presentationData.strings.Username_InvalidTaken + case .purchaseAvailable: + var markdownString = presentationData.strings.Username_UsernamePurchaseAvailable + let entities = generateTextEntities(markdownString, enabledTypes: [.mention]) + if let entity = entities.first { + markdownString.insert(contentsOf: "]()", at: markdownString.index(markdownString.startIndex, offsetBy: entity.range.upperBound)) + markdownString.insert(contentsOf: "[", at: markdownString.index(markdownString.startIndex, offsetBy: entity.range.lowerBound)) + } + statusText = markdownString + } + case .checking: + statusText = presentationData.strings.Username_CheckingUsername + } + entries.append(.usernameStatus(presentationData.theme, currentUsername, status, statusText, currentUsername)) + } + + entries.append(.usernameInfo(presentationData.theme, presentationData.strings.CreateGroup_PublicLinkInfo)) + } + } + return entries } @@ -222,6 +353,7 @@ public func createChannelController(context: AccountContext, mode: CreateChannel var replaceControllerImpl: ((ViewController) -> Void)? var pushControllerImpl: ((ViewController) -> Void)? var presentControllerImpl: ((ViewController, Any?) -> Void)? + var dismissImpl: (() -> Void)? var endEditingImpl: (() -> Void)? var focusOnDescriptionImpl: (() -> Void)? @@ -232,6 +364,14 @@ public func createChannelController(context: AccountContext, mode: CreateChannel let uploadedAvatar = Promise() var uploadedVideoAvatar: (Promise, Double?)? = nil + let checkAddressNameDisposable = MetaDisposable() + actionsDisposable.add(checkAddressNameDisposable) + + var requestPeer: ReplyMarkupButtonRequestPeerType.Channel? + if case let .requestPeer(peerType) = mode { + requestPeer = peerType + } + let arguments = CreateChannelArguments(context: context, updateEditingName: { editingName in updateState { current in var current = current @@ -250,8 +390,8 @@ public func createChannelController(context: AccountContext, mode: CreateChannel return current } }, done: { - let (creating, title, description) = stateValue.with { state -> (Bool, String, String) in - return (state.creating, state.editingName.composedTitle, state.editingDescriptionText) + let (creating, title, description, publicLink) = stateValue.with { state -> (Bool, String, String, String?) in + return (state.creating, state.editingName.composedTitle, state.editingDescriptionText, state.editingPublicLinkText) } if !creating && !title.isEmpty { @@ -263,7 +403,23 @@ public func createChannelController(context: AccountContext, mode: CreateChannel } endEditingImpl?() - actionsDisposable.add((context.engine.peers.createChannel(title: title, description: description.isEmpty ? nil : description) + + var createSignal: Signal = context.engine.peers.createChannel(title: title, description: description.isEmpty ? nil : description) + if case .requestPeer = mode { + if let publicLink, !publicLink.isEmpty { + createSignal = createSignal + |> mapToSignal { peerId in + return context.engine.peers.updateAddressName(domain: .peer(peerId), name: publicLink) + |> mapError { _ in + return .generic + } + |> map { _ in + return peerId + } + } + } + } + actionsDisposable.add((createSignal |> deliverOnMainQueue |> afterDisposed { Queue.mainQueue().async { @@ -283,8 +439,14 @@ public func createChannelController(context: AccountContext, mode: CreateChannel }).start() } - let controller = channelVisibilityController(context: context, peerId: peerId, mode: .initialSetup, upgradedToSupergroup: { _, f in f() }) - replaceControllerImpl?(controller) + if case .requestPeer = mode { + completion?(peerId, { + dismissImpl?() + }) + } else { + let controller = channelVisibilityController(context: context, peerId: peerId, mode: .initialSetup, upgradedToSupergroup: { _, f in f() }) + replaceControllerImpl?(controller) + } }, error: { error in let presentationData = context.sharedContext.currentPresentationData.with { $0 } let text: String? @@ -504,21 +666,57 @@ public func createChannelController(context: AccountContext, mode: CreateChannel }) }, focusOnDescription: { focusOnDescriptionImpl?() + }, updatePublicLinkText: { text in + if text.isEmpty { + checkAddressNameDisposable.set(nil) + updateState { state in + var updated = state + updated.editingPublicLinkText = text + updated.addressNameValidationStatus = nil + return updated + } + } else { + updateState { state in + var updated = state + updated.editingPublicLinkText = text + return updated + } + + checkAddressNameDisposable.set((context.engine.peers.validateAddressNameInteractive(domain: .peer(PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(0))), name: text) + |> deliverOnMainQueue).start(next: { result in + updateState { state in + var updated = state + updated.addressNameValidationStatus = result + return updated + } + })) + } + }, openAuction: { username in + endEditingImpl?() + + context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: "https://fragment.com/username/\(username)", forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {}) }) - + let signal = combineLatest(context.sharedContext.presentationData, statePromise.get()) |> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState, Any)) in let rightNavigationButton: ItemListNavigationButton if state.creating { rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {}) } else { - rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Next), style: .bold, enabled: !state.editingName.composedTitle.isEmpty, action: { + var isEnabled = true + if state.editingName.composedTitle.isEmpty { + isEnabled = false + } + if case let .requestPeer(peerType) = mode, let hasUsername = peerType.hasUsername, hasUsername, (state.editingPublicLinkText ?? "").isEmpty { + isEnabled = false + } + rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Next), style: .bold, enabled: isEnabled, action: { arguments.done() }) } let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ChannelIntro_CreateChannel), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: CreateChannelEntries(presentationData: presentationData, state: state), style: .blocks, focusItemTag: CreateChannelEntryTag.info) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: CreateChannelEntries(presentationData: presentationData, state: state, requestPeer: requestPeer), style: .blocks, focusItemTag: CreateChannelEntryTag.info) return (controllerState, (listState, arguments)) } |> afterDisposed { @@ -535,6 +733,9 @@ public func createChannelController(context: AccountContext, mode: CreateChannel presentControllerImpl = { [weak controller] c, a in controller?.present(c, in: .window(.root), with: a) } + dismissImpl = { [weak controller] in + controller?.dismiss() + } controller.willDisappear = { _ in endEditingImpl?() } diff --git a/submodules/TelegramUI/Sources/CreateGroupController.swift b/submodules/TelegramUI/Sources/CreateGroupController.swift index 0cde5a4f6f..955cd3d506 100644 --- a/submodules/TelegramUI/Sources/CreateGroupController.swift +++ b/submodules/TelegramUI/Sources/CreateGroupController.swift @@ -415,7 +415,7 @@ private func createGroupEntries(presentationData: PresentationData, state: Creat if let hasUsername = requestPeer.hasUsername, hasUsername { let currentUsername = state.editingPublicLinkText ?? "" entries.append(.usernameHeader(presentationData.theme, presentationData.strings.CreateGroup_PublicLinkTitle.uppercased())) - entries.append(.username(presentationData.theme, "link", currentUsername)) + entries.append(.username(presentationData.theme, presentationData.strings.Group_PublicLink_Placeholder, currentUsername)) if let status = state.addressNameValidationStatus { let statusText: String @@ -1180,7 +1180,14 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId] if state.creating { rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {}) } else { - rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Compose_Create), style: .bold, enabled: !state.editingName.composedTitle.isEmpty, action: { + var isEnabled = true + if state.editingName.composedTitle.isEmpty { + isEnabled = false + } + if case let .requestPeer(peerType) = mode, let hasUsername = peerType.hasUsername, hasUsername, (state.editingPublicLinkText ?? "").isEmpty { + isEnabled = false + } + rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Compose_Create), style: .bold, enabled: isEnabled, action: { arguments.done() }) } From 9c99c04e64188ba774fc556f89f50d99a93bd010 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Jan 2023 17:08:25 +0400 Subject: [PATCH 10/10] Various fixes --- .../ChatListUI/Sources/ChatListSearchListPaneNode.swift | 4 +++- submodules/ChatListUI/Sources/Node/ChatListNode.swift | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index a674e5befe..0ddb39044d 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -1687,7 +1687,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { return false } if let userAdminRights = groupType.userAdminRights { - if case let .admin(rights, _) = group.role { + if case .creator = group.role, userAdminRights.rights.contains(.canBeAnonymous) { + return false + } else if case let .admin(rights, _) = group.role { if rights.rights.intersection(userAdminRights.rights) != userAdminRights.rights { return false } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 10d009006d..3dc38bd953 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -1709,7 +1709,9 @@ public final class ChatListNode: ListView { return false } if let userAdminRights = groupType.userAdminRights { - if case let .admin(rights, _) = group.role { + if case .creator = group.role, userAdminRights.rights.contains(.canBeAnonymous) { + return false + } else if case let .admin(rights, _) = group.role { if rights.rights.intersection(userAdminRights.rights) != userAdminRights.rights { return false }