diff --git a/submodules/AccountContext/Sources/ContactMultiselectionController.swift b/submodules/AccountContext/Sources/ContactMultiselectionController.swift index 28b68d9693..6d60174528 100644 --- a/submodules/AccountContext/Sources/ContactMultiselectionController.swift +++ b/submodules/AccountContext/Sources/ContactMultiselectionController.swift @@ -86,18 +86,20 @@ public final class ContactMultiselectionControllerParams { public let mode: ContactMultiselectionControllerMode public let options: [ContactListAdditionalOption] public let filters: [ContactListFilter] + public let onlyWriteable: Bool public let isPeerEnabled: ((EnginePeer) -> Bool)? - public let attemptDisabledItemSelection: ((EnginePeer) -> Void)? + public let attemptDisabledItemSelection: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? public let alwaysEnabled: Bool public let limit: Int32? public let reachedLimit: ((Int32) -> Void)? - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, mode: ContactMultiselectionControllerMode, options: [ContactListAdditionalOption], filters: [ContactListFilter] = [.excludeSelf], isPeerEnabled: ((EnginePeer) -> Bool)? = nil, attemptDisabledItemSelection: ((EnginePeer) -> Void)? = nil, alwaysEnabled: Bool = false, limit: Int32? = nil, reachedLimit: ((Int32) -> Void)? = nil) { + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, mode: ContactMultiselectionControllerMode, options: [ContactListAdditionalOption], filters: [ContactListFilter] = [.excludeSelf], onlyWriteable: Bool = false, isPeerEnabled: ((EnginePeer) -> Bool)? = nil, attemptDisabledItemSelection: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? = nil, alwaysEnabled: Bool = false, limit: Int32? = nil, reachedLimit: ((Int32) -> Void)? = nil) { self.context = context self.updatedPresentationData = updatedPresentationData self.mode = mode self.options = options self.filters = filters + self.onlyWriteable = onlyWriteable self.isPeerEnabled = isPeerEnabled self.attemptDisabledItemSelection = attemptDisabledItemSelection self.alwaysEnabled = alwaysEnabled diff --git a/submodules/AccountContext/Sources/PeerSelectionController.swift b/submodules/AccountContext/Sources/PeerSelectionController.swift index d806ea0bf1..3bbfe1bc3e 100644 --- a/submodules/AccountContext/Sources/PeerSelectionController.swift +++ b/submodules/AccountContext/Sources/PeerSelectionController.swift @@ -39,6 +39,11 @@ public struct ChatListNodePeersFilter: OptionSet { } +public enum ChatListDisabledPeerReason { + case generic + case premiumRequired +} + public final class PeerSelectionControllerParams { public let context: AccountContext public let updatedPresentationData: (initial: PresentationData, signal: Signal)? @@ -50,7 +55,7 @@ public final class PeerSelectionControllerParams { public let hasContactSelector: Bool public let hasGlobalSearch: Bool public let title: String? - public let attemptSelection: ((EnginePeer, Int64?) -> Void)? + public let attemptSelection: ((EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void)? public let createNewGroup: (() -> Void)? public let pretendPresentedInModal: Bool public let multipleSelection: Bool @@ -70,7 +75,7 @@ public final class PeerSelectionControllerParams { hasContactSelector: Bool = true, hasGlobalSearch: Bool = true, title: String? = nil, - attemptSelection: ((EnginePeer, Int64?) -> Void)? = nil, + attemptSelection: ((EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void)? = nil, createNewGroup: (() -> Void)? = nil, pretendPresentedInModal: Bool = false, multipleSelection: Bool = false, diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index c6be7e5ac4..9c69a37534 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -980,6 +980,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { }, addDoNotTranslateLanguage: { _ in }, hideTranslationPanel: { }, openPremiumGift: { + }, openPremiumRequiredForMessaging: { }, updateHistoryFilter: { _ in }, requestLayout: { _ in }, chatController: { diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index c1ea6a899a..e52a226c3c 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -1617,7 +1617,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate { let contentNode = ChatListSearchContainerNode(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, filter: filter, requestPeerType: nil, location: effectiveLocation, displaySearchFilters: displaySearchFilters, hasDownloads: hasDownloads, initialFilter: initialFilter, openPeer: { [weak self] peer, _, threadId, dismissSearch in self?.requestOpenPeerFromSearch?(peer, threadId, dismissSearch) - }, openDisabledPeer: { _, _ in + }, openDisabledPeer: { _, _, _ in }, openRecentPeerOptions: { [weak self] peer in self?.requestOpenRecentPeerOptions?(peer) }, openMessage: { [weak self] peer, threadId, messageId, deactivateOnAction in diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 5f17988f33..24710a58ea 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -47,7 +47,7 @@ private enum ChatListTokenId: Int32 { final class ChatListSearchInteraction { let openPeer: (EnginePeer, EnginePeer?, Int64?, Bool) -> Void - let openDisabledPeer: (EnginePeer, Int64?) -> Void + let openDisabledPeer: (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void let openMessage: (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void let openUrl: (String) -> Void let clearRecentSearch: () -> Void @@ -61,7 +61,7 @@ final class ChatListSearchInteraction { let getSelectedMessageIds: () -> Set? let openStories: ((PeerId, ASDisplayNode) -> Void)? - init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?) -> Void, openMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set?, openStories: ((PeerId, ASDisplayNode) -> Void)?) { + init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set?, openStories: ((PeerId, ASDisplayNode) -> Void)?) { self.openPeer = openPeer self.openDisabledPeer = openDisabledPeer self.openMessage = openMessage @@ -146,7 +146,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo private let sharedOpenStoryDisposable = MetaDisposable() - public init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, filter: ChatListNodePeersFilter, requestPeerType: [ReplyMarkupButtonRequestPeerType]?, location: ChatListControllerLocation, displaySearchFilters: Bool, hasDownloads: Bool, initialFilter: ChatListSearchFilter = .chats, openPeer originalOpenPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?) -> Void, openRecentPeerOptions: @escaping (EnginePeer) -> Void, openMessage originalOpenMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, addContact: ((String) -> Void)?, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, navigationController: NavigationController?, parentController: @escaping () -> ViewController?) { + public init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, filter: ChatListNodePeersFilter, requestPeerType: [ReplyMarkupButtonRequestPeerType]?, location: ChatListControllerLocation, displaySearchFilters: Bool, hasDownloads: Bool, initialFilter: ChatListSearchFilter = .chats, openPeer originalOpenPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openRecentPeerOptions: @escaping (EnginePeer) -> Void, openMessage originalOpenMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, addContact: ((String) -> Void)?, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, navigationController: NavigationController?, parentController: @escaping () -> ViewController?) { var initialFilter = initialFilter if case .chats = initialFilter, case .forum = location { initialFilter = .topics @@ -187,8 +187,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo if peer.id.namespace != Namespaces.Peer.SecretChat { addAppLogEvent(postbox: context.account.postbox, type: "search_global_open_peer", peerId: peer.id) } - }, openDisabledPeer: { peer, threadId in - openDisabledPeer(peer, threadId) + }, openDisabledPeer: { peer, threadId, reason in + openDisabledPeer(peer, threadId, reason) }, openMessage: { peer, threadId, messageId, deactivateOnAction in originalOpenMessage(peer, threadId, messageId, deactivateOnAction) if peer.id.namespace != Namespaces.Peer.SecretChat { diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 2c7ca608e8..03c7d071ae 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -39,13 +39,13 @@ private enum ChatListRecentEntryStableId: Hashable { private enum ChatListRecentEntry: Comparable, Identifiable { case topPeers([EnginePeer], PresentationTheme, PresentationStrings) - case peer(index: Int, peer: RecentlySearchedPeer, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, PresentationPersonNameOrder, EngineGlobalNotificationSettings, PeerStoryStats?) + case peer(index: Int, peer: RecentlySearchedPeer, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, PresentationPersonNameOrder, EngineGlobalNotificationSettings, PeerStoryStats?, Bool) var stableId: ChatListRecentEntryStableId { switch self { case .topPeers: return .topPeers - case let .peer(_, peer, _, _, _, _, _, _, _): + case let .peer(_, peer, _, _, _, _, _, _, _, _): return .peerId(peer.peer.peerId) } } @@ -67,8 +67,8 @@ private enum ChatListRecentEntry: Comparable, Identifiable { } else { return false } - case let .peer(lhsIndex, lhsPeer, lhsTheme, lhsStrings, lhsTimeFormat, lhsSortOrder, lhsDisplayOrder, lhsGlobalNotificationsSettings, lhsStoryStats): - if case let .peer(rhsIndex, rhsPeer, rhsTheme, rhsStrings, rhsTimeFormat, rhsSortOrder, rhsDisplayOrder, rhsGlobalNotificationsSettings, rhsStoryStats) = rhs, lhsPeer == rhsPeer && lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings && lhsTimeFormat == rhsTimeFormat && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsGlobalNotificationsSettings == rhsGlobalNotificationsSettings && lhsStoryStats == rhsStoryStats { + case let .peer(lhsIndex, lhsPeer, lhsTheme, lhsStrings, lhsTimeFormat, lhsSortOrder, lhsDisplayOrder, lhsGlobalNotificationsSettings, lhsStoryStats, lhsRequiresPremiumForMessaging): + if case let .peer(rhsIndex, rhsPeer, rhsTheme, rhsStrings, rhsTimeFormat, rhsSortOrder, rhsDisplayOrder, rhsGlobalNotificationsSettings, rhsStoryStats, rhsRequiresPremiumForMessaging) = rhs, lhsPeer == rhsPeer && lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsStrings === rhsStrings && lhsTimeFormat == rhsTimeFormat && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsGlobalNotificationsSettings == rhsGlobalNotificationsSettings && lhsStoryStats == rhsStoryStats && lhsRequiresPremiumForMessaging == rhsRequiresPremiumForMessaging { return true } else { return false @@ -80,17 +80,17 @@ private enum ChatListRecentEntry: Comparable, Identifiable { switch lhs { case .topPeers: return true - case let .peer(lhsIndex, _, _, _, _, _, _, _, _): + case let .peer(lhsIndex, _, _, _, _, _, _, _, _, _): switch rhs { case .topPeers: return false - case let .peer(rhsIndex, _, _, _, _, _, _, _, _): + case let .peer(rhsIndex, _, _, _, _, _, _, _, _, _): return lhsIndex <= rhsIndex } } } - func item(context: AccountContext, presentationData: ChatListPresentationData, filter: ChatListNodePeersFilter, peerSelected: @escaping (EnginePeer, Int64?) -> Void, disabledPeerSelected: @escaping (EnginePeer, Int64?) -> Void, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, deletePeer: @escaping (EnginePeer.Id) -> Void, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, openStories: @escaping (EnginePeer.Id, AvatarNode) -> Void) -> ListViewItem { + func item(context: AccountContext, presentationData: ChatListPresentationData, filter: ChatListNodePeersFilter, peerSelected: @escaping (EnginePeer, Int64?) -> Void, disabledPeerSelected: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, deletePeer: @escaping (EnginePeer.Id) -> Void, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, openStories: @escaping (EnginePeer.Id, AvatarNode) -> Void) -> ListViewItem { switch self { case let .topPeers(peers, theme, strings): return ChatListRecentPeersListItem(theme: theme, strings: strings, context: context, peers: peers, peerSelected: { peer in @@ -102,7 +102,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable { gesture?.cancel() } }) - case let .peer(_, peer, theme, strings, timeFormat, nameSortOrder, nameDisplayOrder, globalNotificationSettings, storyStats): + case let .peer(_, peer, theme, strings, timeFormat, nameSortOrder, nameDisplayOrder, globalNotificationSettings, storyStats, requiresPremiumForMessaging): let primaryPeer: EnginePeer var chatPeer: EnginePeer? let maybeChatPeer = EnginePeer(peer.peer.peers[peer.peer.peerId]!) @@ -121,6 +121,9 @@ private enum ChatListRecentEntry: Comparable, Identifiable { } else { enabled = canSendMessagesToPeer(primaryPeer._asPeer()) } + if requiresPremiumForMessaging { + enabled = false + } } if filter.contains(.onlyPrivateChats) { if let peer = chatPeer { @@ -221,6 +224,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable { peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: status, badge: badge, + requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), @@ -235,7 +239,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable { }, disabledAction: { _ in if let chatPeer = peer.peer.peers[peer.peer.peerId] { - disabledPeerSelected(EnginePeer(chatPeer), nil) + disabledPeerSelected(EnginePeer(chatPeer), nil, requiresPremiumForMessaging ? .premiumRequired : .generic) } }, deletePeer: deletePeer, @@ -327,23 +331,23 @@ public enum ChatListSearchEntry: Comparable, Identifiable { } case topic(EnginePeer, ChatListItemContent.ThreadInfo, Int, PresentationTheme, PresentationStrings, ChatListSearchSectionExpandType) - case recentlySearchedPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, PeerStoryStats?) - case localPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?) - case globalPeer(FoundPeer, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?) - case message(EngineMessage, EngineRenderedPeer, EnginePeerReadCounters?, EngineMessageHistoryThread.Info?, ChatListPresentationData, Int32, Bool?, Bool, MessageOrderingKey, (id: String, size: Int64, isFirstInList: Bool)?, MessageSection, Bool, PeerStoryStats?) + case recentlySearchedPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, PeerStoryStats?, Bool) + case localPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?, Bool) + case globalPeer(FoundPeer, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?, Bool) + case message(EngineMessage, EngineRenderedPeer, EnginePeerReadCounters?, EngineMessageHistoryThread.Info?, ChatListPresentationData, Int32, Bool?, Bool, MessageOrderingKey, (id: String, size: Int64, isFirstInList: Bool)?, MessageSection, Bool, PeerStoryStats?, Bool) case addContact(String, PresentationTheme, PresentationStrings) public var stableId: ChatListSearchEntryStableId { switch self { case let .topic(_, threadInfo, _, _, _, _): return .threadId(threadInfo.id) - case let .recentlySearchedPeer(peer, _, _, _, _, _, _, _, _): + case let .recentlySearchedPeer(peer, _, _, _, _, _, _, _, _, _): return .localPeerId(peer.id) - case let .localPeer(peer, _, _, _, _, _, _, _, _, _): + case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _): return .localPeerId(peer.id) - case let .globalPeer(peer, _, _, _, _, _, _, _, _): + case let .globalPeer(peer, _, _, _, _, _, _, _, _, _): return .globalPeerId(peer.peer.id) - case let .message(message, _, _, _, _, _, _, _, _, _, section, _, _): + case let .message(message, _, _, _, _, _, _, _, _, _, section, _, _, _): return .messageId(message.id, section) case .addContact: return .addContact @@ -358,26 +362,26 @@ public enum ChatListSearchEntry: Comparable, Identifiable { } else { return false } - case let .recentlySearchedPeer(lhsPeer, lhsAssociatedPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsStoryStats): - if case let .recentlySearchedPeer(rhsPeer, rhsAssociatedPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsStoryStats) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsStoryStats == rhsStoryStats { + case let .recentlySearchedPeer(lhsPeer, lhsAssociatedPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsStoryStats, lhsRequiresPremiumForMessaging): + if case let .recentlySearchedPeer(rhsPeer, rhsAssociatedPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsStoryStats, rhsRequiresPremiumForMessaging) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsStoryStats == rhsStoryStats && lhsRequiresPremiumForMessaging == rhsRequiresPremiumForMessaging { return true } else { return false } - case let .localPeer(lhsPeer, lhsAssociatedPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType, lhsStoryStats): - if case let .localPeer(rhsPeer, rhsAssociatedPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType, rhsStoryStats) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType && lhsStoryStats == rhsStoryStats { + case let .localPeer(lhsPeer, lhsAssociatedPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType, lhsStoryStats, lhsRequiresPremiumForMessaging): + if case let .localPeer(rhsPeer, rhsAssociatedPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType, rhsStoryStats, rhsRequiresPremiumForMessaging) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType && lhsStoryStats == rhsStoryStats && lhsRequiresPremiumForMessaging == rhsRequiresPremiumForMessaging { return true } else { return false } - case let .globalPeer(lhsPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType, lhsStoryStats): - if case let .globalPeer(rhsPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType, rhsStoryStats) = rhs, lhsPeer == rhsPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType && lhsStoryStats == rhsStoryStats { + case let .globalPeer(lhsPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType, lhsStoryStats, lhsRequiresPremiumForMessaging): + if case let .globalPeer(rhsPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType, rhsStoryStats, rhsRequiresPremiumForMessaging) = rhs, lhsPeer == rhsPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType && lhsStoryStats == rhsStoryStats && lhsRequiresPremiumForMessaging == rhsRequiresPremiumForMessaging { return true } else { return false } - case let .message(lhsMessage, lhsPeer, lhsCombinedPeerReadState, lhsThreadInfo, lhsPresentationData, lhsTotalCount, lhsSelected, lhsDisplayCustomHeader, lhsKey, lhsResourceId, lhsSection, lhsAllPaused, lhsStoryStats): - if case let .message(rhsMessage, rhsPeer, rhsCombinedPeerReadState, rhsThreadInfo, rhsPresentationData, rhsTotalCount, rhsSelected, rhsDisplayCustomHeader, rhsKey, rhsResourceId, rhsSection, rhsAllPaused, rhsStoryStats) = rhs { + case let .message(lhsMessage, lhsPeer, lhsCombinedPeerReadState, lhsThreadInfo, lhsPresentationData, lhsTotalCount, lhsSelected, lhsDisplayCustomHeader, lhsKey, lhsResourceId, lhsSection, lhsAllPaused, lhsStoryStats, lhsRequiresPremiumForMessaging): + if case let .message(rhsMessage, rhsPeer, rhsCombinedPeerReadState, rhsThreadInfo, rhsPresentationData, rhsTotalCount, rhsSelected, rhsDisplayCustomHeader, rhsKey, rhsResourceId, rhsSection, rhsAllPaused, rhsStoryStats, rhsRequiresPremiumForMessaging) = rhs { if lhsMessage.id != rhsMessage.id { return false } @@ -423,6 +427,9 @@ public enum ChatListSearchEntry: Comparable, Identifiable { if lhsStoryStats != rhsStoryStats { return false } + if lhsRequiresPremiumForMessaging != rhsRequiresPremiumForMessaging { + return false + } return true } else { return false @@ -453,34 +460,34 @@ public enum ChatListSearchEntry: Comparable, Identifiable { } else { return true } - case let .recentlySearchedPeer(_, _, _, lhsIndex, _, _, _, _, _): + case let .recentlySearchedPeer(_, _, _, lhsIndex, _, _, _, _, _, _): if case .topic = rhs { return false - } else if case let .recentlySearchedPeer(_, _, _, rhsIndex, _, _, _, _, _) = rhs { + } else if case let .recentlySearchedPeer(_, _, _, rhsIndex, _, _, _, _, _, _) = rhs { return lhsIndex <= rhsIndex } else { return true } - case let .localPeer(_, _, _, lhsIndex, _, _, _, _, _, _): + case let .localPeer(_, _, _, lhsIndex, _, _, _, _, _, _, _): switch rhs { case .topic, .recentlySearchedPeer: return false - case let .localPeer(_, _, _, rhsIndex, _, _, _, _, _, _): + case let .localPeer(_, _, _, rhsIndex, _, _, _, _, _, _, _): return lhsIndex <= rhsIndex case .globalPeer, .message, .addContact: return true } - case let .globalPeer(_, _, lhsIndex, _, _, _, _, _, _): + case let .globalPeer(_, _, lhsIndex, _, _, _, _, _, _, _): switch rhs { case .topic, .recentlySearchedPeer, .localPeer: return false - case let .globalPeer(_, _, rhsIndex, _, _, _, _, _, _): + case let .globalPeer(_, _, rhsIndex, _, _, _, _, _, _, _): return lhsIndex <= rhsIndex case .message, .addContact: return true } - case let .message(_, _, _, _, _, _, _, _, lhsKey, _, _, _, _): - if case let .message(_, _, _, _, _, _, _, _, rhsKey, _, _, _, _) = rhs { + case let .message(_, _, _, _, _, _, _, _, lhsKey, _, _, _, _, _): + if case let .message(_, _, _, _, _, _, _, _, rhsKey, _, _, _, _, _) = rhs { return lhsKey < rhsKey } else if case .addContact = rhs { return true @@ -511,7 +518,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: .firstLast, displayOrder: .firstLast, context: context, peerMode: .generalSearch(isSavedMessages: false), peer: .thread(peer: peer, title: threadInfo.info.title, icon: threadInfo.info.icon, color: threadInfo.info.iconColor), status: .none, badge: nil, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in interaction.peerSelected(peer, nil, threadInfo.id, nil) }, contextAction: nil, animationCache: interaction.animationCache, animationRenderer: interaction.animationRenderer) - case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, storyStats): + case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, storyStats, requiresPremiumForMessaging): let primaryPeer: EnginePeer var chatPeer: EnginePeer? if let associatedPeer = associatedPeer { @@ -529,6 +536,9 @@ public enum ChatListSearchEntry: Comparable, Identifiable { } else { enabled = false } + if requiresPremiumForMessaging { + enabled = false + } } if filter.contains(.onlyPrivateChats) { if let peer = chatPeer { @@ -572,12 +582,14 @@ public enum ChatListSearchEntry: Comparable, Identifiable { header = ChatListSearchItemHeader(type: headerType, theme: theme, strings: strings, actionTitle: nil, action: nil) } - return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: false), peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: .none, badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { contactPeer in + return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: false), peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: .none, badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { contactPeer in if case let .peer(maybePeer, maybeChatPeer) = contactPeer, let peer = maybePeer, let chatPeer = maybeChatPeer { interaction.peerSelected(chatPeer, peer, nil, nil) } else { interaction.peerSelected(peer, nil, nil, nil) } + }, disabledAction: { _ in + interaction.disabledPeerSelected(peer, nil, requiresPremiumForMessaging ? .premiumRequired : .generic) }, contextAction: peerContextAction.flatMap { peerContextAction in return { node, gesture, location in if let chatPeer = chatPeer, chatPeer.id.namespace != Namespaces.Peer.SecretChat { @@ -596,7 +608,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { openStories(peer.id, sourceNode.avatarNode) } }) - case let .localPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, storyStats): + case let .localPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, storyStats, requiresPremiumForMessaging): let primaryPeer: EnginePeer var chatPeer: EnginePeer? if let associatedPeer = associatedPeer { @@ -614,6 +626,9 @@ public enum ChatListSearchEntry: Comparable, Identifiable { } else { enabled = false } + if requiresPremiumForMessaging { + enabled = false + } } if filter.contains(.onlyPrivateChats) { if let peer = chatPeer { @@ -676,12 +691,14 @@ public enum ChatListSearchEntry: Comparable, Identifiable { isSavedMessages = true } - return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: .none, badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { contactPeer in + return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: .none, badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { contactPeer in if case let .peer(maybePeer, maybeChatPeer) = contactPeer, let peer = maybePeer, let chatPeer = maybeChatPeer { interaction.peerSelected(chatPeer, peer, nil, nil) } else { interaction.peerSelected(peer, nil, nil, nil) } + }, disabledAction: { _ in + interaction.disabledPeerSelected(peer, nil, requiresPremiumForMessaging ? .premiumRequired : .generic) }, contextAction: peerContextAction.flatMap { peerContextAction in return { node, gesture, location in if let chatPeer = chatPeer, chatPeer.id.namespace != Namespaces.Peer.SecretChat { @@ -700,10 +717,13 @@ public enum ChatListSearchEntry: Comparable, Identifiable { openStories(peer.id, sourceNode.avatarNode) } }) - case let .globalPeer(peer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, storyStats): + case let .globalPeer(peer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, storyStats, requiresPremiumForMessaging): var enabled = true if filter.contains(.onlyWriteable) { enabled = canSendMessagesToPeer(peer.peer) + if requiresPremiumForMessaging { + enabled = false + } } if filter.contains(.onlyPrivateChats) { if !(peer.peer is TelegramUser || peer.peer is TelegramSecretChat) { @@ -757,8 +777,10 @@ public enum ChatListSearchEntry: Comparable, Identifiable { isSavedMessages = true } - return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: EnginePeer(peer.peer), chatPeer: EnginePeer(peer.peer)), status: .addressName(suffixString), badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in + return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: EnginePeer(peer.peer), chatPeer: EnginePeer(peer.peer)), status: .addressName(suffixString), badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in interaction.peerSelected(EnginePeer(peer.peer), nil, nil, nil) + }, disabledAction: { _ in + interaction.disabledPeerSelected(EnginePeer(peer.peer), nil, requiresPremiumForMessaging ? .premiumRequired : .generic) }, contextAction: peerContextAction.flatMap { peerContextAction in return { node, gesture, location in peerContextAction(EnginePeer(peer.peer), .search(nil), node, gesture, location) @@ -773,7 +795,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { openStories(peer.id, sourceNode.avatarNode) } }) - case let .message(message, peer, readState, threadInfo, presentationData, _, selected, displayCustomHeader, orderingKey, _, _, allPaused, storyStats): + case let .message(message, peer, readState, threadInfo, presentationData, _, selected, displayCustomHeader, orderingKey, _, _, allPaused, storyStats, requiresPremiumForMessaging): let header: ChatListSearchItemHeader switch orderingKey { case .downloading: @@ -858,7 +880,8 @@ public enum ChatListSearchEntry: Comparable, Identifiable { ), hasUnseenCloseFriends: stats.hasUnseenCloseFriends ) - } + }, + requiresPremiumForMessaging: requiresPremiumForMessaging )), editing: false, hasActiveRevealControls: false, selected: false, header: tagMask == nil ? header : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction) } case let .addContact(phoneNumber, theme, strings): @@ -897,7 +920,7 @@ public struct ChatListSearchContainerTransition { } } -private func chatListSearchContainerPreparedRecentTransition(from fromEntries: [ChatListRecentEntry], to toEntries: [ChatListRecentEntry], context: AccountContext, presentationData: ChatListPresentationData, filter: ChatListNodePeersFilter, peerSelected: @escaping (EnginePeer, Int64?) -> Void, disabledPeerSelected: @escaping (EnginePeer, Int64?) -> Void, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, deletePeer: @escaping (EnginePeer.Id) -> Void, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, openStories: @escaping (EnginePeer.Id, AvatarNode) -> Void) -> ChatListSearchContainerRecentTransition { +private func chatListSearchContainerPreparedRecentTransition(from fromEntries: [ChatListRecentEntry], to toEntries: [ChatListRecentEntry], context: AccountContext, presentationData: ChatListPresentationData, filter: ChatListNodePeersFilter, peerSelected: @escaping (EnginePeer, Int64?) -> Void, disabledPeerSelected: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, deletePeer: @escaping (EnginePeer.Id) -> Void, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, openStories: @escaping (EnginePeer.Id, AvatarNode) -> Void) -> ChatListSearchContainerRecentTransition { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } @@ -1382,7 +1405,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { resource = (resourceValue.id.stringRepresentation, size, entries.isEmpty) } - entries.append(.message(message, peer, nil, nil, presentationData, 1, nil, false, .downloading(item.priority), resource, .downloading, allPaused, nil)) + entries.append(.message(message, peer, nil, nil, presentationData, 1, nil, false, .downloading(item.priority), resource, .downloading, allPaused, nil, false)) } for item in downloadItems.doneItems.sorted(by: { ChatListSearchEntry.MessageOrderingKey.downloaded(timestamp: $0.timestamp, index: $0.message.index) < ChatListSearchEntry.MessageOrderingKey.downloaded(timestamp: $1.timestamp, index: $1.message.index) }) { if !item.isSeen { @@ -1410,7 +1433,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } } - entries.append(.message(message, peer, nil, nil, presentationData, 1, selectionState?.contains(message.id), false, .downloaded(timestamp: item.timestamp, index: message.index), (item.resourceId, item.size, false), .recentlyDownloaded, false, nil)) + entries.append(.message(message, peer, nil, nil, presentationData, 1, selectionState?.contains(message.id), false, .downloaded(timestamp: item.timestamp, index: message.index), (item.resourceId, item.size, false), .recentlyDownloaded, false, nil, false)) } return (entries.sorted(), false) } @@ -1986,7 +2009,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if lowercasedQuery.count > 1 && (presentationData.strings.DialogList_SavedMessages.lowercased().hasPrefix(lowercasedQuery) || "saved messages".hasPrefix(lowercasedQuery)) { if !existingPeerIds.contains(accountPeer.id), filteredPeer(EnginePeer(accountPeer), EnginePeer(accountPeer)) { existingPeerIds.insert(accountPeer.id) - entries.append(.localPeer(EnginePeer(accountPeer), nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil)) + entries.append(.localPeer(EnginePeer(accountPeer), nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false)) index += 1 } } @@ -2004,7 +2027,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { associatedPeer = renderedPeer.peers[associatedPeerId] } - entries.append(.recentlySearchedPeer(peer, associatedPeer, foundLocalPeers.unread[peer.id], index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, nil)) + entries.append(.recentlySearchedPeer(peer, associatedPeer, foundLocalPeers.unread[peer.id], index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, nil, false)) index += 1 } @@ -2029,7 +2052,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if matches { existingPeerIds.insert(peer.id) - entries.append(.localPeer(peer, nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil)) + entries.append(.localPeer(peer, nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false)) } } } @@ -2052,7 +2075,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { associatedPeer = renderedPeer.peers[associatedPeerId] } - entries.append(.localPeer(peer, associatedPeer, foundLocalPeers.unread[peer.id], index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil)) + entries.append(.localPeer(peer, associatedPeer, foundLocalPeers.unread[peer.id], index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false)) index += 1 numberOfLocalPeers += 1 } @@ -2066,7 +2089,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if !existingPeerIds.contains(peer.peer.id), filteredPeer(EnginePeer(peer.peer), EnginePeer(accountPeer)) { existingPeerIds.insert(peer.peer.id) - entries.append(.localPeer(EnginePeer(peer.peer), nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil)) + entries.append(.localPeer(EnginePeer(peer.peer), nil, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType, nil, false)) index += 1 numberOfLocalPeers += 1 } @@ -2083,7 +2106,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if !existingPeerIds.contains(peer.peer.id), filteredPeer(EnginePeer(peer.peer), EnginePeer(accountPeer)) { existingPeerIds.insert(peer.peer.id) - entries.append(.globalPeer(peer, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, globalExpandType, nil)) + entries.append(.globalPeer(peer, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, globalExpandType, nil, false)) index += 1 numberOfGlobalPeers += 1 } @@ -2097,7 +2120,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { peer = EngineRenderedPeer(peer: EnginePeer(channelPeer)) } } - entries.append(.message(message, peer, nil, nil, presentationData, 1, nil, true, .index(message.index), nil, .generic, false, nil)) + //TODO:requiresPremiumForMessaging + entries.append(.message(message, peer, nil, nil, presentationData, 1, nil, true, .index(message.index), nil, .generic, false, nil, false)) index += 1 } @@ -2128,7 +2152,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } } - entries.append(.message(message, peer, foundRemoteMessageSet.readCounters[message.id.peerId], foundRemoteMessageSet.threadsData[message.id]?.info, presentationData, foundRemoteMessageSet.totalCount, selectionState?.contains(message.id), headerId == firstHeaderId, .index(message.index), nil, .generic, false, nil)) + //TODO:requiresPremiumForMessaging + entries.append(.message(message, peer, foundRemoteMessageSet.readCounters[message.id.peerId], foundRemoteMessageSet.threadsData[message.id]?.info, presentationData, foundRemoteMessageSet.totalCount, selectionState?.contains(message.id), headerId == firstHeaderId, .index(message.index), nil, .generic, false, nil, false)) index += 1 } } @@ -2221,7 +2246,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { break } self?.listNode.clearHighlightAnimated(true) - }, disabledPeerSelected: { _, _ in + }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in @@ -2361,7 +2386,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { var fetchResourceId: (id: String, size: Int64, isFirstInList: Bool)? for entry in currentEntries { switch entry { - case let .message(m, _, _, _, _, _, _, _, _, resource, _, _, _): + case let .message(m, _, _, _, _, _, _, _, _, resource, _, _, _, _): if m.id == message.id { fetchResourceId = resource } @@ -2409,17 +2434,30 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { return .single(nil) } var storyStatsIds: [EnginePeer.Id] = [] + var requiresPremiumForMessagingPeerIds: [EnginePeer.Id] = [] for item in items { switch item { - case let .recentlySearchedPeer(peer, _, _, _, _, _, _, _, _): + case let .recentlySearchedPeer(peer, _, _, _, _, _, _, _, _, _): storyStatsIds.append(peer.id) - case let .localPeer(peer, _, _, _, _, _, _, _, _, _): + if case let .user(user) = peer, user.flags.contains(.requirePremium) { + requiresPremiumForMessagingPeerIds.append(peer.id) + } + case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _): storyStatsIds.append(peer.id) - case let .globalPeer(foundPeer, _, _, _, _, _, _, _, _): + if case let .user(user) = peer, user.flags.contains(.requirePremium) { + requiresPremiumForMessagingPeerIds.append(peer.id) + } + case let .globalPeer(foundPeer, _, _, _, _, _, _, _, _, _): storyStatsIds.append(foundPeer.peer.id) - case let .message(_, peer, _, _, _, _, _, _, _, _, _, _, _): + if let user = foundPeer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + requiresPremiumForMessagingPeerIds.append(foundPeer.peer.id) + } + case let .message(_, peer, _, _, _, _, _, _, _, _, _, _, _, _): if let peer = peer.peer { storyStatsIds.append(peer.id) + if case let .user(user) = peer, user.flags.contains(.requirePremium) { + requiresPremiumForMessagingPeerIds.append(peer.id) + } } default: break @@ -2430,20 +2468,30 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { return context.engine.data.subscribe( EngineDataMap( storyStatsIds.map(TelegramEngine.EngineData.Item.Peer.StoryStats.init(id:)) + ), + EngineDataMap( + requiresPremiumForMessagingPeerIds.map(TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging.init(id:)) ) ) - |> map { stats -> ([ChatListSearchEntry], Bool)? in + |> map { stats, requiresPremiumForMessaging -> ([ChatListSearchEntry], Bool)? in + var requiresPremiumForMessaging = requiresPremiumForMessaging + if !peersFilter.contains(.onlyWriteable) { + requiresPremiumForMessaging = [:] + } else { + context.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: requiresPremiumForMessagingPeerIds) + } + var mappedItems = items for i in 0 ..< mappedItems.count { switch mappedItems[i] { - case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, _): - mappedItems[i] = .recentlySearchedPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, stats[peer.id] ?? nil) - case let .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _): - mappedItems[i] = .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.id] ?? nil) - case let .globalPeer(peer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _): - mappedItems[i] = .globalPeer(peer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.peer.id] ?? nil) - case let .message(message, peer, combinedPeerReadState, threadInfo, presentationData, totalCount, selected, displayCustomHeader, key, resourceId, section, allPaused, _): - mappedItems[i] = .message(message, peer, combinedPeerReadState, threadInfo, presentationData, totalCount, selected, displayCustomHeader, key, resourceId, section, allPaused, stats[peer.peerId] ?? nil) + case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, _, _): + mappedItems[i] = .recentlySearchedPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, stats[peer.id] ?? nil, requiresPremiumForMessaging[peer.id] ?? false) + case let .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _, _): + mappedItems[i] = .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.id] ?? nil, requiresPremiumForMessaging[peer.id] ?? false) + case let .globalPeer(peer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _, _): + mappedItems[i] = .globalPeer(peer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.peer.id] ?? nil, requiresPremiumForMessaging[peer.peer.id] ?? false) + case let .message(message, peer, combinedPeerReadState, threadInfo, presentationData, totalCount, selected, displayCustomHeader, key, resourceId, section, allPaused, _, _): + mappedItems[i] = .message(message, peer, combinedPeerReadState, threadInfo, presentationData, totalCount, selected, displayCustomHeader, key, resourceId, section, allPaused, stats[peer.peerId] ?? nil, requiresPremiumForMessaging[peer.peerId] ?? false) default: break } @@ -2473,7 +2521,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if let entries = entriesAndFlags { var filteredEntries: [ChatListSearchEntry] = [] for entry in entries { - if case let .localPeer(peer, _, _, _, _, _, _, _, _, _) = entry { + if case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _) = entry { peers.append(peer) } else if case .globalPeer = entry { } else { @@ -2588,7 +2636,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { var messages: [EngineMessage] = [] for entry in newEntries { - if case let .message(message, _, _, _, _, _, _, _, _, _, _, _, _) = entry { + if case let .message(message, _, _, _, _, _, _, _, _, _, _, _, _, _) = entry { messages.append(message) } } @@ -2610,13 +2658,28 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { var recentItems = combineLatest( hasRecentPeers, - fixedRecentlySearchedPeers |> mapToSignal { peers -> Signal<([RecentlySearchedPeer], [EnginePeer.Id: PeerStoryStats]), NoError> in + fixedRecentlySearchedPeers |> mapToSignal { peers -> Signal<([RecentlySearchedPeer], [EnginePeer.Id: PeerStoryStats], [EnginePeer.Id: Bool], Set), NoError> in return context.engine.data.subscribe( EngineDataMap(peers.map(\.peer.peerId).map { id in return TelegramEngine.EngineData.Item.Peer.StoryStats(id: id) + }), + EngineDataMap(peers.map(\.peer.peerId).map { id in + return TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging(id: id) }) ) - |> map { stats -> ([RecentlySearchedPeer], [EnginePeer.Id: PeerStoryStats]) in + |> map { stats, isPremiumRequiredForMessaging -> ([RecentlySearchedPeer], [EnginePeer.Id: PeerStoryStats], [EnginePeer.Id: Bool], Set) in + var isPremiumRequiredForMessaging = isPremiumRequiredForMessaging + var refreshIsPremiumRequiredForMessaging = Set() + if !peersFilter.contains(.onlyWriteable) { + isPremiumRequiredForMessaging = [:] + } else { + for peer in peers { + if let user = peer.peer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + refreshIsPremiumRequiredForMessaging.insert(user.id) + } + } + } + var mappedStats: [EnginePeer.Id: PeerStoryStats] = [:] for (id, value) in stats { if id == context.account.peerId { @@ -2626,14 +2689,22 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { mappedStats[id] = value } } - return (peers, mappedStats) + var mappedIsPremiumRequiredForMessaging: [EnginePeer.Id: Bool] = [:] + for (id, value) in isPremiumRequiredForMessaging { + mappedIsPremiumRequiredForMessaging[id] = value + } + return (peers, mappedStats, mappedIsPremiumRequiredForMessaging, refreshIsPremiumRequiredForMessaging) } }, presentationDataPromise.get(), context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()) ) |> mapToSignal { hasRecentPeers, peersAndStories, presentationData, globalNotificationSettings -> Signal<[ChatListRecentEntry], NoError> in - let (peers, peerStoryStats) = peersAndStories + let (peers, peerStoryStats, requiresPremiumForMessaging, refreshIsPremiumRequiredForMessaging) = peersAndStories + + if !refreshIsPremiumRequiredForMessaging.isEmpty { + context.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: Array(refreshIsPremiumRequiredForMessaging)) + } var entries: [ChatListRecentEntry] = [] if !peersFilter.contains(.onlyGroups) { @@ -2653,7 +2724,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } peerIds.insert(peer.id) - entries.append(.peer(index: index, peer: searchedPeer, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameSortOrder, presentationData.nameDisplayOrder, globalNotificationSettings, peerStoryStats[peer.id])) + entries.append(.peer(index: index, peer: searchedPeer, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameSortOrder, presentationData.nameDisplayOrder, globalNotificationSettings, peerStoryStats[peer.id], requiresPremiumForMessaging[peer.id] ?? false)) index += 1 } } @@ -2692,8 +2763,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } } self?.recentListNode.clearHighlightAnimated(true) - }, disabledPeerSelected: { peer, threadId in - interaction.openDisabledPeer(peer, threadId) + }, disabledPeerSelected: { peer, threadId, reason in + interaction.openDisabledPeer(peer, threadId, reason) }, peerContextAction: { peer, source, node, gesture, location in if let peerContextAction = interaction.peerContextAction { peerContextAction(peer, source, node, gesture, location) @@ -3608,7 +3679,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode { let timestamp1: Int32 = 100000 var peers: [EnginePeer.Id: EnginePeer] = [:] peers[peer1.id] = peer1 - let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in + let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in }, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in gesture?.cancel() }, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {}, openPasswordSetup: {}, openPremiumIntro: {}, openPremiumGift: {}, openActiveSessions: { @@ -3672,7 +3743,8 @@ public final class ChatListSearchShimmerNode: ASDisplayNode { forumTopicData: nil, topForumTopicItems: [], autoremoveTimeout: nil, - storyState: nil + storyState: nil, + requiresPremiumForMessaging: false )), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction) case .media: return nil diff --git a/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift b/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift index 0beacce7f5..89a88281c9 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift @@ -702,7 +702,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, UIScrollViewDelegate { var index: UInt32 = 0 if let entries = entries { for entry in entries { - if case let .message(message, _, _, _, _, _, _, _, _, _, _, _, _) = entry { + if case let .message(message, _, _, _, _, _, _, _, _, _, _, _, _, _) = entry { self.mediaItems.append(VisualMediaItem(message: message._asMessage(), index: nil)) } index += 1 diff --git a/submodules/ChatListUI/Sources/ChatListShimmerNode.swift b/submodules/ChatListUI/Sources/ChatListShimmerNode.swift index 1d2dea85df..53f89b3dea 100644 --- a/submodules/ChatListUI/Sources/ChatListShimmerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListShimmerNode.swift @@ -153,7 +153,7 @@ public final class ChatListShimmerNode: ASDisplayNode { let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) let timestamp1: Int32 = 100000 let peers: [EnginePeer.Id: EnginePeer] = [:] - let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in + let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in }, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in gesture?.cancel() }, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {}, openPasswordSetup: {}, openPremiumIntro: {}, openPremiumGift: {}, openActiveSessions: {}, performActiveSessionAction: { _, _ in }, openChatFolderUpdates: {}, hideChatFolderUpdates: {}, openStories: { _, _ in }, dismissNotice: { _ in @@ -207,7 +207,8 @@ public final class ChatListShimmerNode: ASDisplayNode { forumTopicData: nil, topForumTopicItems: [], autoremoveTimeout: nil, - storyState: nil + storyState: nil, + requiresPremiumForMessaging: false )), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction) } diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 77d1077e14..960fdae28f 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -96,6 +96,7 @@ public enum ChatListItemContent { public var topForumTopicItems: [EngineChatList.ForumTopicData] public var autoremoveTimeout: Int32? public var storyState: StoryState? + public var requiresPremiumForMessaging: Bool public init( messages: [EngineMessage], @@ -115,7 +116,8 @@ public enum ChatListItemContent { forumTopicData: EngineChatList.ForumTopicData?, topForumTopicItems: [EngineChatList.ForumTopicData], autoremoveTimeout: Int32?, - storyState: StoryState? + storyState: StoryState?, + requiresPremiumForMessaging: Bool ) { self.messages = messages self.peer = peer @@ -135,6 +137,7 @@ public enum ChatListItemContent { self.topForumTopicItems = topForumTopicItems self.autoremoveTimeout = autoremoveTimeout self.storyState = storyState + self.requiresPremiumForMessaging = requiresPremiumForMessaging } } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 16dff19e41..01fc0c5016 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -74,7 +74,7 @@ public final class ChatListNodeInteraction { let activateSearch: () -> Void let peerSelected: (EnginePeer, EnginePeer?, Int64?, ChatListNodeEntryPromoInfo?) -> Void - let disabledPeerSelected: (EnginePeer, Int64?) -> Void + let disabledPeerSelected: (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void let togglePeerSelected: (EnginePeer, Int64?) -> Void let togglePeersSelection: ([PeerEntry], Bool) -> Void let additionalCategorySelected: (Int) -> Void @@ -126,7 +126,7 @@ public final class ChatListNodeInteraction { animationRenderer: MultiAnimationRenderer, activateSearch: @escaping () -> Void, peerSelected: @escaping (EnginePeer, EnginePeer?, Int64?, ChatListNodeEntryPromoInfo?) -> Void, - disabledPeerSelected: @escaping (EnginePeer, Int64?) -> Void, + disabledPeerSelected: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, togglePeerSelected: @escaping (EnginePeer, Int64?) -> Void, togglePeersSelection: @escaping ([PeerEntry], Bool) -> Void, additionalCategorySelected: @escaping (Int) -> Void, @@ -426,7 +426,8 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL stats: storyState.stats, hasUnseenCloseFriends: storyState.hasUnseenCloseFriends ) - } + }, + requiresPremiumForMessaging: peerEntry.requiresPremiumForMessaging )), editing: editing, hasActiveRevealControls: hasActiveRevealControls, @@ -453,6 +454,9 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL if !canSendMessagesToPeer(peer._asPeer()) { enabled = false } + if peerEntry.requiresPremiumForMessaging { + enabled = false + } } else { enabled = false } @@ -598,7 +602,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL } }, disabledAction: isForum && editing ? nil : { _ in if let chatPeer = chatPeer { - nodeInteraction.disabledPeerSelected(chatPeer, threadId) + nodeInteraction.disabledPeerSelected(chatPeer, threadId, .generic) } }, animationCache: nodeInteraction.animationCache, @@ -791,7 +795,8 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL stats: storyState.stats, hasUnseenCloseFriends: storyState.hasUnseenCloseFriends ) - } + }, + requiresPremiumForMessaging: peerEntry.requiresPremiumForMessaging )), editing: editing, hasActiveRevealControls: hasActiveRevealControls, @@ -818,6 +823,9 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL if !canSendMessagesToPeer(peer._asPeer()) { enabled = false } + if peerEntry.requiresPremiumForMessaging { + enabled = false + } } else { enabled = false } @@ -917,7 +925,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL } }, disabledAction: isForum && editing ? nil : { _ in if let chatPeer = chatPeer { - nodeInteraction.disabledPeerSelected(chatPeer, threadId) + nodeInteraction.disabledPeerSelected(chatPeer, threadId, .generic) } }, animationCache: nodeInteraction.animationCache, @@ -1137,7 +1145,7 @@ public final class ChatListNode: ListView { } public var peerSelected: ((EnginePeer, Int64?, Bool, Bool, ChatListNodeEntryPromoInfo?) -> Void)? - public var disabledPeerSelected: ((EnginePeer, Int64?) -> Void)? + public var disabledPeerSelected: ((EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void)? public var additionalCategorySelected: ((Int) -> Void)? public var groupSelected: ((EngineChatList.Group) -> Void)? public var addContact: ((String) -> Void)? @@ -1316,9 +1324,9 @@ public final class ChatListNode: ListView { if let strongSelf = self, let peerSelected = strongSelf.peerSelected { peerSelected(peer, threadId, true, true, promoInfo) } - }, disabledPeerSelected: { [weak self] peer, threadId in + }, disabledPeerSelected: { [weak self] peer, threadId, reason in if let strongSelf = self, let disabledPeerSelected = strongSelf.disabledPeerSelected { - disabledPeerSelected(peer, threadId) + disabledPeerSelected(peer, threadId, reason) } }, togglePeerSelected: { [weak self] peer, _ in guard let strongSelf = self else { diff --git a/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift b/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift index b8007ffcae..5bd0ba108b 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift @@ -114,6 +114,7 @@ enum ChatListNodeEntry: Comparable, Identifiable { var topForumTopicItems: [EngineChatList.ForumTopicData] var revealed: Bool var storyState: ChatListNodeState.StoryState? + var requiresPremiumForMessaging: Bool init( index: EngineChatList.Item.Index, @@ -138,7 +139,8 @@ enum ChatListNodeEntry: Comparable, Identifiable { forumTopicData: EngineChatList.ForumTopicData?, topForumTopicItems: [EngineChatList.ForumTopicData], revealed: Bool, - storyState: ChatListNodeState.StoryState? + storyState: ChatListNodeState.StoryState?, + requiresPremiumForMessaging: Bool ) { self.index = index self.presentationData = presentationData @@ -163,6 +165,7 @@ enum ChatListNodeEntry: Comparable, Identifiable { self.topForumTopicItems = topForumTopicItems self.revealed = revealed self.storyState = storyState + self.requiresPremiumForMessaging = requiresPremiumForMessaging } static func ==(lhs: PeerEntryData, rhs: PeerEntryData) -> Bool { @@ -275,6 +278,9 @@ enum ChatListNodeEntry: Comparable, Identifiable { if lhs.storyState != rhs.storyState { return false } + if lhs.requiresPremiumForMessaging != rhs.requiresPremiumForMessaging { + return false + } return true } } @@ -701,7 +707,8 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState, stats: stats, hasUnseenCloseFriends: stats.hasUnseenCloseFriends ) - } + }, + requiresPremiumForMessaging: false )) if let threadInfo, threadInfo.isHidden { @@ -751,7 +758,8 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState, forumTopicData: nil, topForumTopicItems: [], revealed: false, - storyState: nil + storyState: nil, + requiresPremiumForMessaging: false ))) if foundPinningIndex != 0 { foundPinningIndex -= 1 @@ -782,7 +790,8 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState, forumTopicData: nil, topForumTopicItems: [], revealed: false, - storyState: nil + storyState: nil, + requiresPremiumForMessaging: false ))) } else { if !filteredAdditionalItemEntries.isEmpty { @@ -833,7 +842,8 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState, forumTopicData: item.item.forumTopicData, topForumTopicItems: item.item.topForumTopicItems, revealed: state.hiddenItemShouldBeTemporaryRevealed || state.editing, - storyState: nil + storyState: nil, + requiresPremiumForMessaging: false ))) if pinningIndex != 0 { pinningIndex -= 1 diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift index b344137731..30314949a0 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift @@ -171,6 +171,7 @@ public final class ChatPanelInterfaceInteraction { public let addDoNotTranslateLanguage: (String) -> Void public let hideTranslationPanel: () -> Void public let openPremiumGift: () -> Void + public let openPremiumRequiredForMessaging: () -> Void public let updateHistoryFilter: ((ChatPresentationInterfaceState.HistoryFilter?) -> ChatPresentationInterfaceState.HistoryFilter?) -> Void public let requestLayout: (ContainedViewLayoutTransition) -> Void public let chatController: () -> ViewController? @@ -279,6 +280,7 @@ public final class ChatPanelInterfaceInteraction { addDoNotTranslateLanguage: @escaping (String) -> Void, hideTranslationPanel: @escaping () -> Void, openPremiumGift: @escaping () -> Void, + openPremiumRequiredForMessaging: @escaping () -> Void, updateHistoryFilter: @escaping ((ChatPresentationInterfaceState.HistoryFilter?) -> ChatPresentationInterfaceState.HistoryFilter?) -> Void, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, chatController: @escaping () -> ViewController?, @@ -386,6 +388,7 @@ public final class ChatPanelInterfaceInteraction { self.addDoNotTranslateLanguage = addDoNotTranslateLanguage self.hideTranslationPanel = hideTranslationPanel self.openPremiumGift = openPremiumGift + self.openPremiumRequiredForMessaging = openPremiumRequiredForMessaging self.updateHistoryFilter = updateHistoryFilter self.requestLayout = requestLayout @@ -501,6 +504,7 @@ public final class ChatPanelInterfaceInteraction { }, addDoNotTranslateLanguage: { _ in }, hideTranslationPanel: { }, openPremiumGift: { + }, openPremiumRequiredForMessaging: { }, updateHistoryFilter: { _ in }, requestLayout: { _ in }, chatController: { diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift index 29d2e8fd0d..2ad9cc52e2 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift @@ -430,6 +430,8 @@ public final class ChatPresentationInterfaceState: Equatable { public let replyMessage: Message? public let accountPeerColor: AccountPeerColor? public let savedMessagesTopicPeer: EnginePeer? + public let hasSearchTags: Bool + public let isPremiumRequiredForMessaging: Bool 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?, replyMessage: Message?, accountPeerColor: AccountPeerColor?) { self.interfaceState = ChatInterfaceState() @@ -506,9 +508,11 @@ public final class ChatPresentationInterfaceState: Equatable { self.replyMessage = replyMessage self.accountPeerColor = accountPeerColor self.savedMessagesTopicPeer = nil + self.hasSearchTags = false + self.isPremiumRequiredForMessaging = false } - 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: UrlPreview?, editingUrlPreview: UrlPreview?, search: ChatSearchData?, searchQuerySuggestionResult: ChatPresentationInputQueryResult?, historyFilter: HistoryFilter?, 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, premiumGiftOptions: [CachedPremiumGiftOption], suggestPremiumGift: Bool, forceInputCommandsHidden: Bool, voiceMessagesAvailable: Bool, customEmojiAvailable: Bool, threadData: ThreadData?, forumTopicData: ThreadData?, isGeneralThreadClosed: Bool?, translationState: ChatPresentationTranslationState?, replyMessage: Message?, accountPeerColor: AccountPeerColor?, savedMessagesTopicPeer: EnginePeer?) { + 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: UrlPreview?, editingUrlPreview: UrlPreview?, search: ChatSearchData?, searchQuerySuggestionResult: ChatPresentationInputQueryResult?, historyFilter: HistoryFilter?, 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, premiumGiftOptions: [CachedPremiumGiftOption], suggestPremiumGift: Bool, forceInputCommandsHidden: Bool, voiceMessagesAvailable: Bool, customEmojiAvailable: Bool, threadData: ThreadData?, forumTopicData: ThreadData?, isGeneralThreadClosed: Bool?, translationState: ChatPresentationTranslationState?, replyMessage: Message?, accountPeerColor: AccountPeerColor?, savedMessagesTopicPeer: EnginePeer?, hasSearchTags: Bool, isPremiumRequiredForMessaging: Bool) { self.interfaceState = interfaceState self.chatLocation = chatLocation self.renderedPeer = renderedPeer @@ -583,6 +587,8 @@ public final class ChatPresentationInterfaceState: Equatable { self.replyMessage = replyMessage self.accountPeerColor = accountPeerColor self.savedMessagesTopicPeer = savedMessagesTopicPeer + self.hasSearchTags = hasSearchTags + self.isPremiumRequiredForMessaging = isPremiumRequiredForMessaging } public static func ==(lhs: ChatPresentationInterfaceState, rhs: ChatPresentationInterfaceState) -> Bool { @@ -814,35 +820,41 @@ public final class ChatPresentationInterfaceState: Equatable { if lhs.savedMessagesTopicPeer != rhs.savedMessagesTopicPeer { return false } + if lhs.hasSearchTags != rhs.hasSearchTags { + return false + } + if lhs.isPremiumRequiredForMessaging != rhs.isPremiumRequiredForMessaging { + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } public func updatedInputQueryResult(queryKind: ChatPresentationInputQueryKind, _ f: (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?) -> ChatPresentationInterfaceState { @@ -854,239 +866,247 @@ 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } public func updatedUrlPreview(_ urlPreview: UrlPreview?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } public func updatedEditingUrlPreview(_ editingUrlPreview: UrlPreview?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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), historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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), historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } public func updatedHistoryFilter(_ historyFilter: HistoryFilter?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } public func updatedPremiumGiftOptions(_ premiumGiftOptions: [CachedPremiumGiftOption]) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } public func updatedSuggestPremiumGift(_ suggestPremiumGift: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } public func updatedForumTopicData(_ forumTopicData: ThreadData?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } public func updatedReplyMessage(_ replyMessage: Message?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } public func updatedAccountPeerColor(_ accountPeerColor: AccountPeerColor?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) } public func updatedSavedMessagesTopicPeer(_ savedMessagesTopicPeer: EnginePeer?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: savedMessagesTopicPeer) + 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) + } + + public func updatedHasSearchTags(_ hasSearchTags: Bool) -> ChatPresentationInterfaceState { + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: hasSearchTags, isPremiumRequiredForMessaging: self.isPremiumRequiredForMessaging) + } + + public func updatedIsPremiumRequiredForMessaging(_ isPremiumRequiredForMessaging: Bool) -> ChatPresentationInterfaceState { + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, 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, historyFilter: self.historyFilter, 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, premiumGiftOptions: self.premiumGiftOptions, suggestPremiumGift: self.suggestPremiumGift, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable, customEmojiAvailable: self.customEmojiAvailable, threadData: self.threadData, forumTopicData: self.forumTopicData, isGeneralThreadClosed: self.isGeneralThreadClosed, translationState: self.translationState, replyMessage: self.replyMessage, accountPeerColor: self.accountPeerColor, savedMessagesTopicPeer: self.savedMessagesTopicPeer, hasSearchTags: self.hasSearchTags, isPremiumRequiredForMessaging: isPremiumRequiredForMessaging) } } diff --git a/submodules/ComponentFlow/Source/Components/VStack.swift b/submodules/ComponentFlow/Source/Components/VStack.swift index bf54722e38..1dd0e3d31d 100644 --- a/submodules/ComponentFlow/Source/Components/VStack.swift +++ b/submodules/ComponentFlow/Source/Components/VStack.swift @@ -1,14 +1,22 @@ import Foundation import UIKit +public enum VStackAlignment { + case left + case center + case right +} + public final class VStack: CombinedComponent { public typealias EnvironmentType = ChildEnvironment private let items: [AnyComponentWithIdentity] + private let alignment: VStackAlignment private let spacing: CGFloat - public init(_ items: [AnyComponentWithIdentity], spacing: CGFloat) { + public init(_ items: [AnyComponentWithIdentity], alignment: VStackAlignment = .center, spacing: CGFloat) { self.items = items + self.alignment = alignment self.spacing = spacing } @@ -16,6 +24,9 @@ public final class VStack: CombinedComponent { if lhs.items != rhs.items { return false } + if lhs.alignment != rhs.alignment { + return false + } if lhs.spacing != rhs.spacing { return false } @@ -45,8 +56,17 @@ public final class VStack: CombinedComponent { var nextY = 0.0 for child in updatedChildren { + let childFrame: CGRect + switch context.component.alignment { + case .left: + childFrame = CGRect(origin: CGPoint(x: 0.0, y: nextY), size: child.size) + case .center: + childFrame = CGRect(origin: CGPoint(x: floor((size.width - child.size.width) * 0.5), y: nextY), size: child.size) + case .right: + childFrame = CGRect(origin: CGPoint(x: size.width - child.size.width, y: nextY), size: child.size) + } context.add(child - .position(child.size.centered(in: CGRect(origin: CGPoint(x: floor((size.width - child.size.width) * 0.5), y: nextY), size: child.size)).center) + .position(childFrame.center) .appear(.default(scale: true, alpha: true)) .disappear(.default(scale: true, alpha: true)) ) diff --git a/submodules/ContactListUI/Sources/ContactListNode.swift b/submodules/ContactListUI/Sources/ContactListNode.swift index 44bd193ef4..58f6510707 100644 --- a/submodules/ContactListUI/Sources/ContactListNode.swift +++ b/submodules/ContactListUI/Sources/ContactListNode.swift @@ -57,17 +57,19 @@ private final class ContactListNodeInteraction { fileprivate let authorize: () -> Void fileprivate let suppressWarning: () -> Void fileprivate let openPeer: (ContactListPeer, ContactListAction) -> Void + fileprivate let openDisabledPeer: (EnginePeer, ChatListDisabledPeerReason) -> Void fileprivate let contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?, Bool) -> Void)? fileprivate let openStories: (EnginePeer, ASDisplayNode) -> Void fileprivate let deselectAll: () -> Void let itemHighlighting = ContactItemHighlighting() - init(activateSearch: @escaping () -> Void, authorize: @escaping () -> Void, suppressWarning: @escaping () -> Void, openPeer: @escaping (ContactListPeer, ContactListAction) -> Void, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?, Bool) -> Void)?, openStories: @escaping (EnginePeer, ASDisplayNode) -> Void, deselectAll: @escaping () -> Void) { + init(activateSearch: @escaping () -> Void, authorize: @escaping () -> Void, suppressWarning: @escaping () -> Void, openPeer: @escaping (ContactListPeer, ContactListAction) -> Void, openDisabledPeer: @escaping (EnginePeer, ChatListDisabledPeerReason) -> Void, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?, Bool) -> Void)?, openStories: @escaping (EnginePeer, ASDisplayNode) -> Void, deselectAll: @escaping () -> Void) { self.activateSearch = activateSearch self.authorize = authorize self.suppressWarning = suppressWarning self.openPeer = openPeer + self.openDisabledPeer = openDisabledPeer self.contextAction = contextAction self.openStories = openStories self.deselectAll = deselectAll @@ -92,7 +94,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable { case permissionInfo(PresentationTheme, String, String, Bool) case permissionEnable(PresentationTheme, String) case option(Int, ContactListAdditionalOption, ListViewItemHeader?, PresentationTheme, PresentationStrings) - case peer(Int, ContactListPeer, EnginePeer.Presence?, ListViewItemHeader?, ContactsPeerItemSelection, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, PresentationPersonNameOrder, Bool, Bool, StoryData?) + case peer(Int, ContactListPeer, EnginePeer.Presence?, ListViewItemHeader?, ContactsPeerItemSelection, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, PresentationPersonNameOrder, Bool, Bool, StoryData?, Bool) var stableId: ContactListNodeEntryId { switch self { @@ -106,7 +108,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable { return .permission(action: true) case let .option(index, _, _, _, _): return .option(index: index) - case let .peer(_, peer, _, _, _, _, _, _, _, _, _, _, storyData): + case let .peer(_, peer, _, _, _, _, _, _, _, _, _, _, storyData, _): switch peer { case let .peer(peer, _, _): return .peerId(peerId: peer.id.toInt64(), section: storyData != nil ? .stories : .contacts) @@ -139,7 +141,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable { }) case let .option(_, option, header, _, _): return ContactListActionItem(presentationData: ItemListPresentationData(presentationData), title: option.title, icon: option.icon, clearHighlightAutomatically: option.clearHighlightAutomatically, header: header, action: option.action) - case let .peer(_, peer, presence, header, selection, _, strings, dateTimeFormat, nameSortOrder, nameDisplayOrder, displayCallIcons, enabled, storyData): + case let .peer(_, peer, presence, header, selection, _, strings, dateTimeFormat, nameSortOrder, nameDisplayOrder, displayCallIcons, enabled, storyData, requiresPremiumForMessaging): var status: ContactsPeerItemStatus let itemPeer: ContactsPeerItemPeer var isContextActionEnabled = false @@ -213,9 +215,13 @@ private enum ContactListNodeEntry: Comparable, Identifiable { status = .custom(string: text, multiline: false, isActive: false, icon: nil) } - return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: isSearch ? .generalSearch(isSavedMessages: false) : .peer, peer: itemPeer, status: status, enabled: enabled, selection: selection, selectionPosition: .left, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), additionalActions: additionalActions, index: nil, header: header, action: { _ in + return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: isSearch ? .generalSearch(isSavedMessages: false) : .peer, peer: itemPeer, status: status, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: selection, selectionPosition: .left, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), additionalActions: additionalActions, index: nil, header: header, action: { _ in interaction.openPeer(peer, .generic) - }, itemHighlighting: interaction.itemHighlighting, contextAction: itemContextAction, storyStats: storyStats, openStories: { peer, sourceNode in + }, disabledAction: { _ in + if case let .peer(peer, _, _) = peer { + interaction.openDisabledPeer(EnginePeer(peer), requiresPremiumForMessaging ? .premiumRequired : .generic) + } + }, itemHighlighting: interaction.itemHighlighting, contextAction: itemContextAction, storyStats: storyStats, openStories: { peer, sourceNode in if case let .peer(peerValue, _) = peer, let peerValue { interaction.openStories(peerValue, sourceNode) } @@ -255,9 +261,9 @@ private enum ContactListNodeEntry: Comparable, Identifiable { } else { return false } - case let .peer(lhsIndex, lhsPeer, lhsPresence, lhsHeader, lhsSelection, lhsTheme, lhsStrings, lhsTimeFormat, lhsSortOrder, lhsDisplayOrder, lhsDisplayCallIcons, lhsEnabled, lhsStoryData): + case let .peer(lhsIndex, lhsPeer, lhsPresence, lhsHeader, lhsSelection, lhsTheme, lhsStrings, lhsTimeFormat, lhsSortOrder, lhsDisplayOrder, lhsDisplayCallIcons, lhsEnabled, lhsStoryData, lhsRequiresPremiumForMessaging): switch rhs { - case let .peer(rhsIndex, rhsPeer, rhsPresence, rhsHeader, rhsSelection, rhsTheme, rhsStrings, rhsTimeFormat, rhsSortOrder, rhsDisplayOrder, rhsDisplayCallIcons, rhsEnabled, rhsStoryData): + case let .peer(rhsIndex, rhsPeer, rhsPresence, rhsHeader, rhsSelection, rhsTheme, rhsStrings, rhsTimeFormat, rhsSortOrder, rhsDisplayOrder, rhsDisplayCallIcons, rhsEnabled, rhsStoryData, rhsRequiresPremiumForMessaging): if lhsIndex != rhsIndex { return false } @@ -301,6 +307,9 @@ private enum ContactListNodeEntry: Comparable, Identifiable { if lhsStoryData != rhsStoryData { return false } + if lhsRequiresPremiumForMessaging != rhsRequiresPremiumForMessaging { + return false + } return true default: return false @@ -342,11 +351,11 @@ private enum ContactListNodeEntry: Comparable, Identifiable { case .peer: return true } - case let .peer(lhsIndex, _, _, _, _, _, _, _, _, _, _, _, lhsStoryData): + case let .peer(lhsIndex, _, _, _, _, _, _, _, _, _, _, _, lhsStoryData, _): switch rhs { case .search, .sort, .permissionInfo, .permissionEnable, .option: return false - case let .peer(rhsIndex, _, _, _, _, _, _, _, _, _, _, _, rhsStoryData): + case let .peer(rhsIndex, _, _, _, _, _, _, _, _, _, _, _, rhsStoryData, _): if (lhsStoryData == nil) != (rhsStoryData == nil) { if lhsStoryData != nil { return true @@ -360,7 +369,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable { } } -private func contactListNodeEntries(accountPeer: EnginePeer?, peers: [ContactListPeer], presences: [EnginePeer.Id: EnginePeer.Presence], presentation: ContactListPresentation, selectionState: ContactListNodeGroupSelectionState?, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, sortOrder: PresentationPersonNameOrder, displayOrder: PresentationPersonNameOrder, disabledPeerIds: Set, authorizationStatus: AccessType, warningSuppressed: (Bool, Bool), displaySortOptions: Bool, displayCallIcons: Bool, storySubscriptions: EngineStorySubscriptions?, topPeers: [EnginePeer], interaction: ContactListNodeInteraction) -> [ContactListNodeEntry] { +private func contactListNodeEntries(accountPeer: EnginePeer?, peers: [ContactListPeer], presences: [EnginePeer.Id: EnginePeer.Presence], presentation: ContactListPresentation, selectionState: ContactListNodeGroupSelectionState?, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, sortOrder: PresentationPersonNameOrder, displayOrder: PresentationPersonNameOrder, disabledPeerIds: Set, peerRequiresPremiumForMessaging: [EnginePeer.Id: Bool], authorizationStatus: AccessType, warningSuppressed: (Bool, Bool), displaySortOptions: Bool, displayCallIcons: Bool, storySubscriptions: EngineStorySubscriptions?, topPeers: [EnginePeer], interaction: ContactListNodeInteraction) -> [ContactListNodeEntry] { var entries: [ContactListNodeEntry] = [] var commonHeader: ListViewItemHeader? @@ -535,7 +544,7 @@ private func contactListNodeEntries(accountPeer: EnginePeer?, peers: [ContactLis } let presence = presences[peer.id] - entries.append(.peer(index, .peer(peer: peer._asPeer(), isGlobal: false, participantCount: nil), presence, header, selection, theme, strings, dateTimeFormat, sortOrder, displayOrder, false, true, nil)) + entries.append(.peer(index, .peer(peer: peer._asPeer(), isGlobal: false, participantCount: nil), presence, header, selection, theme, strings, dateTimeFormat, sortOrder, displayOrder, false, true, nil, false)) index += 1 } @@ -576,7 +585,7 @@ private func contactListNodeEntries(accountPeer: EnginePeer?, peers: [ContactLis enabled = true } - entries.append(.peer(index, peer, presence, nil, selection, theme, strings, dateTimeFormat, sortOrder, displayOrder, displayCallIcons, enabled, nil)) + entries.append(.peer(index, peer, presence, nil, selection, theme, strings, dateTimeFormat, sortOrder, displayOrder, displayCallIcons, enabled, nil, false)) index += 1 } } @@ -605,14 +614,25 @@ private func contactListNodeEntries(accountPeer: EnginePeer?, peers: [ContactLis if case let .peer(peer, _, _) = peer { presence = presences[peer.id] } - let enabled: Bool + var enabled: Bool + var requiresPremiumForMessaging = false switch peer { - case let .peer(peer, _, _): - enabled = !disabledPeerIds.contains(peer.id) - default: - enabled = true + case let .peer(peer, _, _): + enabled = !disabledPeerIds.contains(peer.id) + + if let value = peerRequiresPremiumForMessaging[peer.id], value { + requiresPremiumForMessaging = true + } + + if requiresPremiumForMessaging { + enabled = false + } + default: + enabled = true } - entries.append(.peer(index, peer, presence, header, selection, theme, strings, dateTimeFormat, sortOrder, displayOrder, displayCallIcons, enabled, nil)) + + + entries.append(.peer(index, peer, presence, header, selection, theme, strings, dateTimeFormat, sortOrder, displayOrder, displayCallIcons, enabled, nil, requiresPremiumForMessaging)) index += 1 } return entries @@ -636,7 +656,7 @@ private func preparedContactListNodeTransition(context: AccountContext, presenta case .search: //indexSections.apend(CollectionIndexNode.searchIndex) break - case let .peer(_, _, _, header, _, _, _, _, _, _, _, _, _): + case let .peer(_, _, _, header, _, _, _, _, _, _, _, _, _, _): if let header = header as? ContactListNameIndexHeader { if !existingSections.contains(header.letter) { existingSections.insert(header.letter) @@ -742,6 +762,7 @@ public final class ContactListNode: ASDisplayNode { private let context: AccountContext private var presentation: ContactListPresentation? private let filters: [ContactListFilter] + private let onlyWriteable: Bool public let listNode: ListView private var indexNode: CollectionIndexNode @@ -756,7 +777,7 @@ public final class ContactListNode: ASDisplayNode { } private var didSetReady = false - private let contactPeersViewPromise = Promise<(EngineContactList, EnginePeer?)>() + private let contactPeersViewPromise = Promise<(EngineContactList, EnginePeer?, [EnginePeer.Id: Bool])>() let storySubscriptions = Promise(nil) private let selectionStatePromise = Promise(nil) @@ -804,23 +825,58 @@ public final class ContactListNode: ASDisplayNode { } set(value) { if value != self.enableUpdatesValue { self.enableUpdatesValue = value - if value { - self.contactPeersViewPromise.set(self.context.engine.data.subscribe( - TelegramEngine.EngineData.Item.Contacts.List(includePresences: true), - TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.engine.account.peerId) + + let context = self.context + let contactsWithPremiumRequired: Signal<[EnginePeer.Id: Bool], NoError> + if self.onlyWriteable { + contactsWithPremiumRequired = self.context.engine.data.subscribe( + TelegramEngine.EngineData.Item.Contacts.List(includePresences: false) ) - |> mapToThrottled { next -> Signal<(EngineContactList, EnginePeer?), NoError> in - return .single(next) + |> map { contacts -> Set in + var result = Set() + for peer in contacts.peers { + if case let .user(user) = peer, user.flags.contains(.requirePremium) { + result.insert(peer.id) + } + } + return result + } + |> distinctUntilChanged + |> mapToSignal { peerIds -> Signal<[EnginePeer.Id: Bool], NoError> in + return context.engine.data.subscribe( + EngineDataMap( + peerIds.map(TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging.init(id:)) + ) + ) + } + } else { + contactsWithPremiumRequired = .single([:]) + } + + if value { + self.contactPeersViewPromise.set(combineLatest( + self.context.engine.data.subscribe( + TelegramEngine.EngineData.Item.Contacts.List(includePresences: true), + TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.engine.account.peerId) + ), + contactsWithPremiumRequired + ) + |> mapToThrottled { next, contactsWithPremiumRequired -> Signal<(EngineContactList, EnginePeer?, [EnginePeer.Id: Bool]), NoError> in + return .single((next.0, next.1, contactsWithPremiumRequired)) |> then( .complete() |> delay(5.0, queue: Queue.concurrentDefaultQueue()) ) }) } else { - self.contactPeersViewPromise.set(self.context.engine.data.subscribe( + self.contactPeersViewPromise.set(combineLatest(self.context.engine.data.subscribe( TelegramEngine.EngineData.Item.Contacts.List(includePresences: true), TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.engine.account.peerId) - ) + ), + contactsWithPremiumRequired) + |> map { next, contactsWithPremiumRequired -> (EngineContactList, EnginePeer?, [EnginePeer.Id: Bool]) in + return (next.0, next.1, contactsWithPremiumRequired) + } |> take(1)) } } @@ -832,6 +888,7 @@ public final class ContactListNode: ASDisplayNode { public var activateSearch: (() -> Void)? public var openPeer: ((ContactListPeer, ContactListAction) -> Void)? + public var openDisabledPeer: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? public var deselectedAll: (() -> Void)? public var openPrivacyPolicy: (() -> Void)? public var suppressPermissionWarning: (() -> Void)? @@ -852,13 +909,14 @@ public final class ContactListNode: ASDisplayNode { private let isPeerEnabled: ((EnginePeer) -> Bool)? - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, presentation: Signal, filters: [ContactListFilter] = [.excludeSelf], isPeerEnabled: ((EnginePeer) -> Bool)? = nil, selectionState: ContactListNodeGroupSelectionState? = nil, displayPermissionPlaceholder: Bool = true, displaySortOptions: Bool = false, displayCallIcons: Bool = false, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?, Bool) -> Void)? = nil, isSearch: Bool = false, multipleSelection: Bool = false) { + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, presentation: Signal, filters: [ContactListFilter] = [.excludeSelf], onlyWriteable: Bool, isPeerEnabled: ((EnginePeer) -> Bool)? = nil, selectionState: ContactListNodeGroupSelectionState? = nil, displayPermissionPlaceholder: Bool = true, displaySortOptions: Bool = false, displayCallIcons: Bool = false, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?, Bool) -> Void)? = nil, isSearch: Bool = false, multipleSelection: Bool = false) { self.context = context self.filters = filters self.displayPermissionPlaceholder = displayPermissionPlaceholder self.contextAction = contextAction self.multipleSelection = multipleSelection self.isPeerEnabled = isPeerEnabled + self.onlyWriteable = onlyWriteable let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 } self.presentationData = presentationData @@ -948,6 +1006,11 @@ public final class ContactListNode: ASDisplayNode { strongSelf.openPeer?(peer, action) } } + }, openDisabledPeer: { [weak self] peer, reason in + guard let self else { + return + } + self.openDisabledPeer?(peer, reason) }, contextAction: contextAction, openStories: { [weak self] peer, sourceNode in guard let self else { return @@ -988,7 +1051,7 @@ public final class ContactListNode: ASDisplayNode { strongSelf.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.PreferSynchronousDrawing, .PreferSynchronousResourceLoading], scrollToItem: ListViewScrollToItem(index: index, position: .top(-navigationBarSearchContentHeight), animated: false, curve: .Default(duration: nil), directionHint: .Down), additionalScrollDistance: 0.0, updateSizeAndInsets: updateSizeAndInsets, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) break loop } - case let .peer(_, _, _, header, _, _, _, _, _, _, _, _, _): + case let .peer(_, _, _, header, _, _, _, _, _, _, _, _, _, _): if let header = header as? ContactListNameIndexHeader { if let scalar = UnicodeScalar(header.letter) { let title = "\(Character(scalar))" @@ -1114,9 +1177,70 @@ public final class ContactListNode: ASDisplayNode { let accountPeer = context.account.postbox.loadedPeerWithId(context.account.peerId) |> take(1) - return combineLatest(accountPeer, foundLocalContacts, foundRemoteContacts, foundDeviceContacts, selectionStateSignal, presentationDataPromise.get()) - |> mapToQueue { accountPeer, localPeersAndStatuses, remotePeers, deviceContacts, selectionState, presentationData -> Signal in + struct FoundPeers { + var foundLocalContacts: ([FoundPeer], [EnginePeer.Id: EnginePeer.Presence]) + var foundRemoteContacts: ([FoundPeer], [FoundPeer]) + } + + let foundPeers = Promise() + foundPeers.set(combineLatest( + foundLocalContacts, + foundRemoteContacts + ) + |> map { foundLocalContacts, foundRemoteContacts -> FoundPeers in + return FoundPeers( + foundLocalContacts: foundLocalContacts, + foundRemoteContacts: foundRemoteContacts + ) + }) + + let peerRequiresPremiumForMessaging: Signal<[EnginePeer.Id: Bool], NoError> + if onlyWriteable { + peerRequiresPremiumForMessaging = foundPeers.get() + |> map { foundPeers -> Set in + var result = Set() + + for peer in foundPeers.foundLocalContacts.0 { + if let user = peer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + result.insert(user.id) + } + } + + for peer in foundPeers.foundRemoteContacts.0 { + if let user = peer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + result.insert(user.id) + } + } + for peer in foundPeers.foundRemoteContacts.1 { + if let user = peer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + result.insert(user.id) + } + } + + return result + } + |> distinctUntilChanged + |> mapToSignal { peerIds -> Signal<[EnginePeer.Id: Bool], NoError> in + return context.engine.data.subscribe( + EngineDataMap( + peerIds.map(TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging.init(id:)) + ) + ) + } + } else { + peerRequiresPremiumForMessaging = .single([:]) + } + + return combineLatest(accountPeer, foundPeers.get(), peerRequiresPremiumForMessaging, foundDeviceContacts, selectionStateSignal, presentationDataPromise.get()) + |> mapToQueue { accountPeer, foundPeers, peerRequiresPremiumForMessaging, deviceContacts, selectionState, presentationData -> Signal in + let localPeersAndStatuses = foundPeers.foundLocalContacts + let remotePeers = foundPeers.foundRemoteContacts + let signal = deferred { () -> Signal in + if !peerRequiresPremiumForMessaging.isEmpty { + context.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: Array(peerRequiresPremiumForMessaging.keys)) + } + var existingPeerIds = Set() var disabledPeerIds = Set() @@ -1251,7 +1375,7 @@ public final class ContactListNode: ASDisplayNode { peers.append(.deviceContact(stableId, contact.0)) } - let entries = contactListNodeEntries(accountPeer: nil, peers: peers, presences: localPeersAndStatuses.1, presentation: presentation, selectionState: selectionState, theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, disabledPeerIds: disabledPeerIds, authorizationStatus: .allowed, warningSuppressed: (true, true), displaySortOptions: false, displayCallIcons: displayCallIcons, storySubscriptions: nil, topPeers: [], interaction: interaction) + let entries = contactListNodeEntries(accountPeer: nil, peers: peers, presences: localPeersAndStatuses.1, presentation: presentation, selectionState: selectionState, theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, disabledPeerIds: disabledPeerIds, peerRequiresPremiumForMessaging: peerRequiresPremiumForMessaging, authorizationStatus: .allowed, warningSuppressed: (true, true), displaySortOptions: false, displayCallIcons: displayCallIcons, storySubscriptions: nil, topPeers: [], interaction: interaction) let previous = previousEntries.swap(entries) return .single(preparedContactListNodeTransition(context: context, presentationData: presentationData, from: previous ?? [], to: entries, interaction: interaction, firstTime: previous == nil, isEmpty: false, generateIndexSections: generateSections, animation: .none, isSearch: isSearch)) } @@ -1330,6 +1454,10 @@ public final class ContactListNode: ASDisplayNode { ) |> mapToQueue { view, chatListPeers, selectionState, presentationData, authorizationStatus, warningSuppressed, storySubscriptions, recentPeers -> Signal in let signal = deferred { () -> Signal in + if !view.2.isEmpty { + context.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: Array(view.2.keys)) + } + var peers = view.0.peers.map({ ContactListPeer.peer(peer: $0._asPeer(), isGlobal: false, participantCount: nil) }) for (peer, memberCount) in chatListPeers { peers.append(.peer(peer: peer._asPeer(), isGlobal: false, participantCount: memberCount)) @@ -1374,7 +1502,7 @@ public final class ContactListNode: ASDisplayNode { if (authorizationStatus == .notDetermined || authorizationStatus == .denied) && peers.isEmpty { isEmpty = true } - let entries = contactListNodeEntries(accountPeer: view.1, peers: peers, presences: view.0.presences, presentation: presentation, selectionState: selectionState, theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, disabledPeerIds: disabledPeerIds, authorizationStatus: authorizationStatus, warningSuppressed: warningSuppressed, displaySortOptions: displaySortOptions, displayCallIcons: displayCallIcons, storySubscriptions: storySubscriptions, topPeers: topPeers, interaction: interaction) + let entries = contactListNodeEntries(accountPeer: view.1, peers: peers, presences: view.0.presences, presentation: presentation, selectionState: selectionState, theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, disabledPeerIds: disabledPeerIds, peerRequiresPremiumForMessaging: view.2, authorizationStatus: authorizationStatus, warningSuppressed: warningSuppressed, displaySortOptions: displaySortOptions, displayCallIcons: displayCallIcons, storySubscriptions: storySubscriptions, topPeers: topPeers, interaction: interaction) let previous = previousEntries.swap(entries) let previousSelection = previousSelectionState.swap(selectionState) diff --git a/submodules/ContactListUI/Sources/ContactsControllerNode.swift b/submodules/ContactListUI/Sources/ContactsControllerNode.swift index 3a991bbbe0..02bc45b06e 100644 --- a/submodules/ContactListUI/Sources/ContactsControllerNode.swift +++ b/submodules/ContactListUI/Sources/ContactsControllerNode.swift @@ -59,6 +59,7 @@ final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate { var requestDeactivateSearch: (() -> Void)? var requestOpenPeerFromSearch: ((ContactListPeer) -> Void)? + var requestOpenDisabledPeerFromSearch: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? var requestAddContact: ((String) -> Void)? var openPeopleNearby: (() -> Void)? var openInvite: (() -> Void)? @@ -113,7 +114,7 @@ final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate { var contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?, Bool) -> Void)? - self.contactListNode = ContactListNode(context: context, presentation: presentation, displaySortOptions: true, contextAction: { peer, node, gesture, location, isStories in + self.contactListNode = ContactListNode(context: context, presentation: presentation, onlyWriteable: false, displaySortOptions: true, contextAction: { peer, node, gesture, location, isStories in contextAction?(peer, node, gesture, location, isStories) }) @@ -462,6 +463,10 @@ final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate { if let requestOpenPeerFromSearch = self?.requestOpenPeerFromSearch { requestOpenPeerFromSearch(peer) } + }, openDisabledPeer: { [weak self] peer, reason in + if let requestOpenDisabledPeerFromSearch = self?.requestOpenDisabledPeerFromSearch { + requestOpenDisabledPeerFromSearch(peer, reason) + } }, contextAction: { [weak self] peer, node, gesture, location in self?.contextAction(peer: peer, node: node, gesture: gesture, location: location, isStories: false) }), cancel: { [weak self] in diff --git a/submodules/ContactListUI/Sources/ContactsSearchContainerNode.swift b/submodules/ContactListUI/Sources/ContactsSearchContainerNode.swift index 90972a156b..acda9b4528 100644 --- a/submodules/ContactListUI/Sources/ContactsSearchContainerNode.swift +++ b/submodules/ContactListUI/Sources/ContactsSearchContainerNode.swift @@ -53,13 +53,13 @@ private enum ContactListSearchEntryId: Hashable { private enum ContactListSearchEntry: Comparable, Identifiable { case addContact(PresentationTheme, PresentationStrings, String) - case peer(Int, PresentationTheme, PresentationStrings, ContactListPeer, EnginePeer.Presence?, ContactListSearchGroup, Bool) + case peer(Int, PresentationTheme, PresentationStrings, ContactListPeer, EnginePeer.Presence?, ContactListSearchGroup, Bool, Bool) var stableId: ContactListSearchEntryId { switch self { case .addContact: return .addContact - case let .peer(_, _, _, peer, _, _, _): + case let .peer(_, _, _, peer, _, _, _, _): return .peerId(peer.id) } } @@ -72,9 +72,9 @@ private enum ContactListSearchEntry: Comparable, Identifiable { } else { return false } - case let .peer(lhsIndex, lhsTheme, lhsStrings, lhsPeer, lhsPresence, lhsGroup, lhsEnabled): + case let .peer(lhsIndex, lhsTheme, lhsStrings, lhsPeer, lhsPresence, lhsGroup, lhsEnabled, lhsRequiresPremiumForMessaging): switch rhs { - case let .peer(rhsIndex, rhsTheme, rhsStrings, rhsPeer, rhsPresence, rhsGroup, rhsEnabled): + case let .peer(rhsIndex, rhsTheme, rhsStrings, rhsPeer, rhsPresence, rhsGroup, rhsEnabled, rhsRequiresPremiumForMessaging): if lhsIndex != rhsIndex { return false } @@ -100,6 +100,9 @@ private enum ContactListSearchEntry: Comparable, Identifiable { if lhsEnabled != rhsEnabled { return false } + if lhsRequiresPremiumForMessaging != rhsRequiresPremiumForMessaging { + return false + } return true default: return false @@ -109,25 +112,25 @@ private enum ContactListSearchEntry: Comparable, Identifiable { static func <(lhs: ContactListSearchEntry, rhs: ContactListSearchEntry) -> Bool { switch lhs { + case .addContact: + return true + case let .peer(lhsIndex, _, _, _, _, _, _, _): + switch rhs { case .addContact: - return true - case let .peer(lhsIndex, _, _, _, _, _, _): - switch rhs { - case .addContact: - return false - case let .peer(rhsIndex, _, _, _, _, _, _): - return lhsIndex < rhsIndex - } + return false + case let .peer(rhsIndex, _, _, _, _, _, _, _): + return lhsIndex < rhsIndex + } } } - func item(context: AccountContext, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, timeFormat: PresentationDateTimeFormat, addContact: ((String) -> Void)?, openPeer: @escaping (ContactListPeer) -> Void, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?) -> ListViewItem { + func item(context: AccountContext, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, timeFormat: PresentationDateTimeFormat, addContact: ((String) -> Void)?, openPeer: @escaping (ContactListPeer) -> Void, openDisabledPeer: @escaping (EnginePeer, ChatListDisabledPeerReason) -> Void, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?) -> ListViewItem { switch self { case let .addContact(theme, strings, phoneNumber): return ContactsAddItem(context: context, theme: theme, strings: strings, phoneNumber: phoneNumber, header: ChatListSearchItemHeader(type: .phoneNumber, theme: theme, strings: strings, actionTitle: nil, action: nil), action: { addContact?(phoneNumber) }) - case let .peer(_, theme, strings, peer, presence, group, enabled): + case let .peer(_, theme, strings, peer, presence, group, enabled, requiresPremiumForMessaging): let header: ListViewItemHeader let status: ContactsPeerItemStatus switch group { @@ -158,8 +161,12 @@ private enum ContactListSearchEntry: Comparable, Identifiable { case let .deviceContact(stableId, contact): peerItem = .deviceContact(stableId: stableId, contact: contact) } - return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .peer, peer: peerItem, status: status, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in + return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .peer, peer: peerItem, status: status, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in openPeer(peer) + }, disabledAction: { _ in + if case let .peer(peer, _, _) = peer { + openDisabledPeer(EnginePeer(peer), requiresPremiumForMessaging ? .premiumRequired : .generic) + } }, contextAction: contextAction.flatMap { contextAction in return nativePeer.flatMap { nativePeer in return { node, gesture, location in @@ -180,12 +187,12 @@ struct ContactListSearchContainerTransition { let query: String } -private func contactListSearchContainerPreparedRecentTransition(from fromEntries: [ContactListSearchEntry], to toEntries: [ContactListSearchEntry], isSearching: Bool, emptyResults: Bool, query: String, context: AccountContext, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, timeFormat: PresentationDateTimeFormat, addContact: ((String) -> Void)?, openPeer: @escaping (ContactListPeer) -> Void, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?) -> ContactListSearchContainerTransition { +private func contactListSearchContainerPreparedRecentTransition(from fromEntries: [ContactListSearchEntry], to toEntries: [ContactListSearchEntry], isSearching: Bool, emptyResults: Bool, query: String, context: AccountContext, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, timeFormat: PresentationDateTimeFormat, addContact: ((String) -> Void)?, openPeer: @escaping (ContactListPeer) -> Void, openDisabledPeer: @escaping (EnginePeer, ChatListDisabledPeerReason) -> Void, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?) -> ContactListSearchContainerTransition { 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, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, timeFormat: timeFormat, addContact: addContact, openPeer: openPeer, contextAction: contextAction), directionHint: nil) } - let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, timeFormat: timeFormat, addContact: addContact, openPeer: openPeer, contextAction: contextAction), directionHint: nil) } + let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, timeFormat: timeFormat, addContact: addContact, openPeer: openPeer, openDisabledPeer: openDisabledPeer, contextAction: contextAction), directionHint: nil) } + let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, timeFormat: timeFormat, addContact: addContact, openPeer: openPeer, openDisabledPeer: openDisabledPeer, contextAction: contextAction), directionHint: nil) } return ContactListSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, isSearching: isSearching, emptyResults: emptyResults, query: query) } @@ -206,6 +213,7 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo private let context: AccountContext private let addContact: ((String) -> Void)? private let openPeer: (ContactListPeer) -> Void + private let openDisabledPeer: (EnginePeer, ChatListDisabledPeerReason) -> Void private let contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? private let dimNode: ASDisplayNode @@ -229,10 +237,11 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo return true } - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, onlyWriteable: Bool, categories: ContactsSearchCategories, filters: [ContactListFilter] = [.excludeSelf], addContact: ((String) -> Void)?, openPeer: @escaping (ContactListPeer) -> Void, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?) { + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, onlyWriteable: Bool, categories: ContactsSearchCategories, filters: [ContactListFilter] = [.excludeSelf], addContact: ((String) -> Void)?, openPeer: @escaping (ContactListPeer) -> Void, openDisabledPeer: @escaping (EnginePeer, ChatListDisabledPeerReason) -> Void, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?) { self.context = context self.addContact = addContact self.openPeer = openPeer + self.openDisabledPeer = openDisabledPeer self.contextAction = contextAction let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 } @@ -314,9 +323,71 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo foundDeviceContacts = .single([:]) } - return combineLatest(foundLocalContacts, foundRemoteContacts, foundDeviceContacts, themeAndStringsPromise.get()) + struct FoundPeers { + var foundLocalContacts: ([EnginePeer], [EnginePeer.Id: EnginePeer.Presence]) + var foundRemoteContacts: ([FoundPeer], [FoundPeer])? + } + let foundPeers = Promise() + foundPeers.set(combineLatest( + foundLocalContacts, + foundRemoteContacts + ) + |> map { foundLocalContacts, foundRemoteContacts -> FoundPeers in + return FoundPeers( + foundLocalContacts: foundLocalContacts, + foundRemoteContacts: foundRemoteContacts + ) + }) + + let peerRequiresPremiumForMessaging: Signal<[EnginePeer.Id: Bool], NoError> + if onlyWriteable { + peerRequiresPremiumForMessaging = foundPeers.get() + |> map { foundPeers -> Set in + var result = Set() + + for peer in foundPeers.foundLocalContacts.0 { + if case let .user(user) = peer, user.flags.contains(.requirePremium) { + result.insert(user.id) + } + } + + if let foundRemoteContacts = foundPeers.foundRemoteContacts { + for peer in foundRemoteContacts.0 { + if let user = peer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + result.insert(user.id) + } + } + for peer in foundRemoteContacts.1 { + if let user = peer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + result.insert(user.id) + } + } + } + + return result + } + |> distinctUntilChanged + |> mapToSignal { peerIds -> Signal<[EnginePeer.Id: Bool], NoError> in + return context.engine.data.subscribe( + EngineDataMap( + peerIds.map(TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging.init(id:)) + ) + ) + } + } else { + peerRequiresPremiumForMessaging = .single([:]) + } + + return combineLatest(foundPeers.get(), peerRequiresPremiumForMessaging, foundDeviceContacts, themeAndStringsPromise.get()) |> delay(0.1, queue: Queue.concurrentDefaultQueue()) - |> map { localPeersAndPresences, remotePeers, deviceContacts, themeAndStrings -> ([ContactListSearchEntry], String) in + |> map { foundPeers, peerRequiresPremiumForMessaging, deviceContacts, themeAndStrings -> ([ContactListSearchEntry], String) in + let localPeersAndPresences = foundPeers.foundLocalContacts + let remotePeers = foundPeers.foundRemoteContacts + + if !peerRequiresPremiumForMessaging.isEmpty { + context.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: Array(peerRequiresPremiumForMessaging.keys)) + } + let _ = previousFoundRemoteContacts.swap(remotePeers) var entries: [ContactListSearchEntry] = [] @@ -351,10 +422,15 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo existingPeerIds.insert(peer.id) var enabled = true + var requiresPremiumForMessaging = false if onlyWriteable { enabled = canSendMessagesToPeer(peer._asPeer()) + if let value = peerRequiresPremiumForMessaging[peer.id], value { + requiresPremiumForMessaging = true + enabled = false + } } - entries.append(.peer(index, themeAndStrings.0, themeAndStrings.1, .peer(peer: peer._asPeer(), isGlobal: false, participantCount: nil), localPeersAndPresences.1[peer.id], .contacts, enabled)) + entries.append(.peer(index, themeAndStrings.0, themeAndStrings.1, .peer(peer: peer._asPeer(), isGlobal: false, participantCount: nil), localPeersAndPresences.1[peer.id], .contacts, enabled, requiresPremiumForMessaging)) if searchDeviceContacts, case let .user(user) = peer, let phone = user.phone { existingNormalizedPhoneNumbers.insert(DeviceContactNormalizedPhoneNumber(rawValue: formatPhoneNumber(phone))) } @@ -377,11 +453,16 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo existingPeerIds.insert(peer.peer.id) var enabled = true + var requiresPremiumForMessaging = false if onlyWriteable { enabled = canSendMessagesToPeer(peer.peer) + if let value = peerRequiresPremiumForMessaging[peer.peer.id], value { + requiresPremiumForMessaging = true + enabled = false + } } - entries.append(.peer(index, themeAndStrings.0, themeAndStrings.1, .peer(peer: peer.peer, isGlobal: true, participantCount: peer.subscribers), nil, .global, enabled)) + entries.append(.peer(index, themeAndStrings.0, themeAndStrings.1, .peer(peer: peer.peer, isGlobal: true, participantCount: peer.subscribers), nil, .global, enabled, requiresPremiumForMessaging)) if searchDeviceContacts, let user = peer.peer as? TelegramUser, let phone = user.phone { existingNormalizedPhoneNumbers.insert(DeviceContactNormalizedPhoneNumber(rawValue: formatPhoneNumber(phone))) } @@ -404,11 +485,16 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo existingPeerIds.insert(peer.peer.id) var enabled = true + var requiresPremiumForMessaging = false if onlyWriteable { enabled = canSendMessagesToPeer(peer.peer) + if let value = peerRequiresPremiumForMessaging[peer.peer.id], value { + requiresPremiumForMessaging = true + enabled = false + } } - entries.append(.peer(index, themeAndStrings.0, themeAndStrings.1, .peer(peer: peer.peer, isGlobal: true, participantCount: peer.subscribers), nil, .global, enabled)) + entries.append(.peer(index, themeAndStrings.0, themeAndStrings.1, .peer(peer: peer.peer, isGlobal: true, participantCount: peer.subscribers), nil, .global, enabled, requiresPremiumForMessaging)) if searchDeviceContacts, let user = peer.peer as? TelegramUser, let phone = user.phone { existingNormalizedPhoneNumbers.insert(DeviceContactNormalizedPhoneNumber(rawValue: formatPhoneNumber(phone))) } @@ -429,7 +515,7 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo continue outer } } - entries.append(.peer(index, themeAndStrings.0, themeAndStrings.1, .deviceContact(stableId, contact.0), nil, .deviceContacts, true)) + entries.append(.peer(index, themeAndStrings.0, themeAndStrings.1, .deviceContact(stableId, contact.0), nil, .deviceContacts, true, false)) index += 1 } } @@ -464,6 +550,12 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo let transition = contactListSearchContainerPreparedRecentTransition(from: previousItems, to: items ?? [], isSearching: items != nil, emptyResults: items?.isEmpty ?? false, query: query, context: context, presentationData: strongSelf.presentationData, nameSortOrder: strongSelf.presentationData.nameSortOrder, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder, timeFormat: strongSelf.presentationData.dateTimeFormat, addContact: addContact, openPeer: { peer in self?.listNode.clearHighlightAnimated(true) self?.openPeer(peer) + }, openDisabledPeer: { peer, reason in + guard let self else { + return + } + self.listNode.clearHighlightAnimated(true) + self.openDisabledPeer(peer, reason) }, contextAction: strongSelf.contextAction) strongSelf.enqueueTransition(transition) diff --git a/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift b/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift index 3786a03d23..d3127070f0 100644 --- a/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift +++ b/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift @@ -513,6 +513,7 @@ final class InviteContactsControllerNode: ASDisplayNode { strongSelf.selectionState = strongSelf.selectionState.withSelectedContactId(id) strongSelf.requestDeactivateSearch?() } + }, openDisabledPeer: { _, _ in }, contextAction: nil), cancel: { [weak self] in if let requestDeactivateSearch = self?.requestDeactivateSearch { requestDeactivateSearch() diff --git a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift index 26b5e00c3d..8bbaba3820 100644 --- a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift +++ b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift @@ -163,6 +163,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader { public let peer: ContactsPeerItemPeer let status: ContactsPeerItemStatus let badge: ContactsPeerItemBadge? + let requiresPremiumForMessaging: Bool let enabled: Bool let selection: ContactsPeerItemSelection let selectionPosition: ContactsPeerItemSelectionPosition @@ -199,6 +200,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader { peer: ContactsPeerItemPeer, status: ContactsPeerItemStatus, badge: ContactsPeerItemBadge? = nil, + requiresPremiumForMessaging: Bool = false, enabled: Bool, selection: ContactsPeerItemSelection, selectionPosition: ContactsPeerItemSelectionPosition = .right, @@ -229,6 +231,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader { self.peer = peer self.status = status self.badge = badge + self.requiresPremiumForMessaging = requiresPremiumForMessaging self.enabled = enabled self.selection = selection self.selectionPosition = selectionPosition @@ -399,6 +402,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { private let offsetContainerNode: ASDisplayNode private let avatarNodeContainer: ASDisplayNode public let avatarNode: AvatarNode + private var avatarBadgeBackground: UIImageView? + private var avatarBadge: UIImageView? private var avatarIconView: ComponentHostView? private var avatarIconComponent: EmojiStatusComponent? private let titleNode: TextNode @@ -497,6 +502,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { self.separatorNode.isLayerBacked = true self.highlightedBackgroundNode = ASDisplayNode() + self.highlightedBackgroundNode.alpha = 0.0 self.highlightedBackgroundNode.isLayerBacked = true self.extractedBackgroundImageNode = ASImageNode() @@ -626,6 +632,10 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { } } + if let item = self.item, let avatarBadgeBackground = self.avatarBadgeBackground { + transition.updateTintColor(layer: avatarBadgeBackground.layer, color: item.presentationData.theme.list.itemHighlightedBackgroundColor.mixedWith(item.presentationData.theme.list.plainBackgroundColor, alpha: reallyHighlighted ? 0.0 : 1.0)) + } + if reallyHighlighted { if self.highlightedBackgroundNode.supernode == nil { self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: self.separatorNode) @@ -1144,6 +1154,44 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { strongSelf.avatarNode.frame = CGRect(origin: CGPoint(), size: avatarFrame.size) + if item.requiresPremiumForMessaging { + let avatarBadgeBackground: UIImageView + if let current = strongSelf.avatarBadgeBackground { + avatarBadgeBackground = current + } else { + avatarBadgeBackground = UIImageView() + avatarBadgeBackground.image = PresentationResourcesChatList.avatarPremiumLockBadgeBackground(item.presentationData.theme) + avatarBadgeBackground.tintColor = item.presentationData.theme.list.itemHighlightedBackgroundColor.mixedWith(item.presentationData.theme.list.plainBackgroundColor, alpha: 1.0 - strongSelf.highlightedBackgroundNode.alpha) + strongSelf.avatarBadgeBackground = avatarBadgeBackground + strongSelf.avatarNode.view.addSubview(avatarBadgeBackground) + } + + let avatarBadge: UIImageView + if let current = strongSelf.avatarBadge { + avatarBadge = current + } else { + avatarBadge = UIImageView() + avatarBadge.image = PresentationResourcesChatList.avatarPremiumLockBadge(item.presentationData.theme) + strongSelf.avatarBadge = avatarBadge + strongSelf.avatarNode.view.addSubview(avatarBadge) + } + + let badgeFrame = CGRect(origin: CGPoint(x: avatarFrame.width - 16.0, y: avatarFrame.height - 16.0), size: CGSize(width: 16.0, height: 16.0)) + let badgeBackgroundFrame = badgeFrame.insetBy(dx: -1.0 - UIScreenPixel, dy: -1.0 - UIScreenPixel) + + avatarBadgeBackground.frame = badgeBackgroundFrame + avatarBadge.frame = badgeFrame + } else { + if let avatarBadgeBackground = strongSelf.avatarBadgeBackground { + strongSelf.avatarBadgeBackground = nil + avatarBadgeBackground.removeFromSuperview() + } + if let avatarBadge = strongSelf.avatarBadge { + strongSelf.avatarBadge = nil + avatarBadge.removeFromSuperview() + } + } + transition.updatePosition(node: strongSelf.avatarNodeContainer, position: avatarFrame.center) transition.updateBounds(node: strongSelf.avatarNodeContainer, bounds: CGRect(origin: CGPoint(), size: avatarFrame.size)) diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift index 2ed45cdf2c..a9a40ac489 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift @@ -55,11 +55,11 @@ public final class HashtagSearchController: TelegramBaseController { |> map { result, presentationData in let result = result.0 let chatListPresentationData = ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true) - return result.messages.map({ .message(EngineMessage($0), EngineRenderedPeer(message: EngineMessage($0)), result.readStates[$0.id.peerId].flatMap { EnginePeerReadCounters(state: $0, isMuted: false) }, nil, chatListPresentationData, result.totalCount, nil, false, .index($0.index), nil, .generic, false, nil) }) + return result.messages.map({ .message(EngineMessage($0), EngineRenderedPeer(message: EngineMessage($0)), result.readStates[$0.id.peerId].flatMap { EnginePeerReadCounters(state: $0, isMuted: false) }, nil, chatListPresentationData, result.totalCount, nil, false, .index($0.index), nil, .generic, false, nil, false) }) } let interaction = ChatListNodeInteraction(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: { }, peerSelected: { _, _, _, _ in - }, disabledPeerSelected: { _, _ in + }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in diff --git a/submodules/HorizontalPeerItem/Sources/HorizontalPeerItem.swift b/submodules/HorizontalPeerItem/Sources/HorizontalPeerItem.swift index fdd6ded187..cd58a63fe8 100644 --- a/submodules/HorizontalPeerItem/Sources/HorizontalPeerItem.swift +++ b/submodules/HorizontalPeerItem/Sources/HorizontalPeerItem.swift @@ -144,7 +144,7 @@ public final class HorizontalPeerItemNode: ListViewItemNode { self.addSubnode(self.badgeBackgroundNode) self.addSubnode(self.badgeTextNode) self.addSubnode(self.onlineNode) - self.peerNode.toggleSelection = { [weak self] in + self.peerNode.toggleSelection = { [weak self] _ in if let item = self?.item { item.action(item.peer) } @@ -228,7 +228,7 @@ public final class HorizontalPeerItemNode: ListViewItemNode { } else { strongSelf.peerNode.compact = false } - strongSelf.peerNode.setup(accountPeerId: item.accountPeerId, postbox: item.postbox, network: item.network, energyUsageSettings: item.energyUsageSettings, contentSettings: item.contentSettings, animationCache: item.animationCache, animationRenderer: item.animationRenderer, resolveInlineStickers: item.resolveInlineStickers, theme: item.theme, strings: item.strings, peer: EngineRenderedPeer(peer: item.peer), numberOfLines: 1, synchronousLoad: synchronousLoads) + strongSelf.peerNode.setup(accountPeerId: item.accountPeerId, postbox: item.postbox, network: item.network, energyUsageSettings: item.energyUsageSettings, contentSettings: item.contentSettings, animationCache: item.animationCache, animationRenderer: item.animationRenderer, resolveInlineStickers: item.resolveInlineStickers, theme: item.theme, strings: item.strings, peer: EngineRenderedPeer(peer: item.peer), requiresPremiumForMessaging: false, numberOfLines: 1, synchronousLoad: synchronousLoads) strongSelf.peerNode.frame = CGRect(origin: CGPoint(), size: itemLayout.size) strongSelf.peerNode.updateSelection(selected: item.isPeerSelected(item.peer.id), animated: false) diff --git a/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewPeerContentNode.swift b/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewPeerContentNode.swift index 8e8ede5680..f6412b6200 100644 --- a/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewPeerContentNode.swift +++ b/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewPeerContentNode.swift @@ -143,7 +143,7 @@ final class JoinLinkPreviewPeerContentNode: ASDisplayNode, ShareContentContainer return nil } let node = SelectablePeerNode() - node.setup(context: context, theme: theme, strings: strings, peer: EngineRenderedPeer(peer: peer), synchronousLoad: false) + node.setup(context: context, theme: theme, strings: strings, peer: EngineRenderedPeer(peer: peer), requiresPremiumForMessaging: false, synchronousLoad: false) node.theme = itemTheme return node } diff --git a/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift b/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift index 2c277559c4..b054f966e8 100644 --- a/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift +++ b/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift @@ -75,13 +75,15 @@ public final class SelectablePeerNode: ASDisplayNode { private let avatarSelectionNode: ASImageNode private let avatarNodeContainer: ASDisplayNode private let avatarNode: AvatarNode + private var avatarBadgeBackground: UIImageView? + private var avatarBadge: UIImageView? private let onlineNode: PeerOnlineMarkerNode private var checkNode: CheckNode? private let textNode: ImmediateTextNode private let iconView: ComponentView - public var toggleSelection: (() -> Void)? + public var toggleSelection: ((Bool) -> Void)? public var contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? { didSet { self.contextContainer.isGestureEnabled = self.contextAction != nil @@ -91,6 +93,7 @@ public final class SelectablePeerNode: ASDisplayNode { private var currentSelected = false private var peer: EngineRenderedPeer? + private var requiresPremiumForMessaging: Bool = false public var compact = false @@ -146,7 +149,7 @@ public final class SelectablePeerNode: ASDisplayNode { } } - public func setup(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer, customTitle: String? = nil, iconId: Int64? = nil, iconColor: Int32? = nil, online: Bool = false, numberOfLines: Int = 2, synchronousLoad: Bool) { + public func setup(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer, requiresPremiumForMessaging: Bool, customTitle: String? = nil, iconId: Int64? = nil, iconColor: Int32? = nil, online: Bool = false, numberOfLines: Int = 2, synchronousLoad: Bool) { self.setup( accountPeerId: context.account.peerId, postbox: context.account.postbox, @@ -161,6 +164,7 @@ public final class SelectablePeerNode: ASDisplayNode { theme: theme, strings: strings, peer: peer, + requiresPremiumForMessaging: requiresPremiumForMessaging, customTitle: customTitle, iconId: iconId, iconColor: iconColor, @@ -180,14 +184,21 @@ public final class SelectablePeerNode: ASDisplayNode { self.avatarNode.playRepostAnimation() } - public func setup(accountPeerId: EnginePeer.Id, postbox: Postbox, network: Network, energyUsageSettings: EnergyUsageSettings, contentSettings: ContentSettings, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, resolveInlineStickers: @escaping ([Int64]) -> Signal<[Int64: TelegramMediaFile], NoError>, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer, customTitle: String? = nil, iconId: Int64? = nil, iconColor: Int32? = nil, online: Bool = false, numberOfLines: Int = 2, synchronousLoad: Bool) { + public func setup(accountPeerId: EnginePeer.Id, postbox: Postbox, network: Network, energyUsageSettings: EnergyUsageSettings, contentSettings: ContentSettings, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, resolveInlineStickers: @escaping ([Int64]) -> Signal<[Int64: TelegramMediaFile], NoError>, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer, requiresPremiumForMessaging: Bool, customTitle: String? = nil, iconId: Int64? = nil, iconColor: Int32? = nil, online: Bool = false, numberOfLines: Int = 2, synchronousLoad: Bool) { let isFirstTime = self.peer == nil self.peer = peer guard let mainPeer = peer.chatMainPeer else { return } - let defaultColor: UIColor = peer.peerId.namespace == Namespaces.Peer.SecretChat ? self.theme.secretTextColor : self.theme.textColor + self.requiresPremiumForMessaging = requiresPremiumForMessaging + + let defaultColor: UIColor + if requiresPremiumForMessaging { + defaultColor = self.theme.textColor.withMultipliedAlpha(0.4) + } else { + defaultColor = peer.peerId.namespace == Namespaces.Peer.SecretChat ? self.theme.secretTextColor : self.theme.textColor + } var isForum = false if let peer = peer.chatMainPeer, case let .channel(channel) = peer, channel.flags.contains(.isForum) { @@ -212,6 +223,45 @@ public final class SelectablePeerNode: ASDisplayNode { self.textNode.attributedText = NSAttributedString(string: customTitle ?? text, font: textFont, textColor: self.currentSelected ? self.theme.selectedTextColor : defaultColor, paragraphAlignment: .center) self.avatarNode.setPeer(accountPeerId: accountPeerId, postbox: postbox, network: network, contentSettings: contentSettings, theme: theme, peer: mainPeer, overrideImage: overrideImage, emptyColor: self.theme.avatarPlaceholderColor, clipStyle: isForum ? .roundedRect : .round, synchronousLoad: synchronousLoad) + if requiresPremiumForMessaging { + let avatarBadgeBackground: UIImageView + if let current = self.avatarBadgeBackground { + avatarBadgeBackground = current + } else { + avatarBadgeBackground = UIImageView() + avatarBadgeBackground.image = PresentationResourcesChatList.shareAvatarPremiumLockBadgeBackground(theme) + avatarBadgeBackground.tintColor = theme.chatList.itemBackgroundColor + self.avatarBadgeBackground = avatarBadgeBackground + self.avatarNode.view.addSubview(avatarBadgeBackground) + } + + let avatarBadge: UIImageView + if let current = self.avatarBadge { + avatarBadge = current + } else { + avatarBadge = UIImageView() + avatarBadge.image = PresentationResourcesChatList.shareAvatarPremiumLockBadge(theme) + self.avatarBadge = avatarBadge + self.avatarNode.view.addSubview(avatarBadge) + } + + let avatarFrame = self.avatarNode.frame + let badgeFrame = CGRect(origin: CGPoint(x: avatarFrame.width - 20.0, y: avatarFrame.height - 20.0), size: CGSize(width: 20.0, height: 20.0)) + let badgeBackgroundFrame = badgeFrame.insetBy(dx: -2.0 + UIScreenPixel, dy: -2.0 + UIScreenPixel) + + avatarBadgeBackground.frame = badgeBackgroundFrame + avatarBadge.frame = badgeFrame + } else { + if let avatarBadgeBackground = self.avatarBadgeBackground { + self.avatarBadgeBackground = nil + avatarBadgeBackground.removeFromSuperview() + } + if let avatarBadge = self.avatarBadge { + self.avatarBadge = nil + avatarBadge.removeFromSuperview() + } + } + let onlineLayout = self.onlineNode.asyncLayout() let (onlineSize, onlineApply) = onlineLayout(online, false) let _ = onlineApply(!isFirstTime) @@ -335,7 +385,7 @@ public final class SelectablePeerNode: ASDisplayNode { @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { if case .ended = recognizer.state { - self.toggleSelection?() + self.toggleSelection?(self.requiresPremiumForMessaging) } } diff --git a/submodules/SettingsUI/Sources/Privacy and Security/GlobalAutoremoveScreen.swift b/submodules/SettingsUI/Sources/Privacy and Security/GlobalAutoremoveScreen.swift index 93b2ac63e2..ca723fc519 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/GlobalAutoremoveScreen.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/GlobalAutoremoveScreen.swift @@ -335,7 +335,7 @@ public func globalAutoremoveScreen(context: AccountContext, initialValue: Int32, } return canManage }, - attemptDisabledItemSelection: { peer in + attemptDisabledItemSelection: { peer, _ in let presentationData = context.sharedContext.currentPresentationData.with { $0 } let text: String diff --git a/submodules/SettingsUI/Sources/Privacy and Security/IncomingMessagePrivacyScreen.swift b/submodules/SettingsUI/Sources/Privacy and Security/IncomingMessagePrivacyScreen.swift new file mode 100644 index 0000000000..7e0757fcbc --- /dev/null +++ b/submodules/SettingsUI/Sources/Privacy and Security/IncomingMessagePrivacyScreen.swift @@ -0,0 +1,231 @@ +import Foundation +import UIKit +import Display +import SwiftSignalKit +import TelegramCore +import TelegramPresentationData +import TelegramUIPreferences +import ItemListUI +import PresentationDataUtils +import AccountContext +import UndoUI +import PremiumUI + +private final class IncomingMessagePrivacyScreenArguments { + let context: AccountContext + let updateValue: (Bool) -> Void + let disabledValuePressed: () -> Void + let infoLinkAction: () -> Void + + init( + context: AccountContext, + updateValue: @escaping (Bool) -> Void, + disabledValuePressed: @escaping () -> Void, + infoLinkAction: @escaping () -> Void + ) { + self.context = context + self.updateValue = updateValue + self.disabledValuePressed = disabledValuePressed + self.infoLinkAction = infoLinkAction + } +} + +private enum IncomingMessagePrivacySection: Int32 { + case header + case info +} + +private enum GlobalAutoremoveEntry: ItemListNodeEntry { + case header + case optionEverybody(value: Bool) + case optionPremium(value: Bool, isEnabled: Bool) + case footer + case info + + var section: ItemListSectionId { + switch self { + case .header, .optionEverybody, .optionPremium, .footer: + return IncomingMessagePrivacySection.header.rawValue + case .info: + return IncomingMessagePrivacySection.info.rawValue + } + } + + var stableId: Int { + return self.sortIndex + } + + var sortIndex: Int { + switch self { + case .header: + return 0 + case .optionEverybody: + return 1 + case .optionPremium: + return 2 + case .footer: + return 3 + case .info: + return 4 + } + } + + static func <(lhs: GlobalAutoremoveEntry, rhs: GlobalAutoremoveEntry) -> Bool { + return lhs.sortIndex < rhs.sortIndex + } + + func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { + let arguments = arguments as! IncomingMessagePrivacyScreenArguments + switch self { + case .header: + //TODO:localize + return ItemListSectionHeaderItem(presentationData: presentationData, text: "WHO CAN SEND ME MESSAGES?", sectionId: self.section) + case let .optionEverybody(value): + return ItemListCheckboxItem(presentationData: presentationData, title: "Everybody", style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: { + arguments.updateValue(false) + }) + case let .optionPremium(value, isEnabled): + return ItemListCheckboxItem(presentationData: presentationData, icon: isEnabled ? nil : generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: presentationData.theme.list.itemSecondaryTextColor), iconPlacement: .check, title: "My Contacts and Premium Users", style: .left, checked: isEnabled && value, zeroSeparatorInsets: false, sectionId: self.section, action: { + if isEnabled { + arguments.updateValue(true) + } else { + arguments.disabledValuePressed() + } + }) + case .footer: + //TODO:localize + return ItemListTextItem(presentationData: presentationData, text: .plain("You can restrict incoming messages to only contacts and Premium users."), sectionId: self.section) + case .info: + //TODO:localize + return ItemListTextItem(presentationData: presentationData, text: .markdown("[What is Telegram Premium?]()"), sectionId: self.section, linkAction: { _ in + arguments.infoLinkAction() + }) + } + } +} + +private struct IncomingMessagePrivacyScreenState: Equatable { + var updatedValue: Bool +} + +private func incomingMessagePrivacyScreenEntries(presentationData: PresentationData, state: IncomingMessagePrivacyScreenState, isPremium: Bool) -> [GlobalAutoremoveEntry] { + var entries: [GlobalAutoremoveEntry] = [] + + entries.append(.header) + entries.append(.optionEverybody(value: !state.updatedValue)) + entries.append(.optionPremium(value: state.updatedValue, isEnabled: isPremium)) + entries.append(.footer) + entries.append(.info) + + return entries +} + +public func incomingMessagePrivacyScreen(context: AccountContext, value: Bool, update: @escaping (Bool) -> Void) -> ViewController { + let initialState = IncomingMessagePrivacyScreenState( + updatedValue: value + ) + let statePromise = ValuePromise(initialState, ignoreRepeated: true) + let stateValue = Atomic(value: initialState) + let updateState: ((IncomingMessagePrivacyScreenState) -> IncomingMessagePrivacyScreenState) -> Void = { f in + statePromise.set(stateValue.modify { f($0) }) + } + + var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)? + var presentInCurrentControllerImpl: ((ViewController) -> Void)? + var pushControllerImpl: ((ViewController) -> Void)? + var dismissImpl: (() -> Void)? + + let _ = dismissImpl + let _ = pushControllerImpl + let _ = presentControllerImpl + + let actionsDisposable = DisposableSet() + + let updateTimeoutDisposable = MetaDisposable() + actionsDisposable.add(updateTimeoutDisposable) + + let arguments = IncomingMessagePrivacyScreenArguments( + context: context, + updateValue: { value in + updateState { state in + var state = state + state.updatedValue = value + return state + } + }, + disabledValuePressed: { + let presentationData = context.sharedContext.currentPresentationData.with({ $0 }) + presentInCurrentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: "Premium Required", text: "Subscribe to **Telegram Premium** to select this option", customUndoText: "Add", timeout: nil, linkAction: { _ in + }), elevatedLayout: false, action: { action in + if case .undo = action { + let controller = PremiumIntroScreen(context: context, source: .settings) + pushControllerImpl?(controller) + } + return false + })) + }, + infoLinkAction: { + let controller = PremiumIntroScreen(context: context, source: .settings) + pushControllerImpl?(controller) + } + ) + + let signal = combineLatest(queue: .mainQueue(), + context.sharedContext.presentationData, + context.engine.data.subscribe( + TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId) + ), + statePromise.get() + ) + |> map { presentationData, accountPeer, state -> (ItemListControllerState, (ItemListNodeState, Any)) in + let rightNavigationButton: ItemListNavigationButton? = nil + + //TODO:localize + let title: ItemListControllerTitle = .text("Messages") + + let entries: [GlobalAutoremoveEntry] = incomingMessagePrivacyScreenEntries(presentationData: presentationData, state: state, isPremium: accountPeer?.isPremium ?? false) + + let animateChanges = false + + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: title, leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: entries, style: .blocks, emptyStateItem: nil, crossfadeState: false, animateChanges: animateChanges, scrollEnabled: true) + + return (controllerState, (listState, arguments)) + } + |> afterDisposed { + actionsDisposable.dispose() + } + + let controller = ItemListController(context: context, state: signal) + presentControllerImpl = { [weak controller] c, p in + guard let controller else { + return + } + controller.present(c, in: .window(.root), with: p) + } + presentInCurrentControllerImpl = { [weak controller] c in + guard let controller else { + return + } + + controller.forEachController { c in + if let c = c as? UndoOverlayController { + c.dismiss() + } + return true + } + controller.present(c, in: .current, with: nil) + } + pushControllerImpl = { [weak controller] c in + controller?.push(c) + } + controller.attemptNavigation = { _ in + update(stateValue.with({ $0 }).updatedValue) + return true + } + dismissImpl = { [weak controller] in + controller?.dismiss() + } + + return controller +} diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index 47b3630090..981aaddb20 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -35,13 +35,13 @@ private final class PrivacyAndSecurityControllerArguments { let openTwoStepVerification: (TwoStepVerificationAccessConfiguration?) -> Void let openActiveSessions: () -> Void let toggleArchiveAndMuteNonContacts: (Bool) -> Void - let toggleOnlyAllowPremiumNonContacts: (Bool) -> Void let setupAccountAutoremove: () -> Void let setupMessageAutoremove: () -> Void let openDataSettings: () -> Void let openEmailSettings: (String?) -> Void + let openMessagePrivacy: () -> Void - init(account: Account, openBlockedUsers: @escaping () -> Void, openLastSeenPrivacy: @escaping () -> Void, openGroupsPrivacy: @escaping () -> Void, openVoiceCallPrivacy: @escaping () -> Void, openProfilePhotoPrivacy: @escaping () -> Void, openForwardPrivacy: @escaping () -> Void, openPhoneNumberPrivacy: @escaping () -> Void, openVoiceMessagePrivacy: @escaping () -> Void, openBioPrivacy: @escaping () -> Void, openPasscode: @escaping () -> Void, openTwoStepVerification: @escaping (TwoStepVerificationAccessConfiguration?) -> Void, openActiveSessions: @escaping () -> Void, toggleArchiveAndMuteNonContacts: @escaping (Bool) -> Void, toggleOnlyAllowPremiumNonContacts: @escaping (Bool) -> Void, setupAccountAutoremove: @escaping () -> Void, setupMessageAutoremove: @escaping () -> Void, openDataSettings: @escaping () -> Void, openEmailSettings: @escaping (String?) -> Void) { + init(account: Account, openBlockedUsers: @escaping () -> Void, openLastSeenPrivacy: @escaping () -> Void, openGroupsPrivacy: @escaping () -> Void, openVoiceCallPrivacy: @escaping () -> Void, openProfilePhotoPrivacy: @escaping () -> Void, openForwardPrivacy: @escaping () -> Void, openPhoneNumberPrivacy: @escaping () -> Void, openVoiceMessagePrivacy: @escaping () -> Void, openBioPrivacy: @escaping () -> Void, openPasscode: @escaping () -> Void, openTwoStepVerification: @escaping (TwoStepVerificationAccessConfiguration?) -> Void, openActiveSessions: @escaping () -> Void, toggleArchiveAndMuteNonContacts: @escaping (Bool) -> Void, setupAccountAutoremove: @escaping () -> Void, setupMessageAutoremove: @escaping () -> Void, openDataSettings: @escaping () -> Void, openEmailSettings: @escaping (String?) -> Void, openMessagePrivacy: @escaping () -> Void) { self.account = account self.openBlockedUsers = openBlockedUsers self.openLastSeenPrivacy = openLastSeenPrivacy @@ -56,11 +56,11 @@ private final class PrivacyAndSecurityControllerArguments { self.openTwoStepVerification = openTwoStepVerification self.openActiveSessions = openActiveSessions self.toggleArchiveAndMuteNonContacts = toggleArchiveAndMuteNonContacts - self.toggleOnlyAllowPremiumNonContacts = toggleOnlyAllowPremiumNonContacts self.setupAccountAutoremove = setupAccountAutoremove self.setupMessageAutoremove = setupMessageAutoremove self.openDataSettings = openDataSettings self.openEmailSettings = openEmailSettings + self.openMessagePrivacy = openMessagePrivacy } } @@ -68,7 +68,6 @@ private enum PrivacyAndSecuritySection: Int32 { case general case privacy case autoArchive - case onlyAllowPremiumNonContacts case account case messageAutoremove case dataSettings @@ -98,6 +97,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { case forwardPrivacy(PresentationTheme, String, String) case groupPrivacy(PresentationTheme, String, String) case voiceMessagePrivacy(PresentationTheme, String, String, Bool) + case messagePrivacy(Bool) case bioPrivacy(PresentationTheme, String, String) case selectivePrivacyInfo(PresentationTheme, String) case passcode(PresentationTheme, String, Bool, String) @@ -108,8 +108,6 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { case autoArchiveHeader(String) case autoArchive(String, Bool) case autoArchiveInfo(String) - case onlyAllowPremiumNonContacts(String, Bool) - case onlyAllowPremiumNonContactsInfo(String) case accountHeader(PresentationTheme, String) case accountTimeout(PresentationTheme, String, String) case accountInfo(PresentationTheme, String) @@ -122,12 +120,10 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { switch self { case .blockedPeers, .activeSessions, .passcode, .twoStepVerification, .loginEmail, .loginEmailInfo, .messageAutoremoveTimeout, .messageAutoremoveInfo: return PrivacyAndSecuritySection.general.rawValue - case .privacyHeader, .phoneNumberPrivacy, .lastSeenPrivacy, .profilePhotoPrivacy, .forwardPrivacy, .groupPrivacy, .voiceCallPrivacy, .voiceMessagePrivacy, .bioPrivacy, .selectivePrivacyInfo: + case .privacyHeader, .phoneNumberPrivacy, .lastSeenPrivacy, .profilePhotoPrivacy, .forwardPrivacy, .groupPrivacy, .voiceCallPrivacy, .voiceMessagePrivacy, .messagePrivacy, .bioPrivacy, .selectivePrivacyInfo: return PrivacyAndSecuritySection.privacy.rawValue case .autoArchiveHeader, .autoArchive, .autoArchiveInfo: return PrivacyAndSecuritySection.autoArchive.rawValue - case .onlyAllowPremiumNonContacts, .onlyAllowPremiumNonContactsInfo: - return PrivacyAndSecuritySection.onlyAllowPremiumNonContacts.rawValue case .accountHeader, .accountTimeout, .accountInfo: return PrivacyAndSecuritySection.account.rawValue case .dataSettings, .dataSettingsInfo: @@ -171,28 +167,26 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { return 16 case .voiceMessagePrivacy: return 17 - case .selectivePrivacyInfo: + case .messagePrivacy: return 18 - case .autoArchiveHeader: + case .selectivePrivacyInfo: return 19 - case .autoArchive: + case .autoArchiveHeader: return 20 - case .autoArchiveInfo: + case .autoArchive: return 21 - case .onlyAllowPremiumNonContacts: + case .autoArchiveInfo: return 22 - case .onlyAllowPremiumNonContactsInfo: - return 23 case .accountHeader: - return 24 - case .accountTimeout: return 25 - case .accountInfo: + case .accountTimeout: return 26 - case .dataSettings: + case .accountInfo: return 27 - case .dataSettingsInfo: + case .dataSettings: return 28 + case .dataSettingsInfo: + return 29 } } @@ -252,6 +246,12 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { } else { return false } + case let .messagePrivacy(value): + if case .messagePrivacy(value) = rhs { + return true + } else { + return false + } case let .bioPrivacy(lhsTheme, lhsText, lhsValue): if case let .bioPrivacy(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { return true @@ -312,18 +312,6 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { } else { return false } - case let .onlyAllowPremiumNonContacts(text, value): - if case .onlyAllowPremiumNonContacts(text, value) = rhs { - return true - } else { - return false - } - case let .onlyAllowPremiumNonContactsInfo(text): - if case .onlyAllowPremiumNonContactsInfo(text) = rhs { - return true - } else { - return false - } case let .accountHeader(lhsTheme, lhsText): if case let .accountHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { return true @@ -406,6 +394,11 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, labelStyle: locked ? .textWithIcon(UIImage(bundleImageName: "Chat/Input/Accessory Panels/TextLockIcon")!.precomposed()) : .text, sectionId: self.section, style: .blocks, action: { arguments.openVoiceMessagePrivacy() }) + case let .messagePrivacy(value): + //TODO:localize + return ItemListDisclosureItem(presentationData: presentationData, title: "Messages", label: !value ? "Everybody" : "Contacts and Premium", sectionId: self.section, style: .blocks, action: { + arguments.openMessagePrivacy() + }) case let .bioPrivacy(_, text, value): return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: { arguments.openBioPrivacy() @@ -448,12 +441,6 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { }, tag: PrivacyAndSecurityEntryTag.autoArchive) case let .autoArchiveInfo(text): return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) - case let .onlyAllowPremiumNonContacts(text, value): - return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in - arguments.toggleOnlyAllowPremiumNonContacts(value) - }, tag: PrivacyAndSecurityEntryTag.autoArchive) - case let .onlyAllowPremiumNonContactsInfo(text): - return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) case let .accountHeader(_, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) case let .accountTimeout(_, text, value): @@ -606,6 +593,7 @@ private func privacyAndSecurityControllerEntries( entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.groupInvitations))) if !isPremiumDisabled { entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceMessages), !isPremium)) + entries.append(.messagePrivacy(privacySettings.globalSettings.nonContactChatsRequirePremium)) } //entries.append(.selectivePrivacyInfo(presentationData.theme, presentationData.strings.PrivacyLastSeenSettings_GroupsAndChannelsHelp)) @@ -641,15 +629,6 @@ private func privacyAndSecurityControllerEntries( entries.append(.autoArchiveInfo(presentationData.strings.PrivacySettings_AutoArchiveInfo)) } - //TODO:localize - let onlyAllowPremiumNonContactsValue = state.updatingOnlyAllowPremiumNonContacts ?? privacySettings?.globalSettings.nonContactChatsRequirePremium ?? false - entries.append(.onlyAllowPremiumNonContacts("Only Allow Premium Chats", onlyAllowPremiumNonContactsValue)) - if !onlyAllowPremiumNonContactsValue { - entries.append(.onlyAllowPremiumNonContactsInfo("Non-premium users are allowed to send you a message.")) - } else { - entries.append(.onlyAllowPremiumNonContactsInfo("Non-premium users are not allowed to send you a message.")) - } - entries.append(.accountHeader(presentationData.theme, presentationData.strings.PrivacySettings_DeleteAccountTitle.uppercased())) if let privacySettings = privacySettings { let value: Int32 @@ -1100,36 +1079,6 @@ public func privacyAndSecurityController( return state } })) - }, toggleOnlyAllowPremiumNonContacts: { settingValue in - updateState { state in - var state = state - state.updatingOnlyAllowPremiumNonContacts = settingValue - return state - } - let applyTimeout: Signal = privacySettingsPromise.get() - |> filter { $0 != nil } - |> take(1) - |> deliverOnMainQueue - |> mapToSignal { value -> Signal in - if let value = value { - var globalSettings = value.globalSettings - globalSettings.nonContactChatsRequirePremium = settingValue - - privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, bio: value.bio, globalSettings: globalSettings, accountRemovalTimeout: value.accountRemovalTimeout, messageAutoremoveTimeout: value.messageAutoremoveTimeout))) - } - return .complete() - } - - updateAutoArchiveDisposable.set((context.engine.privacy.updateNonContactChatsRequirePremium(value: settingValue) - |> mapToSignal { _ -> Signal in } - |> then(applyTimeout) - |> deliverOnMainQueue).start(completed: { - updateState { state in - var state = state - state.updatingOnlyAllowPremiumNonContacts = nil - return state - } - })) }, setupAccountAutoremove: { let signal = privacySettingsPromise.get() |> take(1) @@ -1242,6 +1191,46 @@ public func privacyAndSecurityController( } else { setupEmailImpl?(nil) } + }, openMessagePrivacy: { + let _ = (privacySettingsPromise.get() + |> filter { $0 != nil } + |> take(1) + |> deliverOnMainQueue).start(next: { privacySettings in + guard let privacySettings else { + return + } + pushControllerImpl?(incomingMessagePrivacyScreen(context: context, value: privacySettings.globalSettings.nonContactChatsRequirePremium, update: { settingValue in + updateState { state in + var state = state + state.updatingOnlyAllowPremiumNonContacts = settingValue + return state + } + let applyTimeout: Signal = privacySettingsPromise.get() + |> filter { $0 != nil } + |> take(1) + |> deliverOnMainQueue + |> mapToSignal { value -> Signal in + if let value = value { + var globalSettings = value.globalSettings + globalSettings.nonContactChatsRequirePremium = settingValue + + privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, bio: value.bio, globalSettings: globalSettings, accountRemovalTimeout: value.accountRemovalTimeout, messageAutoremoveTimeout: value.messageAutoremoveTimeout))) + } + return .complete() + } + + updateAutoArchiveDisposable.set((context.engine.privacy.updateNonContactChatsRequirePremium(value: settingValue) + |> mapToSignal { _ -> Signal in } + |> then(applyTimeout) + |> deliverOnMainQueue).start(completed: { + updateState { state in + var state = state + state.updatingOnlyAllowPremiumNonContacts = nil + return state + } + })) + }), true) + }) }) actionsDisposable.add(context.engine.peers.managedUpdatedRecentPeers().start()) diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift index 5968674bb2..574a9daa2b 100644 --- a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift @@ -218,7 +218,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) { var items: [ChatListItem] = [] - let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in + let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in }, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in gesture?.cancel() @@ -294,7 +294,8 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView forumTopicData: nil, topForumTopicItems: [], autoremoveTimeout: nil, - storyState: nil + storyState: nil, + requiresPremiumForMessaging: false )), editing: false, hasActiveRevealControls: false, diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift index 5fa37113bb..5f83dd3aec 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift @@ -366,7 +366,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) { var items: [ChatListItem] = [] - let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in + let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in }, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in gesture?.cancel() @@ -441,7 +441,8 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { forumTopicData: nil, topForumTopicItems: [], autoremoveTimeout: nil, - storyState: nil + storyState: nil, + requiresPremiumForMessaging: false )), editing: false, hasActiveRevealControls: false, diff --git a/submodules/ShareController/BUILD b/submodules/ShareController/BUILD index a1b763d9a3..455e9c3a54 100644 --- a/submodules/ShareController/BUILD +++ b/submodules/ShareController/BUILD @@ -39,6 +39,8 @@ swift_library( "//submodules/TelegramUI/Components/EmojiStatusComponent:EmojiStatusComponent", "//submodules/TelegramUI/Components/AnimationCache", "//submodules/TelegramUI/Components/MultiAnimationRenderer", + "//submodules/UndoUI", + "//submodules/PremiumUI", ], visibility = [ "//visibility:public", diff --git a/submodules/ShareController/Sources/ShareController.swift b/submodules/ShareController/Sources/ShareController.swift index 8a0fa81ad0..f67d91d407 100644 --- a/submodules/ShareController/Sources/ShareController.swift +++ b/submodules/ShareController/Sources/ShareController.swift @@ -20,6 +20,8 @@ import TelegramIntents import AnimationCache import MultiAnimationRenderer import ObjectiveC +import PremiumUI +import UndoUI private var ObjCKey_DeinitWatcher: Int? @@ -356,6 +358,7 @@ public protocol ShareControllerAccountContext: AnyObject { var accountId: AccountRecordId { get } var accountPeerId: EnginePeer.Id { get } var stateManager: AccountStateManager { get } + var engineData: TelegramEngine.EngineData { get } var animationCache: AnimationCache { get } var animationRenderer: MultiAnimationRenderer { get } var contentSettings: ContentSettings { get } @@ -376,6 +379,9 @@ public final class ShareControllerAppAccountContext: ShareControllerAccountConte public var stateManager: AccountStateManager { return self.context.account.stateManager } + public var engineData: TelegramEngine.EngineData { + return self.context.engine.data + } public var animationCache: AnimationCache { return self.context.animationCache } @@ -446,7 +452,7 @@ public final class ShareController: ViewController { private let segmentedValues: [ShareControllerSegmentedValue]? private let fromForeignApp: Bool - private let peers = Promise<([(EngineRenderedPeer, EnginePeer.Presence?)], EnginePeer)>() + private let peers = Promise<([(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)], EnginePeer)>() private let peersDisposable = MetaDisposable() private let readyDisposable = MetaDisposable() private let accountActiveDisposable = MetaDisposable() @@ -470,6 +476,8 @@ public final class ShareController: ViewController { public var debugAction: (() -> Void)? + public var parentNavigationController: NavigationController? + public convenience init(context: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil, shareAsLink: Bool = false) { self.init( environment: ShareControllerAppEnvironment(sharedContext: context.sharedContext), @@ -515,6 +523,7 @@ public final class ShareController: ViewController { super.init(navigationBarPresentationData: nil) self.statusBar.statusBarStyle = .Ignore + self.automaticallyControlPresentationContextLayout = false switch subject { case let .url(text): @@ -695,7 +704,7 @@ public final class ShareController: ViewController { fromPublicChannel = true } - self.displayNode = ShareControllerNode(environment: self.environment, presentationData: self.presentationData, presetText: self.presetText, defaultAction: self.defaultAction, requestLayout: { [weak self] transition in + self.displayNode = ShareControllerNode(controller: self, environment: self.environment, presentationData: self.presentationData, presetText: self.presetText, defaultAction: self.defaultAction, requestLayout: { [weak self] transition in self?.requestLayout(transition: transition) }, presentError: { [weak self] title, text in guard let strongSelf = self else { @@ -1197,6 +1206,31 @@ public final class ShareController: ViewController { strongSelf.view.endEditing(true) strongSelf.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) } + self.controllerNode.disabledPeerSelected = { [weak self] peer in + guard let self else { + return + } + + self.forEachController { c in + if let c = c as? UndoOverlayController { + c.dismiss() + } + return true + } + //TODO:localize + self.present(UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: nil, text: "**\(peer.compactDisplayTitle)** only accepts messages from contacts and **Premium** users.", customUndoText: (self.environment is ShareControllerAppEnvironment) ? "View" : nil, timeout: nil, linkAction: { _ in + }), elevatedLayout: false, animateInAsReplacement: false, action: { [weak self] action in + guard let self, let parentNavigationController = self.parentNavigationController, let context = self.currentContext as? ShareControllerAppAccountContext else { + return false + } + if case .undo = action { + self.controllerNode.cancel?() + let premiumController = PremiumIntroScreen(context: context.context, source: .settings) + parentNavigationController.pushViewController(premiumController) + } + return false + }), in: .current) + } self.controllerNode.debugAction = { [weak self] in self?.debugAction?() } @@ -2416,36 +2450,56 @@ public final class ShareController: ViewController { peer, tailChatList |> take(1) ) - |> mapToSignal { maybeAccountPeer, view -> Signal<([(EngineRenderedPeer, EnginePeer.Presence?)], EnginePeer), NoError> in + |> mapToSignal { maybeAccountPeer, view -> Signal<([(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)], EnginePeer), NoError> in let accountPeer = maybeAccountPeer! var peers: [EngineRenderedPeer] = [] + var possiblePremiumRequiredPeers = Set() for entry in view.0.entries.reversed() { switch entry { - case let .MessageEntry(entryData): - if let peer = entryData.renderedPeer.peers[entryData.renderedPeer.peerId], peer.id != accountPeer.id, canSendMessagesToPeer(peer) { - peers.append(EngineRenderedPeer(entryData.renderedPeer)) + case let .MessageEntry(entryData): + if let peer = entryData.renderedPeer.peers[entryData.renderedPeer.peerId], peer.id != accountPeer.id, canSendMessagesToPeer(peer) { + peers.append(EngineRenderedPeer(entryData.renderedPeer)) + if let user = peer as? TelegramUser, user.flags.contains(.requirePremium) { + possiblePremiumRequiredPeers.insert(user.id) } - default: - break + } + default: + break } } - let key = PostboxViewKey.peerPresences(peerIds: Set(peers.map(\.peerId))) - return account.stateManager.postbox.combinedView(keys: [key]) - |> map { views -> [EnginePeer.Id: EnginePeer.Presence?] in + let peerPresencesKey = PostboxViewKey.peerPresences(peerIds: Set(peers.map(\.peerId))) + + var keys: [PostboxViewKey] = [] + keys.append(peerPresencesKey) + + for id in possiblePremiumRequiredPeers { + keys.append(.cachedPeerData(peerId: id)) + } + + return account.stateManager.postbox.combinedView(keys: keys) + |> map { views -> ([EnginePeer.Id: EnginePeer.Presence?], [EnginePeer.Id: Bool]) in var result: [EnginePeer.Id: EnginePeer.Presence?] = [:] - if let view = views.views[key] as? PeerPresencesView { + if let view = views.views[peerPresencesKey] as? PeerPresencesView { result = view.presences.mapValues { value -> EnginePeer.Presence? in return EnginePeer.Presence(value) } } - return result + var requiresPremiumForMessaging: [EnginePeer.Id: Bool] = [:] + for id in possiblePremiumRequiredPeers { + if let view = views.views[.cachedPeerData(peerId: id)] as? CachedPeerDataView, let data = view.cachedPeerData as? CachedUserData { + requiresPremiumForMessaging[id] = data.flags.contains(.premiumRequired) + } else { + requiresPremiumForMessaging[id] = false + } + } + return (result, requiresPremiumForMessaging) } - |> map { presenceMap -> ([(EngineRenderedPeer, EnginePeer.Presence?)], EnginePeer) in - var resultPeers: [(EngineRenderedPeer, EnginePeer.Presence?)] = [] + |> map { presenceMap, requiresPremiumForMessaging -> ([(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)], EnginePeer) in + var resultPeers: [(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)] = [] for peer in peers { - resultPeers.append((peer, presenceMap[peer.peerId].flatMap { $0 })) + resultPeers.append((peer, presenceMap[peer.peerId].flatMap { $0 }, requiresPremiumForMessaging[peer.peerId] ?? false)) } return (resultPeers, accountPeer) } diff --git a/submodules/ShareController/Sources/ShareControllerNode.swift b/submodules/ShareController/Sources/ShareControllerNode.swift index c21786a1e8..cec5c9ebd2 100644 --- a/submodules/ShareController/Sources/ShareControllerNode.swift +++ b/submodules/ShareController/Sources/ShareControllerNode.swift @@ -22,6 +22,7 @@ enum ShareExternalState { } final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { + private weak var controller: ShareController? private let environment: ShareControllerEnvironment private var context: ShareControllerAccountContext? private var presentationData: PresentationData @@ -67,6 +68,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate var openStats: (() -> Void)? var completed: (([PeerId]) -> Void)? var present: ((ViewController) -> Void)? + var disabledPeerSelected: ((EnginePeer) -> Void)? let ready = Promise() private var didSetReady = false @@ -87,7 +89,8 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate private let showNames = ValuePromise(true) - init(environment: ShareControllerEnvironment, presentationData: PresentationData, presetText: String?, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool, immediatePeerId: PeerId?, fromForeignApp: Bool, forceTheme: PresentationTheme?, fromPublicChannel: Bool, segmentedValues: [ShareControllerSegmentedValue]?, shareStory: (() -> Void)?) { + init(controller: ShareController, environment: ShareControllerEnvironment, presentationData: PresentationData, presetText: String?, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool, immediatePeerId: PeerId?, fromForeignApp: Bool, forceTheme: PresentationTheme?, fromPublicChannel: Bool, segmentedValues: [ShareControllerSegmentedValue]?, shareStory: (() -> Void)?) { + self.controller = controller self.environment = environment self.presentationData = presentationData self.forceTheme = forceTheme @@ -272,9 +275,9 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate if search && added { strongSelf.controllerInteraction!.foundPeers = strongSelf.controllerInteraction!.foundPeers.filter { otherPeer in - return peer.peerId != otherPeer.peerId + return peer.peerId != otherPeer.peer.peerId } - strongSelf.controllerInteraction!.foundPeers.append(peer) + strongSelf.controllerInteraction!.foundPeers.append((peer, false)) strongSelf.peersContentNode?.updateFoundPeers() } @@ -325,6 +328,13 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate }) shareStory() } + }, disabledPeerSelected: { [weak self] peer in + guard let self else { + return + } + if let peer = peer.peer { + self.disabledPeerSelected?(peer) + } }) self.backgroundColor = nil @@ -708,6 +718,22 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate topicsContentNode.updateLayout(size: gridSize, isLandscape: layout.size.width > layout.size.height, bottomInset: self.contentNode === self.peersContentNode ? bottomGridInset : 0.0, transition: transition) } + + if let controller = self.controller { + let subLayout = ContainerViewLayout( + size: layout.size, + metrics: layout.metrics, + deviceMetrics: layout.deviceMetrics, + intrinsicInsets: UIEdgeInsets(top: 0.0, left: 4.0, bottom: layout.size.height - contentFrame.maxY - 6.0, right: 4.0), + safeInsets: layout.safeInsets, + additionalInsets: UIEdgeInsets(), + statusBarHeight: nil, + inputHeight: nil, + inputHeightIsInteractivellyChanging: false, + inVoiceOver: false + ) + controller.presentationContext.containerLayoutUpdated(subLayout, transition: transition) + } } private func contentNodeOffsetUpdated(_ contentOffset: CGFloat, transition: ContainedViewLayoutTransition) { @@ -1031,7 +1057,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate } } - func updatePeers(context: ShareControllerAccountContext, switchableAccounts: [ShareControllerSwitchableAccount], peers: [(EngineRenderedPeer, EnginePeer.Presence?)], accountPeer: EnginePeer, defaultAction: ShareControllerAction?) { + func updatePeers(context: ShareControllerAccountContext, switchableAccounts: [ShareControllerSwitchableAccount], peers: [(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)], accountPeer: EnginePeer, defaultAction: ShareControllerAction?) { self.context = context if let peersContentNode = self.peersContentNode, peersContentNode.accountPeer.id == accountPeer.id { @@ -1077,11 +1103,38 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate }, extendedInitialReveal: self.presetText != nil, segmentedValues: self.segmentedValues, fromPublicChannel: self.fromPublicChannel) self.peersContentNode = peersContentNode peersContentNode.openSearch = { [weak self] in - let _ = (_internal_recentlySearchedPeers(postbox: context.stateManager.postbox) + let signal: Signal<([RecentlySearchedPeer], [EnginePeer.Id: Bool]), NoError> = _internal_recentlySearchedPeers(postbox: context.stateManager.postbox) |> take(1) - |> deliverOnMainQueue).start(next: { peers in + |> mapToSignal { peers -> Signal<([RecentlySearchedPeer], [EnginePeer.Id: Bool]), NoError> in + var possiblePremiumRequiredPeers = Set() + for peer in peers { + if let user = peer.peer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + possiblePremiumRequiredPeers.insert(user.id) + } + } + + if let context = context as? ShareControllerAppAccountContext { + context.context.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: Array(possiblePremiumRequiredPeers)) + } + + return context.engineData.subscribe( + EngineDataMap( + possiblePremiumRequiredPeers.map(TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging.init(id:)) + ) + ) + |> map { peerRequiresPremiumForMessaging -> ([RecentlySearchedPeer], [EnginePeer.Id: Bool]) in + return (peers, peerRequiresPremiumForMessaging) + } + } + |> take(1) + let _ = (signal + |> deliverOnMainQueue).startStandalone(next: { peers, peerRequiresPremiumForMessaging in if let strongSelf = self { - let searchContentNode = ShareSearchContainerNode(environment: strongSelf.environment, context: context, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, controllerInteraction: strongSelf.controllerInteraction!, recentPeers: peers.filter({ $0.peer.peerId.namespace != Namespaces.Peer.SecretChat }).map({ EngineRenderedPeer($0.peer) })) + let recentPeers: [(peer: EngineRenderedPeer, requiresPremiumForMessaging: Bool)] = peers.filter({ $0.peer.peerId.namespace != Namespaces.Peer.SecretChat }).map({ + (EngineRenderedPeer($0.peer), peerRequiresPremiumForMessaging[$0.peer.peerId] ?? false) + }) + + let searchContentNode = ShareSearchContainerNode(environment: strongSelf.environment, context: context, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, controllerInteraction: strongSelf.controllerInteraction!, recentPeers: recentPeers) searchContentNode.cancel = { if let strongSelf = self, let peersContentNode = strongSelf.peersContentNode { strongSelf.transitionToContentNode(peersContentNode) diff --git a/submodules/ShareController/Sources/ShareControllerPeerGridItem.swift b/submodules/ShareController/Sources/ShareControllerPeerGridItem.swift index ce8927fa6f..f70a91a523 100644 --- a/submodules/ShareController/Sources/ShareControllerPeerGridItem.swift +++ b/submodules/ShareController/Sources/ShareControllerPeerGridItem.swift @@ -12,7 +12,7 @@ import AccountContext import ShimmerEffect final class ShareControllerInteraction { - var foundPeers: [EngineRenderedPeer] = [] + var foundPeers: [(peer: EngineRenderedPeer, requiresPremiumForMessaging: Bool)] = [] var selectedPeerIds = Set() var selectedPeers: [EngineRenderedPeer] = [] @@ -21,11 +21,13 @@ final class ShareControllerInteraction { let togglePeer: (EngineRenderedPeer, Bool) -> Void let selectTopic: (EngineRenderedPeer, Int64, MessageHistoryThreadData) -> Void let shareStory: (() -> Void)? + let disabledPeerSelected: (EngineRenderedPeer) -> Void - init(togglePeer: @escaping (EngineRenderedPeer, Bool) -> Void, selectTopic: @escaping (EngineRenderedPeer, Int64, MessageHistoryThreadData) -> Void, shareStory: (() -> Void)?) { + init(togglePeer: @escaping (EngineRenderedPeer, Bool) -> Void, selectTopic: @escaping (EngineRenderedPeer, Int64, MessageHistoryThreadData) -> Void, shareStory: (() -> Void)?, disabledPeerSelected: @escaping (EngineRenderedPeer) -> Void) { self.togglePeer = togglePeer self.selectTopic = selectTopic self.shareStory = shareStory + self.disabledPeerSelected = disabledPeerSelected } } @@ -94,11 +96,11 @@ final class ShareControllerGridSectionNode: ASDisplayNode { final class ShareControllerPeerGridItem: GridItem { enum ShareItem: Equatable { - case peer(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, topicId: Int64?, threadData: MessageHistoryThreadData?) + case peer(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, topicId: Int64?, threadData: MessageHistoryThreadData?, requiresPremiumForMessaging: Bool) case story(isMessage: Bool) var peerId: EnginePeer.Id? { - if case let .peer(peer, _, _, _) = self { + if case let .peer(peer, _, _, _, _) = self { return peer.peerId } else { return nil @@ -160,7 +162,7 @@ final class ShareControllerPeerGridItemNode: GridItemNode { private var absoluteLocation: (CGRect, CGSize)? var peerId: EnginePeer.Id? { - if let item = self.currentState?.item, case let .peer(peer, _, _, _) = item { + if let item = self.currentState?.item, case let .peer(peer, _, _, _, _) = item { return peer.peerId } else { return nil @@ -172,11 +174,15 @@ final class ShareControllerPeerGridItemNode: GridItemNode { super.init() - self.peerNode.toggleSelection = { [weak self] in + self.peerNode.toggleSelection = { [weak self] isDisabled in if let strongSelf = self { if let (_, _, _, _, maybeItem, search) = strongSelf.currentState, let item = maybeItem { - if case let .peer(peer, _, _, _) = item, let _ = peer.peers[peer.peerId] { - strongSelf.controllerInteraction?.togglePeer(peer, search) + if case let .peer(peer, _, _, _, _) = item, let _ = peer.peers[peer.peerId] { + if isDisabled { + strongSelf.controllerInteraction?.disabledPeerSelected(peer) + } else { + strongSelf.controllerInteraction?.togglePeer(peer, search) + } } else if case .story = item { strongSelf.controllerInteraction?.shareStory?() } @@ -207,7 +213,7 @@ final class ShareControllerPeerGridItemNode: GridItemNode { var effectivePresence: EnginePeer.Presence? let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) self.peerNode.theme = itemTheme - if let item, case let .peer(renderedPeer, presence, _, threadData) = item, let peer = renderedPeer.peer { + if let item, case let .peer(renderedPeer, presence, _, threadData, requiresPremiumForMessaging) = item, let peer = renderedPeer.peer { effectivePresence = presence var isOnline = false var isSupport = false @@ -236,6 +242,7 @@ final class ShareControllerPeerGridItemNode: GridItemNode { theme: theme, strings: strings, peer: renderedPeer, + requiresPremiumForMessaging: requiresPremiumForMessaging, customTitle: threadData?.info.title, iconId: threadData?.info.icon, iconColor: threadData?.info.iconColor ?? 0, @@ -295,7 +302,7 @@ final class ShareControllerPeerGridItemNode: GridItemNode { func updateSelection(animated: Bool) { var selected = false if let controllerInteraction = self.controllerInteraction, let (_, _, _, _, maybeItem, _) = self.currentState, let item = maybeItem { - if case let .peer(peer, _, _, _) = item { + if case let .peer(peer, _, _, _, _) = item { selected = controllerInteraction.selectedPeerIds.contains(peer.peerId) } } diff --git a/submodules/ShareController/Sources/SharePeersContainerNode.swift b/submodules/ShareController/Sources/SharePeersContainerNode.swift index 15eaac5cd5..60e45b0d7f 100644 --- a/submodules/ShareController/Sources/SharePeersContainerNode.swift +++ b/submodules/ShareController/Sources/SharePeersContainerNode.swift @@ -43,7 +43,7 @@ private struct SharePeerEntry: Comparable, Identifiable { var stableId: Int64 { switch self.item { - case let .peer(peer, _, _, _): + case let .peer(peer, _, _, _, _): return peer.peerId.toInt64() case .story: return 0 @@ -105,7 +105,7 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { private let extendedInitialReveal: Bool let accountPeer: EnginePeer - private let foundPeers = Promise<[EngineRenderedPeer]>([]) + private let foundPeers = Promise<[(peer: EngineRenderedPeer, requiresPremiumForMessaging: Bool)]>([]) private let disposable = MetaDisposable() private var entries: [SharePeerEntry] = [] @@ -136,7 +136,7 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { private var validLayout: (CGSize, CGFloat)? private var overrideGridOffsetTransition: ContainedViewLayoutTransition? - let peersValue = Promise<[(EngineRenderedPeer, EnginePeer.Presence?)]>() + let peersValue = Promise<[(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)]>() private var _tick: Int = 0 { didSet { @@ -145,7 +145,7 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { } private let tick = ValuePromise(0) - init(environment: ShareControllerEnvironment, context: ShareControllerAccountContext, switchableAccounts: [ShareControllerSwitchableAccount], theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, peers: [(EngineRenderedPeer, EnginePeer.Presence?)], accountPeer: EnginePeer, controllerInteraction: ShareControllerInteraction, externalShare: Bool, switchToAnotherAccount: @escaping () -> Void, debugAction: @escaping () -> Void, extendedInitialReveal: Bool, segmentedValues: [ShareControllerSegmentedValue]?, fromPublicChannel: Bool) { + init(environment: ShareControllerEnvironment, context: ShareControllerAccountContext, switchableAccounts: [ShareControllerSwitchableAccount], theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, peers: [(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)], accountPeer: EnginePeer, controllerInteraction: ShareControllerInteraction, externalShare: Bool, switchToAnotherAccount: @escaping () -> Void, debugAction: @escaping () -> Void, extendedInitialReveal: Bool, segmentedValues: [ShareControllerSegmentedValue]?, fromPublicChannel: Bool) { self.environment = environment self.context = context self.theme = theme @@ -175,22 +175,22 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { } var existingPeerIds: Set = Set() - entries.append(SharePeerEntry(index: index, item: .peer(peer: EngineRenderedPeer(peer: accountPeer), presence: nil, topicId: nil, threadData: nil), theme: theme, strings: strings)) + entries.append(SharePeerEntry(index: index, item: .peer(peer: EngineRenderedPeer(peer: accountPeer), presence: nil, topicId: nil, threadData: nil, requiresPremiumForMessaging: false), theme: theme, strings: strings)) existingPeerIds.insert(accountPeer.id) index += 1 - for peer in foundPeers.reversed() { + for (peer, requiresPremiumForMessaging) in foundPeers.reversed() { if !existingPeerIds.contains(peer.peerId) { - entries.append(SharePeerEntry(index: index, item: .peer(peer: peer, presence: nil, topicId: nil, threadData: nil), theme: theme, strings: strings)) + entries.append(SharePeerEntry(index: index, item: .peer(peer: peer, presence: nil, topicId: nil, threadData: nil, requiresPremiumForMessaging: requiresPremiumForMessaging), theme: theme, strings: strings)) existingPeerIds.insert(peer.peerId) index += 1 } } - for (peer, presence) in initialPeers { + for (peer, presence, requiresPremiumForMessaging) in initialPeers { if !existingPeerIds.contains(peer.peerId) { let thread = controllerInteraction?.selectedTopics[peer.peerId] - entries.append(SharePeerEntry(index: index, item: .peer(peer: peer, presence: presence, topicId: thread?.0, threadData: thread?.1), theme: theme, strings: strings)) + entries.append(SharePeerEntry(index: index, item: .peer(peer: peer, presence: presence, topicId: thread?.0, threadData: thread?.1, requiresPremiumForMessaging: requiresPremiumForMessaging), theme: theme, strings: strings)) existingPeerIds.insert(peer.peerId) index += 1 } diff --git a/submodules/ShareController/Sources/ShareSearchContainerNode.swift b/submodules/ShareController/Sources/ShareSearchContainerNode.swift index 4db2fa5471..3376a93e7d 100644 --- a/submodules/ShareController/Sources/ShareSearchContainerNode.swift +++ b/submodules/ShareController/Sources/ShareSearchContainerNode.swift @@ -2,6 +2,7 @@ import Foundation import UIKit import AsyncDisplayKit import TelegramCore +import Postbox import SwiftSignalKit import Display import TelegramPresentationData @@ -35,13 +36,13 @@ private enum ShareSearchRecentEntryStableId: Hashable { private enum ShareSearchRecentEntry: Comparable, Identifiable { case topPeers(PresentationTheme, PresentationStrings) - case peer(index: Int, theme: PresentationTheme, peer: EnginePeer, associatedPeer: EnginePeer?, presence: EnginePeer.Presence?, PresentationStrings) + case peer(index: Int, theme: PresentationTheme, peer: EnginePeer, associatedPeer: EnginePeer?, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool, strings: PresentationStrings) var stableId: ShareSearchRecentEntryStableId { switch self { case .topPeers: return .topPeers - case let .peer(_, _, peer, _, _, _): + case let .peer(_, _, peer, _, _, _, _): return .peerId(peer.id) } } @@ -60,8 +61,8 @@ private enum ShareSearchRecentEntry: Comparable, Identifiable { } else { return false } - case let .peer(lhsIndex, lhsTheme, lhsPeer, lhsAssociatedPeer, lhsPresence, lhsStrings): - if case let .peer(rhsIndex, rhsTheme, rhsPeer, rhsAssociatedPeer, rhsPresence, rhsStrings) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsStrings === rhsStrings && lhsTheme === rhsTheme && lhsPresence == rhsPresence { + case let .peer(lhsIndex, lhsTheme, lhsPeer, lhsAssociatedPeer, lhsPresence, lhsRequiresPremiumForMessaging, lhsStrings): + if case let .peer(rhsIndex, rhsTheme, rhsPeer, rhsAssociatedPeer, rhsPresence, rhsRequiresPremiumForMessaging, rhsStrings) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsStrings === rhsStrings && lhsTheme === rhsTheme && lhsPresence == rhsPresence && lhsRequiresPremiumForMessaging == rhsRequiresPremiumForMessaging { return true } else { return false @@ -73,11 +74,11 @@ private enum ShareSearchRecentEntry: Comparable, Identifiable { switch lhs { case .topPeers: return true - case let .peer(lhsIndex, _, _, _, _, _): + case let .peer(lhsIndex, _, _, _, _, _, _): switch rhs { case .topPeers: return false - case let .peer(rhsIndex, _, _, _, _, _): + case let .peer(rhsIndex, _, _, _, _, _, _): return lhsIndex <= rhsIndex } } @@ -87,13 +88,13 @@ private enum ShareSearchRecentEntry: Comparable, Identifiable { switch self { case let .topPeers(theme, strings): return ShareControllerRecentPeersGridItem(environment: environment, context: context, theme: theme, strings: strings, controllerInteraction: interfaceInteraction) - case let .peer(_, theme, peer, associatedPeer, presence, strings): + case let .peer(_, theme, peer, associatedPeer, presence, requiresPremiumForMessaging, strings): var peers: [EnginePeer.Id: EnginePeer] = [peer.id: peer] if let associatedPeer = associatedPeer { peers[associatedPeer.id] = associatedPeer } let peer = EngineRenderedPeer(peerId: peer.id, peers: peers, associatedMedia: [:]) - return ShareControllerPeerGridItem(environment: environment, context: context, theme: theme, strings: strings, item: .peer(peer: peer, presence: presence, topicId: nil, threadData: nil), controllerInteraction: interfaceInteraction, sectionTitle: strings.DialogList_SearchSectionRecent, search: true) + return ShareControllerPeerGridItem(environment: environment, context: context, theme: theme, strings: strings, item: .peer(peer: peer, presence: presence, topicId: nil, threadData: nil, requiresPremiumForMessaging: requiresPremiumForMessaging), controllerInteraction: interfaceInteraction, sectionTitle: strings.DialogList_SearchSectionRecent, search: true) } } } @@ -102,6 +103,7 @@ private struct ShareSearchPeerEntry: Comparable, Identifiable { let index: Int32 let peer: EngineRenderedPeer? let presence: EnginePeer.Presence? + let requiresPremiumForMessaging: Bool let theme: PresentationTheme let strings: PresentationStrings @@ -120,6 +122,12 @@ private struct ShareSearchPeerEntry: Comparable, Identifiable { if lhs.peer != rhs.peer { return false } + if lhs.presence != rhs.presence { + return false + } + if lhs.requiresPremiumForMessaging != rhs.requiresPremiumForMessaging { + return false + } if lhs.theme !== rhs.theme { return false } @@ -133,7 +141,7 @@ private struct ShareSearchPeerEntry: Comparable, Identifiable { func item(environment: ShareControllerEnvironment, context: ShareControllerAccountContext, interfaceInteraction: ShareControllerInteraction) -> GridItem { // let item: ShareControllerPeerGridItem.ShareItem // item = self.peer.flatMap { .peer(peer: $0, presence: self.presence, topicId: nil, threadData: nil) } - return ShareControllerPeerGridItem(environment: environment, context: context, theme: self.theme, strings: self.strings, item: self.peer.flatMap({ .peer(peer: $0, presence: self.presence, topicId: nil, threadData: nil) }), controllerInteraction: interfaceInteraction, search: true) + return ShareControllerPeerGridItem(environment: environment, context: context, theme: self.theme, strings: self.strings, item: self.peer.flatMap({ .peer(peer: $0, presence: self.presence, topicId: nil, threadData: nil, requiresPremiumForMessaging: self.requiresPremiumForMessaging) }), controllerInteraction: interfaceInteraction, search: true) } } @@ -199,7 +207,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { private let searchQuery = ValuePromise("", ignoreRepeated: true) private let searchDisposable = MetaDisposable() - init(environment: ShareControllerEnvironment, context: ShareControllerAccountContext, theme: PresentationTheme, strings: PresentationStrings, controllerInteraction: ShareControllerInteraction, recentPeers recentPeerList: [EngineRenderedPeer]) { + init(environment: ShareControllerEnvironment, context: ShareControllerAccountContext, theme: PresentationTheme, strings: PresentationStrings, controllerInteraction: ShareControllerInteraction, recentPeers recentPeerList: [(peer: EngineRenderedPeer, requiresPremiumForMessaging: Bool)]) { self.environment = environment self.context = context self.theme = theme @@ -260,8 +268,65 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { } ) - return combineLatest(accountPeer, foundLocalPeers, foundRemotePeers) - |> map { accountPeer, foundLocalPeers, foundRemotePeers -> ([ShareSearchPeerEntry]?, Bool) in + struct FoundPeers { + var foundLocalPeers: [RenderedPeer] + var foundRemotePeers: ([FoundPeer], [FoundPeer], Bool) + } + + let foundPeers = Promise() + foundPeers.set(combineLatest( + foundLocalPeers, + foundRemotePeers + ) + |> map { foundLocalPeers, foundRemotePeers -> FoundPeers in + return FoundPeers( + foundLocalPeers: foundLocalPeers, + foundRemotePeers: foundRemotePeers + ) + }) + + let peerRequiresPremiumForMessaging: Signal<[EnginePeer.Id: Bool], NoError> + peerRequiresPremiumForMessaging = foundPeers.get() + |> map { foundPeers -> Set in + var result = Set() + + for peer in foundPeers.foundLocalPeers { + if let user = peer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + result.insert(user.id) + } + } + + for peer in foundPeers.foundRemotePeers.0 { + if let user = peer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + result.insert(user.id) + } + } + for peer in foundPeers.foundRemotePeers.1 { + if let user = peer.peer as? TelegramUser, user.flags.contains(.requirePremium) { + result.insert(user.id) + } + } + + return result + } + |> distinctUntilChanged + |> mapToSignal { peerIds -> Signal<[EnginePeer.Id: Bool], NoError> in + if let context = context as? ShareControllerAppAccountContext { + context.context.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: Array(peerIds)) + } + + return context.engineData.subscribe( + EngineDataMap( + peerIds.map(TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging.init(id:)) + ) + ) + } + + return combineLatest(accountPeer, foundPeers.get(), peerRequiresPremiumForMessaging) + |> map { accountPeer, foundPeers, peerRequiresPremiumForMessaging -> ([ShareSearchPeerEntry]?, Bool) in + let foundLocalPeers = foundPeers.foundLocalPeers + let foundRemotePeers = foundPeers.foundRemotePeers + var entries: [ShareSearchPeerEntry] = [] var index: Int32 = 0 @@ -271,7 +336,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { if strings.DialogList_SavedMessages.lowercased().hasPrefix(lowercasedQuery) || "saved messages".hasPrefix(lowercasedQuery) { if !existingPeerIds.contains(accountPeer.id) { existingPeerIds.insert(accountPeer.id) - entries.append(ShareSearchPeerEntry(index: index, peer: EngineRenderedPeer(peer: EnginePeer(accountPeer)), presence: nil, theme: theme, strings: strings)) + entries.append(ShareSearchPeerEntry(index: index, peer: EngineRenderedPeer(peer: EnginePeer(accountPeer)), presence: nil, requiresPremiumForMessaging: false, theme: theme, strings: strings)) index += 1 } } @@ -280,7 +345,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { if let peer = renderedPeer.peers[renderedPeer.peerId], peer.id != accountPeer.id { if !existingPeerIds.contains(renderedPeer.peerId) && canSendMessagesToPeer(peer) { existingPeerIds.insert(renderedPeer.peerId) - entries.append(ShareSearchPeerEntry(index: index, peer: EngineRenderedPeer(renderedPeer), presence: nil, theme: theme, strings: strings)) + entries.append(ShareSearchPeerEntry(index: index, peer: EngineRenderedPeer(renderedPeer), presence: nil, requiresPremiumForMessaging: peerRequiresPremiumForMessaging[peer.id] ?? false, theme: theme, strings: strings)) index += 1 } } @@ -290,7 +355,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { if foundRemotePeers.2 { isPlaceholder = true for _ in 0 ..< 4 { - entries.append(ShareSearchPeerEntry(index: index, peer: nil, presence: nil, theme: theme, strings: strings)) + entries.append(ShareSearchPeerEntry(index: index, peer: nil, presence: nil, requiresPremiumForMessaging: false, theme: theme, strings: strings)) index += 1 } } else { @@ -298,7 +363,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { let peer = foundPeer.peer if !existingPeerIds.contains(peer.id) && canSendMessagesToPeer(peer) { existingPeerIds.insert(peer.id) - entries.append(ShareSearchPeerEntry(index: index, peer: EngineRenderedPeer(peer: EnginePeer(foundPeer.peer)), presence: nil, theme: theme, strings: strings)) + entries.append(ShareSearchPeerEntry(index: index, peer: EngineRenderedPeer(peer: EnginePeer(foundPeer.peer)), presence: nil, requiresPremiumForMessaging: peerRequiresPremiumForMessaging[peer.id] ?? false, theme: theme, strings: strings)) index += 1 } } @@ -307,7 +372,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { let peer = foundPeer.peer if !existingPeerIds.contains(peer.id) && canSendMessagesToPeer(peer) { existingPeerIds.insert(peer.id) - entries.append(ShareSearchPeerEntry(index: index, peer: EngineRenderedPeer(peer: EnginePeer(peer)), presence: nil, theme: theme, strings: strings)) + entries.append(ShareSearchPeerEntry(index: index, peer: EngineRenderedPeer(peer: EnginePeer(peer)), presence: nil, requiresPremiumForMessaging: peerRequiresPremiumForMessaging[peer.id] ?? false, theme: theme, strings: strings)) index += 1 } } @@ -370,9 +435,9 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { recentItemList.append(.topPeers(theme, strings)) } var index = 0 - for peer in recentPeerList { + for (peer, requiresPremiumForMessaging) in recentPeerList { if let mainPeer = peer.peers[peer.peerId], canSendMessagesToPeer(mainPeer._asPeer()) { - recentItemList.append(.peer(index: index, theme: theme, peer: mainPeer, associatedPeer: mainPeer._asPeer().associatedPeerId.flatMap { peer.peers[$0] }, presence: nil, strings)) + recentItemList.append(.peer(index: index, theme: theme, peer: mainPeer, associatedPeer: mainPeer._asPeer().associatedPeerId.flatMap { peer.peers[$0] }, presence: nil, requiresPremiumForMessaging: requiresPremiumForMessaging, strings: strings)) index += 1 } } @@ -476,7 +541,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { switch $0 { case .topPeers: return false - case let .peer(_, _, peer, _, _, _): + case let .peer(_, _, peer, _, _, _, _): return peer.id == ensurePeerVisibleOnLayout } }) { diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift index 62902b77e8..dde199f34a 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift @@ -70,7 +70,7 @@ extension TelegramUser { if (flags2 & (1 << 2)) != 0 { userFlags.insert(.isCloseFriend) } - if (flags2 & (1 << 6)) != 0 { + if (flags2 & (1 << 10)) != 0 { userFlags.insert(.requirePremium) } var storiesHidden: Bool? diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index d07ff0584a..1e6e6000a5 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -300,6 +300,9 @@ public final class AccountViewTracker { private var refreshStoriesForPeerIdsAndTimestamps: [PeerId: Int32] = [:] private var refreshStoriesForPeerIdsDebounceDisposable: Disposable? private var pendingRefreshStoriesForPeerIds: [PeerId] = [] + private var refreshCanSendMessagesForPeerIdsAndTimestamps: [PeerId: Int32] = [:] + private var refreshCanSendMessagesForPeerIdsDebounceDisposable: Disposable? + private var pendingRefreshCanSendMessagesForPeerIds: [PeerId] = [] private var updatedSeenPersonalMessageIds = Set() private var updatedReactionsSeenForMessageIds = Set() @@ -1368,6 +1371,110 @@ public final class AccountViewTracker { } } + public func refreshCanSendMessagesForPeerIds(peerIds: [PeerId]) { + self.queue.async { + self.pendingRefreshCanSendMessagesForPeerIds.append(contentsOf: peerIds) + + if self.refreshCanSendMessagesForPeerIdsDebounceDisposable == nil { + self.refreshCanSendMessagesForPeerIdsDebounceDisposable = (Signal.complete() |> delay(0.15, queue: self.queue)).start(completed: { + self.refreshCanSendMessagesForPeerIdsDebounceDisposable = nil + + let pendingPeerIds = self.pendingRefreshCanSendMessagesForPeerIds + self.pendingRefreshCanSendMessagesForPeerIds.removeAll() + self.internalRefreshCanSendMessagesStatsForPeerIds(peerIds: pendingPeerIds) + }) + } + } + } + + private func internalRefreshCanSendMessagesStatsForPeerIds(peerIds: [PeerId]) { + self.queue.async { + var addedPeerIds: [PeerId] = [] + let timestamp = Int32(CFAbsoluteTimeGetCurrent()) + for peerId in peerIds { + let messageTimestamp = self.refreshCanSendMessagesForPeerIdsAndTimestamps[peerId] + var refresh = false + if let messageTimestamp = messageTimestamp { + refresh = messageTimestamp < timestamp - 60 * 60 + } else { + refresh = true + } + + if refresh { + self.refreshCanSendMessagesForPeerIdsAndTimestamps[peerId] = timestamp + addedPeerIds.append(peerId) + } + } + if !addedPeerIds.isEmpty { + let disposableId = self.nextUpdatedUnsupportedMediaDisposableId + self.nextUpdatedUnsupportedMediaDisposableId += 1 + + if let account = self.account { + let signal = account.postbox.transaction { transaction -> [(PeerId, Api.InputUser)] in + return addedPeerIds.compactMap { id -> (PeerId, Api.InputUser)? in + if let user = transaction.getPeer(id).flatMap(apiInputUser) { + return (id, user) + } else { + return nil + } + } + } + |> mapToSignal { inputPeers -> Signal in + guard !inputPeers.isEmpty else { + return .complete() + } + + var requests: [Signal] = [] + + let batchCount = 100 + var startIndex = 0 + while startIndex < inputPeers.count { + var slice: [(PeerId, Api.InputUser)] = [] + for i in startIndex ..< min(startIndex + batchCount, inputPeers.count) { + slice.append(inputPeers[i]) + } + startIndex += batchCount + requests.append(account.network.request(Api.functions.users.getIsPremiumRequiredToContact(id: slice.map(\.1))) + |> `catch` { _ -> Signal<[Api.Bool], NoError> in + return .single([]) + } + |> mapToSignal { result -> Signal in + return account.postbox.transaction { transaction in + for i in 0 ..< result.count { + if i < slice.count { + let value = result[i] + transaction.updatePeerCachedData(peerIds: Set([slice[i].0]), update: { _, cachedData in + var cachedData = cachedData as? CachedUserData ?? CachedUserData(about: nil, botInfo: nil, editableBotInfo: nil, peerStatusSettings: nil, pinnedMessageId: nil, isBlocked: false, commonGroupCount: 0, voiceCallsAvailable: true, videoCallsAvailable: true, callsPrivate: true, canPinMessages: true, hasScheduledMessages: true, autoremoveTimeout: .unknown, themeEmoticon: nil, photo: .unknown, personalPhoto: .unknown, fallbackPhoto: .unknown, premiumGiftOptions: [], voiceMessagesAvailable: true, wallpaper: nil, flags: []) + var flags = cachedData.flags + if case .boolTrue = value { + flags.insert(.premiumRequired) + } else { + flags.remove(.premiumRequired) + } + cachedData = cachedData.withUpdatedFlags(flags) + return cachedData + }) + } + } + } + |> ignoreValues + }) + } + + return combineLatest(requests) + |> ignoreValues + } + |> afterDisposed { [weak self] in + self?.queue.async { + self?.updatedUnsupportedMediaDisposables.set(nil, forKey: disposableId) + } + } + self.updatedUnsupportedMediaDisposables.set(signal.start(), forKey: disposableId) + } + } + } + } + public func updateMarkAllMentionsSeen(peerId: PeerId, threadId: Int64?) { self.queue.async { guard let account = self.account else { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift index 661b57902c..842e7d34c6 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift @@ -1022,6 +1022,51 @@ public extension TelegramEngine.EngineData.Item { } } + public struct IsPremiumRequiredForMessaging: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, AnyPostboxViewDataItem { + public typealias Result = Bool + + fileprivate var id: EnginePeer.Id + public var mapKey: EnginePeer.Id { + return self.id + } + + public init(id: EnginePeer.Id) { + self.id = id + } + + func keys(data: TelegramEngine.EngineData) -> [PostboxViewKey] { + return [ + .cachedPeerData(peerId: self.id), + .basicPeer(data.accountPeerId) + ] + } + + func _extract(data: TelegramEngine.EngineData, views: [PostboxViewKey: PostboxView]) -> Any { + guard let basicPeerView = views[.basicPeer(data.accountPeerId)] as? BasicPeerView else { + assertionFailure() + return false + } + guard let view = views[.cachedPeerData(peerId: self.id)] as? CachedPeerDataView else { + assertionFailure() + return false + } + + if let peer = basicPeerView.peer, peer.isPremium { + return false + } + + if self.id.namespace == Namespaces.Peer.CloudUser { + if let cachedData = view.cachedPeerData as? CachedUserData { + return cachedData.flags.contains(.premiumRequired) + } else { + return false + } + } else { + return false + } + } + } + public struct LegacyGroupParticipants: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { public typealias Result = EnginePeerCachedInfoItem<[EngineLegacyGroupParticipant]> diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/TelegramEngineData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/TelegramEngineData.swift index 87d5c3390f..de74d882fb 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/TelegramEngineData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/TelegramEngineData.swift @@ -12,9 +12,9 @@ public protocol TelegramEngineMapKeyDataItem { } protocol AnyPostboxViewDataItem { - var keys: [PostboxViewKey] { get } + func keys(data: TelegramEngine.EngineData) -> [PostboxViewKey] - func _extract(views: [PostboxViewKey: PostboxView]) -> Any + func _extract(data: TelegramEngine.EngineData, views: [PostboxViewKey: PostboxView]) -> Any } protocol PostboxViewDataItem: TelegramEngineDataItem, AnyPostboxViewDataItem { @@ -24,11 +24,11 @@ protocol PostboxViewDataItem: TelegramEngineDataItem, AnyPostboxViewDataItem { } extension PostboxViewDataItem { - var keys: [PostboxViewKey] { + func keys(data: TelegramEngine.EngineData) -> [PostboxViewKey] { return [self.key] } - func _extract(views: [PostboxViewKey: PostboxView]) -> Any { + func _extract(data: TelegramEngine.EngineData, views: [PostboxViewKey: PostboxView]) -> Any { return self.extract(view: views[self.key]!) } } @@ -42,21 +42,21 @@ public final class EngineDataMap [PostboxViewKey] { var keys = Set() for item in self.items { - for key in (item as! AnyPostboxViewDataItem).keys { + for key in (item as! AnyPostboxViewDataItem).keys(data: data) { keys.insert(key) } } return Array(keys) } - func _extract(views: [PostboxViewKey: PostboxView]) -> Any { + func _extract(data: TelegramEngine.EngineData, views: [PostboxViewKey: PostboxView]) -> Any { var result: [Item.Key: Item.Result] = [:] for item in self.items { - let itemResult = (item as! AnyPostboxViewDataItem)._extract(views: views) + let itemResult = (item as! AnyPostboxViewDataItem)._extract(data: data, views: views) result[item.mapKey] = (itemResult as! Item.Result) } @@ -73,21 +73,21 @@ public final class EngineDataList [PostboxViewKey] { var keys = Set() for item in self.items { - for key in (item as! AnyPostboxViewDataItem).keys { + for key in (item as! AnyPostboxViewDataItem).keys(data: data) { keys.insert(key) } } return Array(keys) } - func _extract(views: [PostboxViewKey: PostboxView]) -> Any { + func _extract(data: TelegramEngine.EngineData, views: [PostboxViewKey: PostboxView]) -> Any { var result: [Item.Result] = [] for item in self.items { - let itemResult = (item as! AnyPostboxViewDataItem)._extract(views: views) + let itemResult = (item as! AnyPostboxViewDataItem)._extract(data: data, views: views) result.append(itemResult as! Item.Result) } @@ -104,21 +104,21 @@ public final class EngineDataOptional: TelegramEng self.item = item } - var keys: [PostboxViewKey] { + func keys(data: TelegramEngine.EngineData) -> [PostboxViewKey] { var keys = Set() if let item = self.item { - for key in (item as! AnyPostboxViewDataItem).keys { + for key in (item as! AnyPostboxViewDataItem).keys(data: data) { keys.insert(key) } } return Array(keys) } - func _extract(views: [PostboxViewKey: PostboxView]) -> Any { + func _extract(data: TelegramEngine.EngineData, views: [PostboxViewKey: PostboxView]) -> Any { var result: Item.Result? if let item = self.item { - let itemResult = (item as! AnyPostboxViewDataItem)._extract(views: views) + let itemResult = (item as! AnyPostboxViewDataItem)._extract(data: data, views: views) result = (itemResult as! Item.Result) } @@ -131,16 +131,18 @@ public extension TelegramEngine { public struct Item { } + let accountPeerId: PeerId private let postbox: Postbox - public init(postbox: Postbox) { + public init(accountPeerId: PeerId, postbox: Postbox) { + self.accountPeerId = accountPeerId self.postbox = postbox } private func _subscribe(items: [AnyPostboxViewDataItem]) -> Signal<[Any], NoError> { var keys = Set() for item in items { - for key in item.keys { + for key in item.keys(data: self) { keys.insert(key) } } @@ -149,7 +151,7 @@ public extension TelegramEngine { var results: [Any] = [] for item in items { - results.append(item._extract(views: views.views)) + results.append(item._extract(data: self, views: views.views)) } return results @@ -340,6 +342,55 @@ public extension TelegramEngine { } } + public func subscribe< + T0: TelegramEngineDataItem, + T1: TelegramEngineDataItem, + T2: TelegramEngineDataItem, + T3: TelegramEngineDataItem, + T4: TelegramEngineDataItem, + T5: TelegramEngineDataItem, + T6: TelegramEngineDataItem + >( + _ t0: T0, + _ t1: T1, + _ t2: T2, + _ t3: T3, + _ t4: T4, + _ t5: T5, + _ t6: T6 + ) -> Signal< + ( + T0.Result, + T1.Result, + T2.Result, + T3.Result, + T4.Result, + T5.Result, + T6.Result + ), + NoError> { + return self._subscribe(items: [ + t0 as! AnyPostboxViewDataItem, + t1 as! AnyPostboxViewDataItem, + t2 as! AnyPostboxViewDataItem, + t3 as! AnyPostboxViewDataItem, + t4 as! AnyPostboxViewDataItem, + t5 as! AnyPostboxViewDataItem, + t6 as! AnyPostboxViewDataItem + ]) + |> map { results -> (T0.Result, T1.Result, T2.Result, T3.Result, T4.Result, T5.Result, T6.Result) in + return ( + results[0] as! T0.Result, + results[1] as! T1.Result, + results[2] as! T2.Result, + results[3] as! T3.Result, + results[4] as! T4.Result, + results[5] as! T5.Result, + results[6] as! T6.Result + ) + } + } + public func get< T0: TelegramEngineDataItem, T1: TelegramEngineDataItem diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index d0efcf1e74..beed309046 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -1277,6 +1277,75 @@ public extension TelegramEngine { public func isPremiumRequiredToContact(_ peerIds: [EnginePeer.Id]) -> Signal<[EnginePeer.Id], NoError> { return _internal_updateIsPremiumRequiredToContact(account: self.account, peerIds: peerIds) } + + public func subscribeIsPremiumRequiredForMessaging(id: EnginePeer.Id) -> Signal { + if id.namespace != Namespaces.Peer.CloudUser { + return .single(false) + } + + return self.account.postbox.combinedView(keys: [ + PostboxViewKey.basicPeer(self.account.peerId), + PostboxViewKey.basicPeer(id), + PostboxViewKey.cachedPeerData(peerId: id) + ]) + |> map { views -> Bool in + guard let basicAccountPeerView = views.views[PostboxViewKey.basicPeer(self.account.peerId)] as? BasicPeerView else { + return false + } + guard let accountPeer = basicAccountPeerView.peer else { + return false + } + if accountPeer.isPremium { + return false + } + + guard let basicPeerView = views.views[PostboxViewKey.basicPeer(id)] as? BasicPeerView else { + return false + } + guard let user = basicPeerView.peer as? TelegramUser else { + return false + } + guard let cachedDataView = views.views[PostboxViewKey.cachedPeerData(peerId: id)] as? CachedPeerDataView else { + return false + } + if !user.flags.contains(.requirePremium) { + return false + } + + /*#if DEBUG + if "".isEmpty { + return true + } + #endif*/ + + if let cachedData = cachedDataView.cachedPeerData as? CachedUserData { + if cachedData.flags.contains(.premiumRequired) { + return true + } else { + return false + } + } else { + return true + } + } + |> distinctUntilChanged + |> mapToSignal { maybeValue -> Signal in + if !maybeValue { + return .single(false) + } + + return self.account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: id, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 44, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tag: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allScheduled), orderStatistics: []) + |> map { view -> Bool in + for entry in view.0.entries { + if entry.message.flags.contains(.Incoming) { + return false + } + } + return true + } + |> distinctUntilChanged + } + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift index 01ada4bf65..05a80077d9 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/TelegramEngine.swift @@ -73,7 +73,7 @@ public final class TelegramEngine { }() public lazy var data: EngineData = { - return EngineData(postbox: self.account.postbox) + return EngineData(accountPeerId: self.account.peerId, postbox: self.account.postbox) }() public lazy var orderedLists: OrderedLists = { diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift index dbaddd9023..e33f56e967 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift @@ -298,6 +298,11 @@ public enum PresentationResourceKey: Int32 { case chatReplyServiceBackgroundTemplateImage case chatBubbleCloseIcon + + case avatarPremiumLockBadgeBackground + case avatarPremiumLockBadge + case shareAvatarPremiumLockBadgeBackground + case shareAvatarPremiumLockBadge } public enum ChatExpiredStoryIndicatorType: Hashable { diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChatList.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChatList.swift index c41529fc28..0273cfc4b5 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChatList.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChatList.swift @@ -426,4 +426,66 @@ public struct PresentationResourcesChatList { return generateTintedImage(image: UIImage(bundleImageName: isActive ? "Chat List/StatusIconAutoremoveOn" : "Chat List/StatusIconAutoremoveOff"), color: isActive ? theme.list.itemAccentColor : theme.list.itemSecondaryTextColor) }) } + + public static func avatarPremiumLockBadgeBackground(_ theme: PresentationTheme) -> UIImage? { + return theme.image(PresentationResourceKey.avatarPremiumLockBadgeBackground.rawValue, { theme in + return generateFilledCircleImage(diameter: 17.0, color: .white)?.withRenderingMode(.alwaysTemplate) + }) + } + + public static func avatarPremiumLockBadge(_ theme: PresentationTheme) -> UIImage? { + return theme.image(PresentationResourceKey.avatarPremiumLockBadge.rawValue, { theme in + return generateImage(CGSize(width: 16.0, height: 16.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.addPath(CGPath(ellipseIn: CGRect(origin: CGPoint(), size: size), transform: nil)) + context.clip() + + var locations: [CGFloat] = [0.0, 1.0] + let colors: [CGColor] = [UIColor(rgb: 0x9981FF).cgColor, UIColor(rgb: 0xBA6DE9).cgColor] + + let colorSpace = CGColorSpaceCreateDeviceRGB() + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: 0.0), options: CGGradientDrawingOptions()) + + context.resetClip() + + if let image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/StatusLockIcon"), color: .white), let cgImage = image.cgImage { + let imageSize = image.size.fitted(CGSize(width: 8.0, height: 8.0)) + context.draw(cgImage, in: CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) * 0.5), y: floor((size.height - imageSize.height) * 0.5)), size: imageSize)) + } + }) + }) + } + + public static func shareAvatarPremiumLockBadgeBackground(_ theme: PresentationTheme) -> UIImage? { + return theme.image(PresentationResourceKey.shareAvatarPremiumLockBadgeBackground.rawValue, { theme in + return generateFilledCircleImage(diameter: 22.0, color: .white)?.withRenderingMode(.alwaysTemplate) + }) + } + + public static func shareAvatarPremiumLockBadge(_ theme: PresentationTheme) -> UIImage? { + return theme.image(PresentationResourceKey.shareAvatarPremiumLockBadge.rawValue, { theme in + return generateImage(CGSize(width: 20.0, height: 20.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.addPath(CGPath(ellipseIn: CGRect(origin: CGPoint(), size: size), transform: nil)) + context.clip() + + var locations: [CGFloat] = [0.0, 1.0] + let colors: [CGColor] = [UIColor(rgb: 0x9981FF).cgColor, UIColor(rgb: 0xBA6DE9).cgColor] + + let colorSpace = CGColorSpaceCreateDeviceRGB() + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: 0.0), options: CGGradientDrawingOptions()) + + context.resetClip() + + if let image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/StatusLockIcon"), color: .white), let cgImage = image.cgImage { + let imageSize = image.size.fitted(CGSize(width: 14.0, height: 14.0)) + context.draw(cgImage, in: CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) * 0.5), y: floor((size.height - imageSize.height) * 0.5)), size: imageSize)) + } + }) + }) + } } diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index d05ee13e10..0e0ee8712c 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -422,6 +422,7 @@ swift_library( "//submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem", "//submodules/Components/MultilineTextComponent", "//submodules/TelegramUI/Components/PlainButtonComponent", + "//submodules/Components/BalancedTextComponent", ] + select({ "@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets, "//build-system:ios_sim_arm64": [], diff --git a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift index 9f9b181fce..878eaa3604 100644 --- a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift @@ -166,6 +166,7 @@ public final class ChatRecentActionsController: TelegramBaseController { }, addDoNotTranslateLanguage: { _ in }, hideTranslationPanel: { }, openPremiumGift: { + }, openPremiumRequiredForMessaging: { }, updateHistoryFilter: { _ in }, requestLayout: { _ in }, chatController: { diff --git a/submodules/TelegramUI/Components/MessageInputPanelComponent/BUILD b/submodules/TelegramUI/Components/MessageInputPanelComponent/BUILD index dec402da52..1963f35d45 100644 --- a/submodules/TelegramUI/Components/MessageInputPanelComponent/BUILD +++ b/submodules/TelegramUI/Components/MessageInputPanelComponent/BUILD @@ -40,6 +40,7 @@ swift_library( "//submodules/ContextUI", "//submodules/TelegramUI/Components/ContextReferenceButtonComponent", "//submodules/TelegramUI/Components/Stories/ForwardInfoPanelComponent", + "//submodules/TelegramUI/Components/PlainButtonComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift index 19a8992f9a..35ce217451 100644 --- a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift +++ b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift @@ -20,6 +20,8 @@ import AnimatedCountLabelNode import MessageInputActionButtonComponent import ContextReferenceButtonComponent import ForwardInfoPanelComponent +import MultilineTextComponent +import PlainButtonComponent private var sharedIsReduceTransparencyEnabled = UIAccessibility.isReduceTransparencyEnabled @@ -86,6 +88,42 @@ public final class MessageInputPanelComponent: Component { case counter([CounterItem]) } + public enum DisabledPlaceholder: Equatable { + enum Kind { + case text + case premiumRequired + } + + case text(String) + case premiumRequired(title: String, subtitle: String, action: () -> Void) + + var kind: Kind { + switch self { + case .text: + return .text + case .premiumRequired: + return .premiumRequired + } + } + + public static func ==(lhs: DisabledPlaceholder, rhs: DisabledPlaceholder) -> Bool { + switch lhs { + case let .text(value): + if case .text(value) = rhs { + return true + } else { + return false + } + case let .premiumRequired(title, subtitle, _): + if case .premiumRequired(title, subtitle, _) = rhs { + return true + } else { + return false + } + } + } + } + public final class ExternalState { public fileprivate(set) var isEditing: Bool = false public fileprivate(set) var hasText: Bool = false @@ -148,7 +186,7 @@ public final class MessageInputPanelComponent: Component { public let hideKeyboard: Bool public let customInputView: UIView? public let forceIsEditing: Bool - public let disabledPlaceholder: String? + public let disabledPlaceholder: DisabledPlaceholder? public let header: AnyComponent? public let isChannel: Bool public let storyItem: EngineStoryItem? @@ -203,7 +241,7 @@ public final class MessageInputPanelComponent: Component { hideKeyboard: Bool, customInputView: UIView?, forceIsEditing: Bool, - disabledPlaceholder: String?, + disabledPlaceholder: DisabledPlaceholder?, header: AnyComponent?, isChannel: Bool, storyItem: EngineStoryItem?, @@ -676,7 +714,8 @@ public final class MessageInputPanelComponent: Component { let baseFieldHeight: CGFloat = 40.0 var transition = transition - if transition.animation.isImmediate, let previousComponent = self.component, previousComponent.storyItem?.id == component.storyItem?.id, component.isChannel { + let previousComponent = self.component + if transition.animation.isImmediate, let previousComponent, previousComponent.storyItem?.id == component.storyItem?.id, component.isChannel { transition = transition.withAnimation(.curve(duration: 0.3, curve: .spring)) } @@ -1034,23 +1073,56 @@ public final class MessageInputPanelComponent: Component { } } - if let disabledPlaceholderText = component.disabledPlaceholder, !component.isChannel { + if let disabledPlaceholderValue = component.disabledPlaceholder, !component.isChannel { let disabledPlaceholder: ComponentView var disabledPlaceholderTransition = transition - if let current = self.disabledPlaceholder { + if let current = self.disabledPlaceholder, let previous = previousComponent?.disabledPlaceholder, disabledPlaceholderValue.kind == previous.kind { disabledPlaceholder = current } else { + self.disabledPlaceholder?.view?.removeFromSuperview() + disabledPlaceholderTransition = .immediate disabledPlaceholder = ComponentView() self.disabledPlaceholder = disabledPlaceholder } + + let contents: AnyComponent + var leftAlignment = false + switch disabledPlaceholderValue { + case let .text(text): + contents = AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: text, font: Font.regular(17.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.3))) + )) + case let .premiumRequired(title, subtitle, action): + leftAlignment = true + contents = AnyComponent(PlainButtonComponent( + content: AnyComponent(VStack([ + AnyComponentWithIdentity(id: 0, component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: title, font: Font.regular(13.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.3))) + ))), + AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: subtitle, font: Font.regular(13.0), textColor: component.theme.list.itemAccentColor)) + ))) + ], alignment: .left, spacing: 1.0)), + effectAlignment: .center, + action: { + action() + } + )) + } + let disabledPlaceholderSize = disabledPlaceholder.update( transition: .immediate, - component: AnyComponent(Text(text: disabledPlaceholderText, font: Font.regular(17.0), color: UIColor(rgb: 0xffffff, alpha: 0.3))), + component: contents, environment: {}, containerSize: CGSize(width: fieldBackgroundFrame.width - 8.0 * 2.0, height: 100.0) ) - let disabledPlaceholderFrame = CGRect(origin: CGPoint(x: fieldBackgroundFrame.minX + floor((fieldBackgroundFrame.width - disabledPlaceholderSize.width) * 0.5), y: fieldBackgroundFrame.minY + floor((fieldBackgroundFrame.height - disabledPlaceholderSize.height) * 0.5)), size: disabledPlaceholderSize) + let disabledPlaceholderFrame: CGRect + if leftAlignment { + disabledPlaceholderFrame = CGRect(origin: CGPoint(x: 12.0, y: fieldBackgroundFrame.minY + floor((fieldBackgroundFrame.height - disabledPlaceholderSize.height) * 0.5)), size: disabledPlaceholderSize) + } else { + disabledPlaceholderFrame = CGRect(origin: CGPoint(x: fieldBackgroundFrame.minX + floor((fieldBackgroundFrame.width - disabledPlaceholderSize.width) * 0.5), y: fieldBackgroundFrame.minY + floor((fieldBackgroundFrame.height - disabledPlaceholderSize.height) * 0.5)), size: disabledPlaceholderSize) + } if let disabledPlaceholderView = disabledPlaceholder.view { if disabledPlaceholderView.superview == nil { self.addSubview(disabledPlaceholderView) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 39a46e66c3..55e3528daf 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -412,6 +412,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode { }, addDoNotTranslateLanguage: { _ in }, hideTranslationPanel: { }, openPremiumGift: { + }, openPremiumRequiredForMessaging: { }, updateHistoryFilter: { _ in }, requestLayout: { _ in }, chatController: { @@ -9345,7 +9346,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro subject: nil, keepStack: .always )) - }, openDisabledPeer: { _, _ in + }, openDisabledPeer: { _, _, _ in }, openRecentPeerOptions: { _ in }, openMessage: { [weak self] peer, threadId, messageId, deactivateOnAction in guard let self else { diff --git a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift index a45060cb6e..29bb255230 100644 --- a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift +++ b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionController.swift @@ -24,7 +24,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon private let forumPeerId: EnginePeer.Id? private let selectForumThreads: Bool - private let attemptSelection: ((EnginePeer, Int64?) -> Void)? + private let attemptSelection: ((EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void)? private let createNewGroup: (() -> Void)? public var inProgress: Bool = false { @@ -289,9 +289,9 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon } } - self.peerSelectionNode.requestOpenDisabledPeer = { [weak self] peer, threadId in + self.peerSelectionNode.requestOpenDisabledPeer = { [weak self] peer, threadId, reason in if let strongSelf = self { - strongSelf.attemptSelection?(peer, threadId) + strongSelf.attemptSelection?(peer, threadId, reason) } } diff --git a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift index 9a1809fd95..d082f509c0 100644 --- a/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift @@ -80,7 +80,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { var requestActivateSearch: (() -> Void)? var requestDeactivateSearch: (() -> Void)? var requestOpenPeer: ((EnginePeer, Int64?) -> Void)? - var requestOpenDisabledPeer: ((EnginePeer, Int64?) -> Void)? + var requestOpenDisabledPeer: ((EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void)? var requestOpenPeerFromSearch: ((EnginePeer, Int64?) -> Void)? var requestOpenMessageFromSearch: ((EnginePeer, Int64?, EngineMessage.Id) -> Void)? var requestSend: (([EnginePeer], [EnginePeer.Id: EnginePeer], NSAttributedString, AttachmentTextInputPanelSendMode, ChatInterfaceForwardOptionsState?) -> Void)? @@ -250,8 +250,8 @@ final class PeerSelectionControllerNode: ASDisplayNode { self?.requestOpenPeer?(peer, threadId) } - self.chatListNode?.disabledPeerSelected = { [weak self] peer, threadId in - self?.requestOpenDisabledPeer?(peer, threadId) + self.chatListNode?.disabledPeerSelected = { [weak self] peer, threadId, reason in + self?.requestOpenDisabledPeer?(peer, threadId, reason) } self.chatListNode?.contentOffsetChanged = { [weak self] offset in @@ -727,6 +727,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { }, addDoNotTranslateLanguage: { _ in }, hideTranslationPanel: { }, openPremiumGift: { + }, openPremiumRequiredForMessaging: { }, updateHistoryFilter: { _ in }, requestLayout: { _ in }, chatController: { @@ -1177,8 +1178,8 @@ final class PeerSelectionControllerNode: ASDisplayNode { requestOpenPeerFromSearch(peer, threadId) } }, - openDisabledPeer: { [weak self] peer, threadId in - self?.requestOpenDisabledPeer?(peer, threadId) + openDisabledPeer: { [weak self] peer, threadId, reason in + self?.requestOpenDisabledPeer?(peer, threadId, reason) }, openRecentPeerOptions: { _ in }, @@ -1268,6 +1269,11 @@ final class PeerSelectionControllerNode: ASDisplayNode { } } } + }, openDisabledPeer: { [weak self] peer, reason in + guard let self else { + return + } + self.requestOpenDisabledPeer?(peer, nil, reason) }, contextAction: nil), cancel: { [weak self] in if let requestDeactivateSearch = self?.requestDeactivateSearch { requestDeactivateSearch() @@ -1339,7 +1345,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { self.controller?.containerLayoutUpdated(layout, transition: .immediate) } } else { - let contactListNode = ContactListNode(context: self.context, updatedPresentationData: self.updatedPresentationData, presentation: .single(.natural(options: [], includeChatList: false, topPeers: false))) + let contactListNode = ContactListNode(context: self.context, updatedPresentationData: self.updatedPresentationData, presentation: .single(.natural(options: [], includeChatList: false, topPeers: false)), onlyWriteable: self.filter.contains(.onlyWriteable)) self.contactListNode = contactListNode contactListNode.enableUpdates = true contactListNode.selectionStateUpdated = { [weak self] selectionState in @@ -1356,6 +1362,12 @@ final class PeerSelectionControllerNode: ASDisplayNode { self?.requestOpenPeer?(EnginePeer(peer), nil) } } + contactListNode.openDisabledPeer = { [weak self] peer, reason in + guard let self else { + return + } + self.requestOpenDisabledPeer?(peer, nil, reason) + } contactListNode.suppressPermissionWarning = { [weak self] in if let strongSelf = self { strongSelf.context.sharedContext.presentContactsWarningSuppression(context: strongSelf.context, present: { c, a in diff --git a/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift b/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift index 14166f5041..40ab1301ea 100644 --- a/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift +++ b/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift @@ -860,7 +860,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) { var items: [ChatListItem] = [] - let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in + let interaction = ChatListNodeInteraction(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in }, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in gesture?.cancel() @@ -936,7 +936,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate forumTopicData: nil, topForumTopicItems: [], autoremoveTimeout: nil, - storyState: nil + storyState: nil, + requiresPremiumForMessaging: false )), editing: false, hasActiveRevealControls: false, diff --git a/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift b/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift index 2d2654d7a6..ef463ef0f3 100644 --- a/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift +++ b/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift @@ -87,6 +87,7 @@ private final class ShareControllerAccountContextExtension: ShareControllerAccou let accountId: AccountRecordId let accountPeerId: EnginePeer.Id let stateManager: AccountStateManager + let engineData: TelegramEngine.EngineData let animationCache: AnimationCache let animationRenderer: MultiAnimationRenderer let contentSettings: ContentSettings @@ -101,6 +102,7 @@ private final class ShareControllerAccountContextExtension: ShareControllerAccou self.accountId = accountId self.accountPeerId = stateManager.accountPeerId self.stateManager = stateManager + self.engineData = TelegramEngine.EngineData(accountPeerId: stateManager.accountPeerId, postbox: stateManager.postbox) let cacheStorageBox = stateManager.postbox.mediaBox.cacheStorageBox self.animationCache = AnimationCacheImpl(basePath: stateManager.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { return TempBox.shared.tempFile(fileName: "file").path @@ -463,7 +465,7 @@ public class ShareRootControllerImpl { |> mapToSignal { data -> Signal<(ShareControllerEnvironment, ShareControllerAccountContext, PostboxAccessChallengeData, [ShareControllerSwitchableAccount]), ShareAuthorizationError> in let (environment, context, otherAccounts) = data - let limitsConfigurationAndContentSettings = TelegramEngine.EngineData(postbox: context.stateManager.postbox).get( + let limitsConfigurationAndContentSettings = TelegramEngine.EngineData(accountPeerId: context.stateManager.accountPeerId, postbox: context.stateManager.postbox).get( TelegramEngine.EngineData.Item.Configuration.Limits(), TelegramEngine.EngineData.Item.Configuration.ContentSettings(), TelegramEngine.EngineData.Item.Configuration.App() @@ -891,7 +893,7 @@ private func attemptChatImport( var attemptSelectionImpl: ((EnginePeer) -> Void)? var createNewGroupImpl: (() -> Void)? - let controller = PeerSelectionControllerImpl(PeerSelectionControllerParams(context: context, filter: [.onlyGroups, .onlyManageable, .excludeDisabled, .doNotSearchMessages], hasContactSelector: false, hasGlobalSearch: false, title: presentationData.strings.ChatImport_Title, attemptSelection: { peer, _ in + let controller = PeerSelectionControllerImpl(PeerSelectionControllerParams(context: context, filter: [.onlyGroups, .onlyManageable, .excludeDisabled, .doNotSearchMessages], hasContactSelector: false, hasGlobalSearch: false, title: presentationData.strings.ChatImport_Title, attemptSelection: { peer, _, _ in attemptSelectionImpl?(peer) }, createNewGroup: { createNewGroupImpl?() @@ -1058,7 +1060,7 @@ private func attemptChatImport( navigationController.viewControllers = [controller] case let .privateChat(title): var attemptSelectionImpl: ((EnginePeer) -> Void)? - let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyPrivateChats, .excludeDisabled, .doNotSearchMessages, .excludeSecretChats], hasChatListSelector: false, hasContactSelector: true, hasGlobalSearch: false, title: presentationData.strings.ChatImport_Title, attemptSelection: { peer, _ in + let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.onlyPrivateChats, .excludeDisabled, .doNotSearchMessages, .excludeSecretChats], hasChatListSelector: false, hasContactSelector: true, hasGlobalSearch: false, title: presentationData.strings.ChatImport_Title, attemptSelection: { peer, _, _ in attemptSelectionImpl?(peer) }, pretendPresentedInModal: true, selectForumThreads: true)) @@ -1131,7 +1133,7 @@ private func attemptChatImport( case let .unknown(peerTitle): var attemptSelectionImpl: ((EnginePeer) -> Void)? var createNewGroupImpl: (() -> Void)? - let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.excludeDisabled, .doNotSearchMessages], hasContactSelector: true, hasGlobalSearch: false, title: presentationData.strings.ChatImport_Title, attemptSelection: { peer, _ in + let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, filter: [.excludeDisabled, .doNotSearchMessages], hasContactSelector: true, hasGlobalSearch: false, title: presentationData.strings.ChatImport_Title, attemptSelection: { peer, _, _ in attemptSelectionImpl?(peer) }, createNewGroup: { createNewGroupImpl?() diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift index 5acf908a08..e1964e5fd1 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift @@ -50,6 +50,8 @@ public final class StoryContentContextImpl: StoryContentContext { self.currentFocusedId = initialFocusedId self.currentFocusedIdUpdatedPromise.set(.single(Void())) + context.engine.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: [peerId]) + var inputKeys: [PostboxViewKey] = [ PostboxViewKey.basicPeer(peerId), PostboxViewKey.cachedPeerData(peerId: peerId), @@ -63,10 +65,13 @@ public final class StoryContentContextImpl: StoryContentContext { context.account.postbox.combinedView( keys: inputKeys ), - context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()) + context.engine.data.subscribe( + TelegramEngine.EngineData.Item.NotificationSettings.Global(), + TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging(id: peerId) + ) ) - |> mapToSignal { _, views, globalNotificationSettings -> Signal<(CombinedView, [PeerId: Peer], EngineGlobalNotificationSettings, [MediaId: TelegramMediaFile], [Int64: EngineStoryItem.ForwardInfo], [StoryId: EngineStoryItem?]), NoError> in - return context.account.postbox.transaction { transaction -> (CombinedView, [PeerId: Peer], EngineGlobalNotificationSettings, [MediaId: TelegramMediaFile], [Int64: EngineStoryItem.ForwardInfo], [StoryId: EngineStoryItem?]) in + |> mapToSignal { _, views, data -> Signal<(CombinedView, [PeerId: Peer], (EngineGlobalNotificationSettings, Bool), [MediaId: TelegramMediaFile], [Int64: EngineStoryItem.ForwardInfo], [StoryId: EngineStoryItem?]), NoError> in + return context.account.postbox.transaction { transaction -> (CombinedView, [PeerId: Peer], (EngineGlobalNotificationSettings, Bool), [MediaId: TelegramMediaFile], [Int64: EngineStoryItem.ForwardInfo], [StoryId: EngineStoryItem?]) in var peers: [PeerId: Peer] = [:] var forwardInfoStories: [StoryId: EngineStoryItem?] = [:] var allEntityFiles: [MediaId: TelegramMediaFile] = [:] @@ -131,10 +136,10 @@ public final class StoryContentContextImpl: StoryContentContext { } } - return (views, peers, globalNotificationSettings, allEntityFiles, pendingForwardsInfo, forwardInfoStories) + return (views, peers, data, allEntityFiles, pendingForwardsInfo, forwardInfoStories) } } - |> deliverOnMainQueue).startStrict(next: { [weak self] views, peers, globalNotificationSettings, allEntityFiles, pendingForwardsInfo, forwardInfoStories in + |> deliverOnMainQueue).startStrict(next: { [weak self] views, peers, data, allEntityFiles, pendingForwardsInfo, forwardInfoStories in guard let self else { return } @@ -156,6 +161,8 @@ public final class StoryContentContextImpl: StoryContentContext { peerPresence = presencesView.presences[peerId] } + let (globalNotificationSettings, isPremiumRequiredForMessaging) = data + for (storyId, story) in forwardInfoStories { let promise: Promise var added = false @@ -185,21 +192,24 @@ public final class StoryContentContextImpl: StoryContentContext { isMuted: isMuted, areVoiceMessagesAvailable: cachedUserData.voiceMessagesAvailable, presence: peerPresence.flatMap { EnginePeer.Presence($0) }, - canViewStats: false + canViewStats: false, + isPremiumRequiredForMessaging: isPremiumRequiredForMessaging ) } else if let cachedChannelData = cachedPeerDataView.cachedPeerData as? CachedChannelData { additionalPeerData = StoryContentContextState.AdditionalPeerData( isMuted: true, areVoiceMessagesAvailable: true, presence: peerPresence.flatMap { EnginePeer.Presence($0) }, - canViewStats: cachedChannelData.flags.contains(.canViewStats) + canViewStats: cachedChannelData.flags.contains(.canViewStats), + isPremiumRequiredForMessaging: isPremiumRequiredForMessaging ) } else { additionalPeerData = StoryContentContextState.AdditionalPeerData( isMuted: true, areVoiceMessagesAvailable: true, presence: peerPresence.flatMap { EnginePeer.Presence($0) }, - canViewStats: false + canViewStats: false, + isPremiumRequiredForMessaging: isPremiumRequiredForMessaging ) } } @@ -208,7 +218,8 @@ public final class StoryContentContextImpl: StoryContentContext { isMuted: true, areVoiceMessagesAvailable: true, presence: peerPresence.flatMap { EnginePeer.Presence($0) }, - canViewStats: false + canViewStats: false, + isPremiumRequiredForMessaging: isPremiumRequiredForMessaging ) } let state = stateView.value?.get(Stories.PeerState.self) @@ -1093,6 +1104,8 @@ public final class SingleStoryContentContextImpl: StoryContentContext { } } + context.engine.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: [storyId.peerId]) + self.storyDisposable = (combineLatest(queue: .mainQueue(), context.engine.data.subscribe( TelegramEngine.EngineData.Item.Peer.Peer(id: storyId.peerId), @@ -1100,7 +1113,8 @@ public final class SingleStoryContentContextImpl: StoryContentContext { TelegramEngine.EngineData.Item.Peer.AreVoiceMessagesAvailable(id: storyId.peerId), TelegramEngine.EngineData.Item.Peer.CanViewStats(id: storyId.peerId), TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: storyId.peerId), - TelegramEngine.EngineData.Item.NotificationSettings.Global() + TelegramEngine.EngineData.Item.NotificationSettings.Global(), + TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging(id: storyId.peerId) ), item |> mapToSignal { item -> Signal<(Stories.StoredItem?, [PeerId: Peer], [MediaId: TelegramMediaFile], [StoryId: EngineStoryItem?]), NoError> in return context.account.postbox.transaction { transaction -> (Stories.StoredItem?, [PeerId: Peer], [MediaId: TelegramMediaFile], [StoryId: EngineStoryItem?]) in @@ -1165,7 +1179,7 @@ public final class SingleStoryContentContextImpl: StoryContentContext { return } - let (peer, presence, areVoiceMessagesAvailable, canViewStats, notificationSettings, globalNotificationSettings) = data + let (peer, presence, areVoiceMessagesAvailable, canViewStats, notificationSettings, globalNotificationSettings, isPremiumRequiredForMessaging) = data let (item, peers, allEntityFiles, forwardInfoStories) = itemAndPeers guard let peer else { @@ -1178,7 +1192,8 @@ public final class SingleStoryContentContextImpl: StoryContentContext { isMuted: isMuted, areVoiceMessagesAvailable: areVoiceMessagesAvailable, presence: presence, - canViewStats: canViewStats + canViewStats: canViewStats, + isPremiumRequiredForMessaging: isPremiumRequiredForMessaging ) for (storyId, story) in forwardInfoStories { @@ -1347,6 +1362,8 @@ public final class PeerStoryListContentContextImpl: StoryContentContext { public init(context: AccountContext, peerId: EnginePeer.Id, listContext: PeerStoryListContext, initialId: Int32?) { self.context = context + context.engine.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: [peerId]) + self.storyDisposable = (combineLatest(queue: .mainQueue(), context.engine.data.subscribe( TelegramEngine.EngineData.Item.Peer.Peer(id: peerId), @@ -1354,7 +1371,8 @@ public final class PeerStoryListContentContextImpl: StoryContentContext { TelegramEngine.EngineData.Item.Peer.AreVoiceMessagesAvailable(id: peerId), TelegramEngine.EngineData.Item.Peer.CanViewStats(id: peerId), TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: peerId), - TelegramEngine.EngineData.Item.NotificationSettings.Global() + TelegramEngine.EngineData.Item.NotificationSettings.Global(), + TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging(id: peerId) ), listContext.state, self.focusedIdUpdated.get() @@ -1364,7 +1382,7 @@ public final class PeerStoryListContentContextImpl: StoryContentContext { return } - let (peer, presence, areVoiceMessagesAvailable, canViewStats, notificationSettings, globalNotificationSettings) = data + let (peer, presence, areVoiceMessagesAvailable, canViewStats, notificationSettings, globalNotificationSettings, isPremiumRequiredForMessaging) = data guard let peer else { return @@ -1376,7 +1394,8 @@ public final class PeerStoryListContentContextImpl: StoryContentContext { isMuted: isMuted, areVoiceMessagesAvailable: areVoiceMessagesAvailable, presence: presence, - canViewStats: canViewStats + canViewStats: canViewStats, + isPremiumRequiredForMessaging: isPremiumRequiredForMessaging ) self.listState = state @@ -2123,6 +2142,8 @@ public final class RepostStoriesContentContextImpl: StoryContentContext { self.currentFocusedId = initialFocusedId self.currentFocusedIdUpdatedPromise.set(.single(Void())) + context.engine.account.viewTracker.refreshCanSendMessagesForPeerIds(peerIds: [peerId]) + let originalStoryId = StoryId(peerId: originalPeerId, id: originalStory.id) let inputKeys: [PostboxViewKey] = [ @@ -2135,10 +2156,13 @@ public final class RepostStoriesContentContextImpl: StoryContentContext { context.account.postbox.combinedView( keys: inputKeys ), - context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()) + context.engine.data.subscribe( + TelegramEngine.EngineData.Item.NotificationSettings.Global(), + TelegramEngine.EngineData.Item.Peer.IsPremiumRequiredForMessaging(id: peerId) + ) ) - |> mapToSignal { _, views, globalNotificationSettings -> Signal<(CombinedView, [PeerId: Peer], EngineGlobalNotificationSettings, [MediaId: TelegramMediaFile], [StoryId: EngineStoryItem?]), NoError> in - return context.account.postbox.transaction { transaction -> (CombinedView, [PeerId: Peer], EngineGlobalNotificationSettings, [MediaId: TelegramMediaFile], [StoryId: EngineStoryItem?]) in + |> mapToSignal { _, views, data -> Signal<(CombinedView, [PeerId: Peer], (EngineGlobalNotificationSettings, Bool), [MediaId: TelegramMediaFile], [StoryId: EngineStoryItem?]), NoError> in + return context.account.postbox.transaction { transaction -> (CombinedView, [PeerId: Peer], (EngineGlobalNotificationSettings, Bool), [MediaId: TelegramMediaFile], [StoryId: EngineStoryItem?]) in var peers: [PeerId: Peer] = [:] var forwardInfoStories: [StoryId: EngineStoryItem?] = [:] var allEntityFiles: [MediaId: TelegramMediaFile] = [:] @@ -2180,10 +2204,10 @@ public final class RepostStoriesContentContextImpl: StoryContentContext { } } - return (views, peers, globalNotificationSettings, allEntityFiles, forwardInfoStories) + return (views, peers, data, allEntityFiles, forwardInfoStories) } } - |> deliverOnMainQueue).startStrict(next: { [weak self] views, peers, globalNotificationSettings, allEntityFiles, forwardInfoStories in + |> deliverOnMainQueue).startStrict(next: { [weak self] views, peers, data, allEntityFiles, forwardInfoStories in guard let self else { return } @@ -2198,6 +2222,9 @@ public final class RepostStoriesContentContextImpl: StoryContentContext { if let presencesView = views.views[PostboxViewKey.peerPresences(peerIds: Set([peerId]))] as? PeerPresencesView { peerPresence = presencesView.presences[peerId] } + + let (globalNotificationSettings, isPremiumRequiredForMessaging) = data + for (storyId, story) in forwardInfoStories { let promise: Promise var added = false @@ -2229,21 +2256,24 @@ public final class RepostStoriesContentContextImpl: StoryContentContext { isMuted: isMuted, areVoiceMessagesAvailable: cachedUserData.voiceMessagesAvailable, presence: peerPresence.flatMap { EnginePeer.Presence($0) }, - canViewStats: false + canViewStats: false, + isPremiumRequiredForMessaging: isPremiumRequiredForMessaging ) } else if let cachedChannelData = cachedPeerDataView.cachedPeerData as? CachedChannelData { additionalPeerData = StoryContentContextState.AdditionalPeerData( isMuted: true, areVoiceMessagesAvailable: true, presence: peerPresence.flatMap { EnginePeer.Presence($0) }, - canViewStats: cachedChannelData.flags.contains(.canViewStats) + canViewStats: cachedChannelData.flags.contains(.canViewStats), + isPremiumRequiredForMessaging: isPremiumRequiredForMessaging ) } else { additionalPeerData = StoryContentContextState.AdditionalPeerData( isMuted: true, areVoiceMessagesAvailable: true, presence: peerPresence.flatMap { EnginePeer.Presence($0) }, - canViewStats: false + canViewStats: false, + isPremiumRequiredForMessaging: isPremiumRequiredForMessaging ) } } @@ -2252,7 +2282,8 @@ public final class RepostStoriesContentContextImpl: StoryContentContext { isMuted: true, areVoiceMessagesAvailable: true, presence: peerPresence.flatMap { EnginePeer.Presence($0) }, - canViewStats: false + canViewStats: false, + isPremiumRequiredForMessaging: isPremiumRequiredForMessaging ) } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContent.swift index 0202af58cf..860d7ace4f 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContent.swift @@ -141,17 +141,20 @@ public final class StoryContentContextState { public let areVoiceMessagesAvailable: Bool public let presence: EnginePeer.Presence? public let canViewStats: Bool + public let isPremiumRequiredForMessaging: Bool public init( isMuted: Bool, areVoiceMessagesAvailable: Bool, presence: EnginePeer.Presence?, - canViewStats: Bool + canViewStats: Bool, + isPremiumRequiredForMessaging: Bool ) { self.isMuted = isMuted self.areVoiceMessagesAvailable = areVoiceMessagesAvailable self.presence = presence self.canViewStats = canViewStats + self.isPremiumRequiredForMessaging = isPremiumRequiredForMessaging } public static func == (lhs: StoryContentContextState.AdditionalPeerData, rhs: StoryContentContextState.AdditionalPeerData) -> Bool { @@ -167,6 +170,9 @@ public final class StoryContentContextState { if lhs.canViewStats != rhs.canViewStats { return false } + if lhs.isPremiumRequiredForMessaging != rhs.isPremiumRequiredForMessaging { + return false + } return true } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 29e003b52c..ed12f3b56c 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -2737,12 +2737,17 @@ public final class StoryItemSetContainerComponent: Component { } var isUnsupported = false - var disabledPlaceholder: String? - if component.slice.peer.isService { - disabledPlaceholder = component.strings.Story_FooterReplyUnavailable + var disabledPlaceholder: MessageInputPanelComponent.DisabledPlaceholder? + if component.slice.additionalPeerData.isPremiumRequiredForMessaging { + //TODO:localize + disabledPlaceholder = .premiumRequired(title: "Only Premium users can message \(component.slice.peer.compactDisplayTitle).", subtitle: "Learn more...", action: { [weak self] in + self?.presentPremiumRequiredForMessaging() + }) + } else if component.slice.peer.isService { + disabledPlaceholder = .text(component.strings.Story_FooterReplyUnavailable) } else if case .unsupported = component.slice.item.storyItem.media { isUnsupported = true - disabledPlaceholder = component.strings.Story_FooterReplyUnavailable + disabledPlaceholder = .text(component.strings.Story_FooterReplyUnavailable) } let inputPlaceholder: MessageInputPanelComponent.Placeholder @@ -5616,6 +5621,28 @@ public final class StoryItemSetContainerComponent: Component { }) } + private func presentPremiumRequiredForMessaging() { + guard let component = self.component else { + return + } + + let controller = PremiumIntroScreen(context: component.context, source: .settings, forceDark: true) + self.sendMessageContext.actionSheet = controller + controller.wasDismissed = { [weak self, weak controller]in + guard let self else { + return + } + + if self.sendMessageContext.actionSheet === controller { + self.sendMessageContext.actionSheet = nil + } + self.updateIsProgressPaused() + } + + self.updateIsProgressPaused() + component.controller()?.push(controller) + } + private func presentStoriesUpgradeScreen(source: PremiumSource) { guard let component = self.component else { return diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/Contents.json index 38f0c81fc2..6e965652df 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/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/Empty Chat/PremiumRequiredIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/PremiumRequiredIcon.imageset/Contents.json new file mode 100644 index 0000000000..a2cead8511 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/PremiumRequiredIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "premiumlockedchat.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/PremiumRequiredIcon.imageset/premiumlockedchat.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/PremiumRequiredIcon.imageset/premiumlockedchat.pdf new file mode 100644 index 0000000000..56f0ca020c --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/PremiumRequiredIcon.imageset/premiumlockedchat.pdf @@ -0,0 +1,188 @@ +%PDF-1.7 + +1 0 obj + << /Type /XObject + /Length 2 0 R + /Group << /Type /Group + /S /Transparency + >> + /Subtype /Form + /Resources << >> + /BBox [ 0.000000 0.000000 120.000000 120.000000 ] + >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 26.666748 23.947998 cm +0.000000 0.000000 0.000000 scn +33.333332 67.118652 m +51.742825 67.118652 66.666664 53.551525 66.666664 36.815620 c +66.666664 20.079723 51.742825 6.512592 33.333332 6.512592 c +30.510870 6.512592 27.770340 6.831497 25.152962 7.431835 c +24.657856 7.545395 24.095694 7.026123 23.157236 6.159271 c +22.022297 5.110928 20.337004 3.554222 17.554379 1.993690 c +13.999221 -0.000084 9.073529 0.172890 8.239902 0.522552 c +7.440670 0.857796 8.055842 1.524185 9.139198 2.697731 c +9.888692 3.509621 10.862268 4.564251 11.746614 5.919903 c +13.909238 9.235085 13.015616 13.181854 12.045396 13.892178 c +4.458577 19.446659 0.000000 27.270615 0.000000 36.815620 c +0.000000 53.551525 14.923841 67.118652 33.333332 67.118652 c +h +25.627058 49.241592 m +26.466211 54.000668 31.004473 57.178391 35.763550 56.339237 c +40.522621 55.500084 43.700348 50.961823 42.861195 46.202747 c +41.652504 39.347935 l +42.190289 39.251141 42.644272 39.108437 43.057198 38.898041 c +44.186165 38.322800 45.104050 37.404915 45.679291 36.275944 c +46.333252 34.992474 46.333252 33.312317 46.333252 29.952000 c +46.333252 28.152000 l +46.333252 24.791687 46.333252 23.111526 45.679291 21.828056 c +45.104050 20.699085 44.186165 19.781200 43.057198 19.205959 c +41.773727 18.552002 40.093567 18.552002 36.733253 18.552002 c +29.933254 18.552002 l +26.572937 18.552002 24.892780 18.552002 23.609308 19.205959 c +22.480337 19.781200 21.562452 20.699085 20.987213 21.828056 c +20.333252 23.111526 20.333252 24.791687 20.333252 28.152000 c +20.333252 29.952000 l +20.333252 33.312317 20.333252 34.992474 20.987213 36.275944 c +21.562452 37.404915 22.480337 38.322800 23.609308 38.898041 c +24.892780 39.552002 26.572937 39.552002 29.933252 39.552002 c +36.733253 39.552002 l +37.045204 39.552002 37.342670 39.552002 37.626686 39.551476 c +38.921963 46.897339 l +39.377502 49.480839 37.652451 51.944466 35.068954 52.400005 c +32.485458 52.855545 30.021830 51.130497 29.566288 48.546997 c +29.436054 47.808395 l +29.244247 46.720604 28.206930 45.994267 27.119141 46.186073 c +26.031353 46.377880 25.305016 47.415199 25.496822 48.502983 c +25.627058 49.241592 l +h +f* +n +Q + +endstream +endobj + +2 0 obj + 2182 +endobj + +3 0 obj + << /Type /XObject + /Length 4 0 R + /Group << /Type /Group + /S /Transparency + >> + /Subtype /Form + /Resources << >> + /BBox [ 0.000000 0.000000 120.000000 120.000000 ] + >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 10.000000 9.000000 cm +0.000000 0.000000 0.000000 scn +0.000000 62.666668 m +0.000000 75.734558 0.000000 82.268509 2.543181 87.259781 c +4.780226 91.650230 8.349772 95.219772 12.740221 97.456818 c +17.731495 100.000000 24.265440 100.000000 37.333332 100.000000 c +62.666668 100.000000 l +75.734558 100.000000 82.268509 100.000000 87.259781 97.456818 c +91.650230 95.219772 95.219772 91.650230 97.456818 87.259781 c +100.000000 82.268509 100.000000 75.734558 100.000000 62.666668 c +100.000000 37.333332 l +100.000000 24.265442 100.000000 17.731491 97.456818 12.740219 c +95.219772 8.349770 91.650230 4.780228 87.259781 2.543182 c +82.268509 0.000000 75.734558 0.000000 62.666668 0.000000 c +37.333332 0.000000 l +24.265440 0.000000 17.731495 0.000000 12.740221 2.543182 c +8.349772 4.780228 4.780226 8.349770 2.543181 12.740219 c +0.000000 17.731491 0.000000 24.265442 0.000000 37.333332 c +0.000000 62.666668 l +h +f +n +Q + +endstream +endobj + +4 0 obj + 969 +endobj + +5 0 obj + << /XObject << /X1 1 0 R >> + /ExtGState << /E1 << /SMask << /Type /Mask + /G 3 0 R + /S /Alpha + >> + /Type /ExtGState + >> >> + >> +endobj + +6 0 obj + << /Length 7 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +/E1 gs +/X1 Do +Q + +endstream +endobj + +7 0 obj + 46 +endobj + +8 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 120.000000 120.000000 ] + /Resources 5 0 R + /Contents 6 0 R + /Parent 9 0 R + >> +endobj + +9 0 obj + << /Kids [ 8 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +10 0 obj + << /Pages 9 0 R + /Type /Catalog + >> +endobj + +xref +0 11 +0000000000 65535 f +0000000010 00000 n +0000002442 00000 n +0000002465 00000 n +0000003684 00000 n +0000003706 00000 n +0000004004 00000 n +0000004106 00000 n +0000004127 00000 n +0000004302 00000 n +0000004376 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 10 0 R + /Size 11 +>> +startxref +4436 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift b/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift index 12bfa12d89..28072667a9 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatMessageActionOptions.swift @@ -17,6 +17,8 @@ import ChatMessageItemView import ChatMessageBubbleItemNode import TelegramNotices import ChatMessageWebpageBubbleContentNode +import PremiumUI +import UndoUI private enum OptionsId: Hashable { case reply @@ -545,27 +547,49 @@ func moveReplyMessageToAnotherChat(selfController: ChatControllerImpl, replySubj return } let filter: ChatListNodePeersFilter = [.onlyWriteable, .includeSavedMessages, .excludeDisabled, .doNotSearchMessages] - var attemptSelectionImpl: ((EnginePeer) -> Void)? + var attemptSelectionImpl: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? let controller = selfController.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams( context: selfController.context, updatedPresentationData: selfController.updatedPresentationData, filter: filter, hasFilters: true, title: selfController.presentationData.strings.Conversation_MoveReplyToAnotherChatTitle, - attemptSelection: { peer, _ in - attemptSelectionImpl?(peer) + attemptSelection: { peer, _, reason in + attemptSelectionImpl?(peer, reason) }, multipleSelection: false, forwardedMessageIds: [], selectForumThreads: true )) let context = selfController.context - attemptSelectionImpl = { [weak selfController, weak controller] peer in + attemptSelectionImpl = { [weak selfController, weak controller] peer, reason in guard let selfController, let controller = controller else { return } let presentationData = context.sharedContext.currentPresentationData.with { $0 } - controller.present(textAlertController(context: context, updatedPresentationData: selfController.updatedPresentationData, title: nil, text: presentationData.strings.Forward_ErrorDisabledForChat, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + switch reason { + case .generic: + controller.present(textAlertController(context: context, updatedPresentationData: selfController.updatedPresentationData, title: nil, text: presentationData.strings.Forward_ErrorDisabledForChat, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + case .premiumRequired: + //TODO:localize + controller.forEachController { c in + if let c = c as? UndoOverlayController { + c.dismiss() + } + return true + } + controller.present(UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: nil, text: "**\(peer.compactDisplayTitle)** only accepts messages from contacts and **Premium** users.", customUndoText: "View", timeout: nil, linkAction: { _ in + }), elevatedLayout: false, animateInAsReplacement: true, action: { [weak selfController, weak controller] action in + guard let selfController, let controller else { + return false + } + if case .undo = action { + let premiumController = PremiumIntroScreen(context: selfController.context, source: .settings) + controller.push(premiumController) + } + return false + }), in: .current) + } } controller.peerSelected = { [weak selfController, weak controller] peer, threadId in guard let selfController, let strongController = controller else { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index d8e572ea92..828c796674 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -2257,6 +2257,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } let shareController = ShareController(context: strongSelf.context, subject: .messages(messages), updatedPresentationData: strongSelf.updatedPresentationData, shareAsLink: true) + shareController.parentNavigationController = strongSelf.navigationController as? NavigationController + if let message = messages.first, message.media.contains(where: { media in if media is TelegramMediaContact || media is TelegramMediaPoll { return true @@ -5168,6 +5170,27 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G threadInfo = .single(nil) } + let hasSearchTags: Signal + if case let .peer(peerId) = self.chatLocation, peerId == context.account.peerId { + hasSearchTags = context.engine.data.subscribe( + TelegramEngine.EngineData.Item.Messages.SavedMessageTagStats(peerId: context.account.peerId) + ) + |> map { tags -> Bool in + return !tags.isEmpty + } + |> distinctUntilChanged + } else { + hasSearchTags = .single(false) + } + + let isPremiumRequiredForMessaging: Signal + if let peerId = self.chatLocation.peerId { + isPremiumRequiredForMessaging = context.engine.peers.subscribeIsPremiumRequiredForMessaging(id: peerId) + |> distinctUntilChanged + } else { + isPremiumRequiredForMessaging = .single(false) + } + self.peerDisposable.set(combineLatest( queue: Queue.mainQueue(), peerView.get(), @@ -5176,8 +5199,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G hasScheduledMessages, self.reportIrrelvantGeoNoticePromise.get(), displayedCountSignal, - threadInfo - ).startStrict(next: { [weak self] peerView, globalNotificationSettings, onlineMemberCount, hasScheduledMessages, peerReportNotice, pinnedCount, threadInfo in + threadInfo, + hasSearchTags, + isPremiumRequiredForMessaging + ).startStrict(next: { [weak self] peerView, globalNotificationSettings, onlineMemberCount, hasScheduledMessages, peerReportNotice, pinnedCount, threadInfo, hasSearchTags, isPremiumRequiredForMessaging in if let strongSelf = self { if strongSelf.peerView === peerView && strongSelf.reportIrrelvantGeoNotice == peerReportNotice && strongSelf.hasScheduledMessages == hasScheduledMessages && strongSelf.threadInfo == threadInfo { return @@ -5441,6 +5466,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G .updatedAutoremoveTimeout(autoremoveTimeout) .updatedCurrentSendAsPeerId(currentSendAsPeerId) .updatedCopyProtectionEnabled(copyProtectionEnabled) + .updatedHasSearchTags(hasSearchTags) + .updatedIsPremiumRequiredForMessaging(isPremiumRequiredForMessaging) .updatedInterfaceState { interfaceState in var interfaceState = interfaceState @@ -5689,15 +5716,38 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G onlineMemberCount = recentOnlineSignal } + let hasSearchTags: Signal + if case let .peer(peerId) = self.chatLocation, peerId == context.account.peerId { + hasSearchTags = context.engine.data.subscribe( + TelegramEngine.EngineData.Item.Messages.SavedMessageTagStats(peerId: context.account.peerId) + ) + |> map { tags -> Bool in + return !tags.isEmpty + } + |> distinctUntilChanged + } else { + hasSearchTags = .single(false) + } + + let isPremiumRequiredForMessaging: Signal + if let peerId = self.chatLocation.peerId { + isPremiumRequiredForMessaging = context.engine.peers.subscribeIsPremiumRequiredForMessaging(id: peerId) + |> distinctUntilChanged + } else { + isPremiumRequiredForMessaging = .single(false) + } + self.titleDisposable.set(nil) self.peerDisposable.set((combineLatest(queue: Queue.mainQueue(), peerView, messageAndTopic, savedMessagesPeer, onlineMemberCount, - hasScheduledMessages + hasScheduledMessages, + hasSearchTags, + isPremiumRequiredForMessaging ) - |> deliverOnMainQueue).startStrict(next: { [weak self] peerView, messageAndTopic, savedMessagesPeer, onlineMemberCount, hasScheduledMessages in + |> deliverOnMainQueue).startStrict(next: { [weak self] peerView, messageAndTopic, savedMessagesPeer, onlineMemberCount, hasScheduledMessages, hasSearchTags, isPremiumRequiredForMessaging in if let strongSelf = self { strongSelf.hasScheduledMessages = hasScheduledMessages @@ -5965,6 +6015,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return renderedPeer }.updatedIsNotAccessible(isNotAccessible).updatedContactStatus(contactStatus).updatedHasBots(hasBots).updatedIsArchived(isArchived).updatedPeerIsMuted(peerIsMuted).updatedPeerDiscussionId(peerDiscussionId).updatedPeerGeoLocation(peerGeoLocation).updatedExplicitelyCanPinMessages(explicitelyCanPinMessages).updatedHasScheduledMessages(hasScheduledMessages).updatedCurrentSendAsPeerId(currentSendAsPeerId) .updatedCopyProtectionEnabled(copyProtectionEnabled) + .updatedHasSearchTags(hasSearchTags) + .updatedIsPremiumRequiredForMessaging(isPremiumRequiredForMessaging) .updatedInterfaceState { interfaceState in var interfaceState = interfaceState @@ -10825,6 +10877,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G Queue.mainQueue().after(0.5) { let _ = ApplicationSpecificNotice.incrementDismissedPremiumGiftSuggestion(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peerId).startStandalone() } + }, openPremiumRequiredForMessaging: { [weak self] in + guard let self else { + return + } + let controller = PremiumIntroScreen(context: self.context, source: .settings) + self.push(controller) }, updateHistoryFilter: { [weak self] update in guard let self else { return diff --git a/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift b/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift index d75c8f0ca8..582747f748 100644 --- a/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift +++ b/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift @@ -10,6 +10,7 @@ import PresentationDataUtils import TextFormat import UndoUI import ChatInterfaceState +import PremiumUI extension ChatControllerImpl { func forwardMessages(messageIds: [MessageId], options: ChatInterfaceForwardOptionsState? = nil, resetCurrent: Bool = false) { @@ -41,12 +42,12 @@ extension ChatControllerImpl { } } } - var attemptSelectionImpl: ((EnginePeer) -> Void)? - let controller = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, updatedPresentationData: self.updatedPresentationData, filter: filter, hasFilters: true, attemptSelection: { peer, _ in - attemptSelectionImpl?(peer) + var attemptSelectionImpl: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? + let controller = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, updatedPresentationData: self.updatedPresentationData, filter: filter, hasFilters: true, attemptSelection: { peer, _, reason in + attemptSelectionImpl?(peer, reason) }, multipleSelection: true, forwardedMessageIds: messages.map { $0.id }, selectForumThreads: true)) let context = self.context - attemptSelectionImpl = { [weak self, weak controller] peer in + attemptSelectionImpl = { [weak self, weak controller] peer, reason in guard let strongSelf = self, let controller = controller else { return } @@ -57,7 +58,29 @@ extension ChatControllerImpl { return } } - controller.present(textAlertController(context: context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: presentationData.strings.Forward_ErrorDisabledForChat, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + switch reason { + case .generic: + controller.present(textAlertController(context: context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: presentationData.strings.Forward_ErrorDisabledForChat, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + case .premiumRequired: + //TODO:localize + controller.forEachController { c in + if let c = c as? UndoOverlayController { + c.dismiss() + } + return true + } + controller.present(UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: nil, text: "**\(peer.compactDisplayTitle)** only accepts messages from contacts and **Premium** users.", customUndoText: "View", timeout: nil, linkAction: { _ in + }), elevatedLayout: false, animateInAsReplacement: true, action: { [weak controller] action in + guard let self, let controller else { + return false + } + if case .undo = action { + let premiumController = PremiumIntroScreen(context: self.context, source: .settings) + controller.push(premiumController) + } + return false + }), in: .current) + } } controller.multiplePeersSelected = { [weak self, weak controller] peers, peerMap, messageText, mode, forwardOptions in guard let strongSelf = self, let strongController = controller else { diff --git a/submodules/TelegramUI/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Sources/ChatEmptyNode.swift index f511b9dafa..9cb2ab150e 100644 --- a/submodules/TelegramUI/Sources/ChatEmptyNode.swift +++ b/submodules/TelegramUI/Sources/ChatEmptyNode.swift @@ -15,6 +15,10 @@ import WallpaperBackgroundNode import ComponentFlow import EmojiStatusComponent import ChatLoadingNode +import MultilineTextComponent +import BalancedTextComponent +import Markdown +import ReactionSelectionNode private protocol ChatEmptyNodeContent { func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize @@ -893,6 +897,167 @@ final class ChatEmptyNodeTopicChatContent: ASDisplayNode, ChatEmptyNodeContent, } } +final class ChatEmptyNodePremiumRequiredChatContent: ASDisplayNode, ChatEmptyNodeContent { + private let interaction: ChatPanelInterfaceInteraction? + + private let iconBackground: SimpleLayer + private let icon: UIImageView + private let text = ComponentView() + private let buttonTitle = ComponentView() + private let button: HighlightTrackingButton + private let buttonStarsNode: PremiumStarsNode + + private var currentTheme: PresentationTheme? + private var currentStrings: PresentationStrings? + + init(interaction: ChatPanelInterfaceInteraction?) { + self.interaction = interaction + + self.iconBackground = SimpleLayer() + self.icon = UIImageView(image: UIImage(bundleImageName: "Chat/Empty Chat/PremiumRequiredIcon")?.withRenderingMode(.alwaysTemplate)) + + self.button = HighlightTrackingButton() + self.button.clipsToBounds = true + + self.buttonStarsNode = PremiumStarsNode() + self.buttonStarsNode.isUserInteractionEnabled = false + + super.init() + + self.layer.addSublayer(self.iconBackground) + self.view.addSubview(self.icon) + + self.view.addSubview(self.button) + + self.button.addSubnode(self.buttonStarsNode) + + self.button.highligthedChanged = { [weak self] highlighted in + guard let self else { + return + } + if highlighted { + self.button.layer.removeAnimation(forKey: "opacity") + self.button.alpha = 0.6 + } else { + self.button.alpha = 1.0 + self.button.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + self.button.addTarget(self, action: #selector(self.buttonPressed), for: .touchUpInside) + } + + @objc private func buttonPressed() { + if let interaction = self.interaction { + interaction.openPremiumRequiredForMessaging() + } + } + + func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { + let serviceColor = serviceMessageColorComponents(theme: interfaceState.theme, wallpaper: interfaceState.chatWallpaper) + /*if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings { + self.currentTheme = interfaceState.theme + self.currentStrings = interfaceState.strings + + self.titleNode.attributedText = NSAttributedString(string: interfaceState.strings.Chat_EmptyTopicPlaceholder_Title, font: titleFont, textColor: serviceColor.primaryText) + self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Chat_EmptyTopicPlaceholder_Text, font: messageFont, textColor: serviceColor.primaryText) + }*/ + + let maxWidth = min(200.0, size.width) + + let sideInset: CGFloat = 22.0 + let topInset: CGFloat = 16.0 + let bottomInset: CGFloat = 16.0 + let iconBackgroundSize: CGFloat = 120.0 + let iconTextSpacing: CGFloat = 16.0 + let textButtonSpacing: CGFloat = 12.0 + + let peerTitle: String + if let peer = interfaceState.renderedPeer?.chatMainPeer { + peerTitle = EnginePeer(peer).compactDisplayTitle + } else { + peerTitle = " " + } + + //TODO:localize + let text = "Subscribe to **Premium**\nto message **\(peerTitle)**." + let textSize = self.text.update( + transition: .immediate, + component: AnyComponent(BalancedTextComponent( + text: .markdown(text: text, attributes: MarkdownAttributes( + body: MarkdownAttributeSet(font: Font.regular(15.0), textColor: serviceColor.primaryText), + bold: MarkdownAttributeSet(font: Font.semibold(15.0), textColor: serviceColor.primaryText), + link: MarkdownAttributeSet(font: Font.regular(15.0), textColor: serviceColor.primaryText), + linkAttribute: { url in + return ("URL", url) + } + )), + horizontalAlignment: .center, + maximumNumberOfLines: 0 + )), + environment: {}, + containerSize: CGSize(width: maxWidth - sideInset * 2.0, height: 500.0) + ) + + //TODO:localize + let buttonTitleSize = self.buttonTitle.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: "Add Premium", font: Font.semibold(15.0), textColor: serviceColor.primaryText)) + )), + environment: {}, + containerSize: CGSize(width: 200.0, height: 100.0) + ) + let buttonSize = CGSize(width: buttonTitleSize.width + 20.0 * 2.0, height: buttonTitleSize.height + 9.0 * 2.0) + + var contentsWidth: CGFloat = 0.0 + contentsWidth = max(contentsWidth, iconBackgroundSize + sideInset * 2.0) + contentsWidth = max(contentsWidth, textSize.width + sideInset * 2.0) + contentsWidth = max(contentsWidth, buttonSize.width + sideInset * 2.0) + + var contentsHeight: CGFloat = 0.0 + contentsHeight += topInset + + let iconBackgroundFrame = CGRect(origin: CGPoint(x: floor((contentsWidth - iconBackgroundSize) * 0.5), y: contentsHeight), size: CGSize(width: iconBackgroundSize, height: iconBackgroundSize)) + transition.updateFrame(layer: self.iconBackground, frame: iconBackgroundFrame) + transition.updateCornerRadius(layer: self.iconBackground, cornerRadius: iconBackgroundSize * 0.5) + self.iconBackground.backgroundColor = (interfaceState.theme.overallDarkAppearance ? UIColor(rgb: 0xffffff, alpha: 0.12) : UIColor(rgb: 0x000000, alpha: 0.12)).cgColor + contentsHeight += iconBackgroundSize + contentsHeight += iconTextSpacing + + self.icon.tintColor = serviceColor.primaryText + if let image = self.icon.image { + transition.updateFrame(view: self.icon, frame: CGRect(origin: CGPoint(x: iconBackgroundFrame.minX + floor((iconBackgroundFrame.width - image.size.width) * 0.5), y: iconBackgroundFrame.minY + floor((iconBackgroundFrame.height - image.size.height) * 0.5)), size: image.size)) + } + + let textFrame = CGRect(origin: CGPoint(x: floor((contentsWidth - textSize.width) * 0.5), y: contentsHeight), size: textSize) + if let textView = self.text.view { + if textView.superview == nil { + textView.isUserInteractionEnabled = false + self.view.addSubview(textView) + } + textView.frame = textFrame + } + contentsHeight += textSize.height + contentsHeight += textButtonSpacing + + let buttonFrame = CGRect(origin: CGPoint(x: floor((contentsWidth - buttonSize.width) * 0.5), y: contentsHeight), size: buttonSize) + transition.updateFrame(view: self.button, frame: buttonFrame) + transition.updateCornerRadius(layer: self.button.layer, cornerRadius: buttonFrame.height * 0.5) + if let buttonTitleView = self.buttonTitle.view { + if buttonTitleView.superview == nil { + buttonTitleView.isUserInteractionEnabled = false + self.button.addSubview(buttonTitleView) + } + transition.updateFrame(view: buttonTitleView, frame: CGRect(origin: CGPoint(x: floor((buttonSize.width - buttonTitleSize.width) * 0.5), y: floor((buttonSize.height - buttonTitleSize.height) * 0.5)), size: buttonTitleSize)) + } + self.button.backgroundColor = interfaceState.theme.overallDarkAppearance ? UIColor(rgb: 0xffffff, alpha: 0.12) : UIColor(rgb: 0x000000, alpha: 0.12) + self.buttonStarsNode.frame = CGRect(origin: CGPoint(), size: buttonSize) + contentsHeight += buttonSize.height + contentsHeight += bottomInset + + return CGSize(width: contentsWidth, height: contentsHeight) + } +} private enum ChatEmptyNodeContentType: Equatable { case regular @@ -902,6 +1067,7 @@ private enum ChatEmptyNodeContentType: Equatable { case peerNearby case greeting case topic + case premiumRequired } final class ChatEmptyNode: ASDisplayNode { @@ -937,6 +1103,13 @@ final class ChatEmptyNode: ASDisplayNode { self.addSubnode(self.backgroundNode) } + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + guard let result = super.hitTest(point, with: event) else { + return nil + } + return result + } + func animateFromLoadingNode(_ loadingNode: ChatLoadingNode) { guard let (_, node) = content else { return @@ -1000,12 +1173,16 @@ final class ChatEmptyNode: ASDisplayNode { } else if let _ = interfaceState.peerNearbyData { contentType = .peerNearby } else if let peer = peer as? TelegramUser { - if peer.isDeleted || peer.botInfo != nil || peer.flags.contains(.isSupport) || peer.isScam || interfaceState.peerIsBlocked { - contentType = .regular - } else if case .clearedHistory = emptyType { - contentType = .regular + if interfaceState.isPremiumRequiredForMessaging { + contentType = .premiumRequired } else { - contentType = .greeting + if peer.isDeleted || peer.botInfo != nil || peer.flags.contains(.isSupport) || peer.isScam || interfaceState.peerIsBlocked { + contentType = .regular + } else if case .clearedHistory = emptyType { + contentType = .regular + } else { + contentType = .greeting + } } } else { contentType = .regular @@ -1027,21 +1204,23 @@ final class ChatEmptyNode: ASDisplayNode { } let node: ASDisplayNode & ChatEmptyNodeContent switch contentType { - case .regular: - node = ChatEmptyNodeRegularChatContent() - case .secret: - node = ChatEmptyNodeSecretChatContent() - case .group: - node = ChatEmptyNodeGroupChatContent() - case .cloud: - node = ChatEmptyNodeCloudChatContent() - case .peerNearby: - node = ChatEmptyNodeNearbyChatContent(context: self.context, interaction: self.interaction) - case .greeting: - node = ChatEmptyNodeGreetingChatContent(context: self.context, interaction: self.interaction) - updateGreetingSticker = true - case .topic: - node = ChatEmptyNodeTopicChatContent(context: self.context) + case .regular: + node = ChatEmptyNodeRegularChatContent() + case .secret: + node = ChatEmptyNodeSecretChatContent() + case .group: + node = ChatEmptyNodeGroupChatContent() + case .cloud: + node = ChatEmptyNodeCloudChatContent() + case .peerNearby: + node = ChatEmptyNodeNearbyChatContent(context: self.context, interaction: self.interaction) + case .greeting: + node = ChatEmptyNodeGreetingChatContent(context: self.context, interaction: self.interaction) + updateGreetingSticker = true + case .topic: + node = ChatEmptyNodeTopicChatContent(context: self.context) + case .premiumRequired: + node = ChatEmptyNodePremiumRequiredChatContent(interaction: self.interaction) } self.content = (contentType, node) self.addSubnode(node) @@ -1052,7 +1231,7 @@ final class ChatEmptyNode: ASDisplayNode { node.layer.animateScale(from: 0.0, to: 1.0, duration: duration, timingFunction: curve.timingFunction) } } - self.isUserInteractionEnabled = [.peerNearby, .greeting].contains(contentType) + self.isUserInteractionEnabled = [.peerNearby, .greeting, .premiumRequired].contains(contentType) let displayRect = CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: size.width, height: size.height - insets.top - insets.bottom)) diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index 8ce9a34d2d..ccd7802233 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -1626,13 +1626,6 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto let previous = previousValueAndVersion?.0 let previousSelectedMessages = previousValueAndVersion?.2 - if let previous { - print("view entries: \(view.entries.count), previous: \(previous.originalView.entries.count)") - if previous.originalView.entries.count >= 44 && view.entries.count == 1 { - assert(true) - } - } - if let previousVersion = previousValueAndVersion?.1 { assert(update.1 >= previousVersion) } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift index f4c6e77b41..f19abefb67 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift @@ -106,6 +106,18 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState } } + if chatPresentationInterfaceState.isPremiumRequiredForMessaging { + if let currentPanel = (currentPanel as? ChatPremiumRequiredInputPanelNode) ?? (currentSecondaryPanel as? ChatPremiumRequiredInputPanelNode) { + currentPanel.interfaceInteraction = interfaceInteraction + return (currentPanel, nil) + } else { + let panel = ChatPremiumRequiredInputPanelNode(theme: chatPresentationInterfaceState.theme) + panel.context = context + panel.interfaceInteraction = interfaceInteraction + return (panel, nil) + } + } + if chatPresentationInterfaceState.peerIsBlocked, let peer = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramUser, peer.botInfo == nil { if let currentPanel = (currentPanel as? ChatUnblockInputPanelNode) ?? (currentSecondaryPanel as? ChatUnblockInputPanelNode) { currentPanel.interfaceInteraction = interfaceInteraction diff --git a/submodules/TelegramUI/Sources/ChatPremiumRequiredInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatPremiumRequiredInputPanelNode.swift new file mode 100644 index 0000000000..16121e3d7d --- /dev/null +++ b/submodules/TelegramUI/Sources/ChatPremiumRequiredInputPanelNode.swift @@ -0,0 +1,142 @@ +import Foundation +import UIKit +import AsyncDisplayKit +import Display +import TelegramCore +import Postbox +import SwiftSignalKit +import TelegramNotices +import TelegramPresentationData +import ActivityIndicator +import ChatPresentationInterfaceState +import ChatInputPanelNode +import ComponentFlow +import MultilineTextComponent +import PlainButtonComponent +import ComponentDisplayAdapters + +private let labelFont = Font.regular(15.0) + +final class ChatPremiumRequiredInputPanelNode: ChatInputPanelNode { + private struct Params: Equatable { + var width: CGFloat + var leftInset: CGFloat + var rightInset: CGFloat + var bottomInset: CGFloat + var additionalSideInsets: UIEdgeInsets + var maxHeight: CGFloat + var isSecondary: Bool + var interfaceState: ChatPresentationInterfaceState + var metrics: LayoutMetrics + var isMediaInputExpanded: Bool + + init(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) { + self.width = width + self.leftInset = leftInset + self.rightInset = rightInset + self.bottomInset = bottomInset + self.additionalSideInsets = additionalSideInsets + self.maxHeight = maxHeight + self.isSecondary = isSecondary + self.interfaceState = interfaceState + self.metrics = metrics + self.isMediaInputExpanded = isMediaInputExpanded + } + } + + private struct Layout { + var params: Params + var height: CGFloat + + init(params: Params, height: CGFloat) { + self.params = params + self.height = height + } + } + + private let button = ComponentView() + + private var params: Params? + private var currentLayout: Layout? + + override var interfaceInteraction: ChatPanelInterfaceInteraction? { + didSet { + } + } + + init(theme: PresentationTheme) { + super.init() + } + + deinit { + } + + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { + let params = Params(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, interfaceState: interfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) + if let currentLayout = self.currentLayout, currentLayout.params == params { + return currentLayout.height + } + + let height = self.update(params: params, transition: Transition(transition)) + self.currentLayout = Layout(params: params, height: height) + + return height + } + + private func update(params: Params, transition: Transition) -> CGFloat { + let height: CGFloat + if case .regular = params.metrics.widthClass { + height = 49.0 + } else { + height = 45.0 + } + + let peerTitle: String + if let peer = params.interfaceState.renderedPeer?.chatMainPeer { + peerTitle = EnginePeer(peer).compactDisplayTitle + } else { + peerTitle = " " + } + + //TODO:localize + let buttonTitle: String = "Only Premium users can message \(peerTitle)." + let buttonSubtitle: String = "Learn more..." + + let size = CGSize(width: params.width - params.additionalSideInsets.left * 2.0 - params.leftInset * 2.0, height: height) + let buttonSize = self.button.update( + transition: .immediate, + component: AnyComponent(PlainButtonComponent( + content: AnyComponent(VStack([ + AnyComponentWithIdentity(id: 0, component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: buttonTitle, font: Font.regular(13.0), textColor: params.interfaceState.theme.rootController.navigationBar.secondaryTextColor)) + ))), + AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: buttonSubtitle, font: Font.regular(13.0), textColor: params.interfaceState.theme.rootController.navigationBar.accentTextColor)) + ))) + ], spacing: 1.0)), + effectAlignment: .center, + minSize: size, + action: { [weak self] in + guard let self else { + return + } + self.interfaceInteraction?.openPremiumRequiredForMessaging() + } + )), + environment: {}, + containerSize: size + ) + if let buttonView = self.button.view { + if buttonView.superview == nil { + self.view.addSubview(buttonView) + } + transition.setFrame(view: buttonView, frame: CGRect(origin: CGPoint(), size: buttonSize)) + } + + return height + } + + override func minimalHeight(interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + return defaultHeight(metrics: metrics) + } +} diff --git a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift index 74117ec7f3..69b0505429 100644 --- a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift @@ -103,7 +103,8 @@ private enum ChatListSearchEntry: Comparable, Identifiable { forumTopicData: nil, topForumTopicItems: [], autoremoveTimeout: nil, - storyState: nil + storyState: nil, + requiresPremiumForMessaging: false )), editing: false, hasActiveRevealControls: false, @@ -219,7 +220,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe let interaction = ChatListNodeInteraction(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: { }, peerSelected: { _, _, _, _ in - }, disabledPeerSelected: { _, _ in + }, disabledPeerSelected: { _, _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in diff --git a/submodules/TelegramUI/Sources/ComposeController.swift b/submodules/TelegramUI/Sources/ComposeController.swift index 871f7f855d..881560b309 100644 --- a/submodules/TelegramUI/Sources/ComposeController.swift +++ b/submodules/TelegramUI/Sources/ComposeController.swift @@ -124,7 +124,7 @@ public class ComposeControllerImpl: ViewController, ComposeController { self.contactsNode.openCreateNewGroup = { [weak self] in if let strongSelf = self { - let controller = strongSelf.context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: strongSelf.context, mode: .groupCreation, options: [])) + let controller = strongSelf.context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: strongSelf.context, mode: .groupCreation, options: [], onlyWriteable: true)) (strongSelf.navigationController as? NavigationController)?.pushViewController(controller, completion: { [weak self] in if let strongSelf = self { strongSelf.contactsNode.contactListNode.listNode.clearHighlightAnimated(true) diff --git a/submodules/TelegramUI/Sources/ComposeControllerNode.swift b/submodules/TelegramUI/Sources/ComposeControllerNode.swift index 897ad34313..9213c2fd39 100644 --- a/submodules/TelegramUI/Sources/ComposeControllerNode.swift +++ b/submodules/TelegramUI/Sources/ComposeControllerNode.swift @@ -23,6 +23,7 @@ final class ComposeControllerNode: ASDisplayNode { var requestDeactivateSearch: (() -> Void)? var requestOpenPeerFromSearch: ((PeerId) -> Void)? + var requestOpenDisabledPeerFromSearch: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? var openCreateNewGroup: (() -> Void)? var openCreateNewSecretChat: (() -> Void)? @@ -51,7 +52,7 @@ final class ComposeControllerNode: ASDisplayNode { ContactListAdditionalOption(title: self.presentationData.strings.Compose_NewChannel, icon: .generic(UIImage(bundleImageName: "Contact List/CreateChannelActionIcon")!), action: { openCreateNewChannelImpl?() }) - ], includeChatList: false, topPeers: false)), displayPermissionPlaceholder: false) + ], includeChatList: false, topPeers: false)), onlyWriteable: false, displayPermissionPlaceholder: false) super.init() @@ -123,6 +124,11 @@ final class ComposeControllerNode: ASDisplayNode { if let requestOpenPeerFromSearch = self?.requestOpenPeerFromSearch, case let .peer(peer, _, _) = peer { requestOpenPeerFromSearch(peer.id) } + }, openDisabledPeer: { [weak self] peer, reason in + guard let self else { + return + } + self.requestOpenDisabledPeerFromSearch?(peer, reason) }, contextAction: nil), cancel: { [weak self] in self?.requestDeactivateSearch?() }) diff --git a/submodules/TelegramUI/Sources/ContactMultiselectionController.swift b/submodules/TelegramUI/Sources/ContactMultiselectionController.swift index d89f9bb1a6..c4fb5ae77a 100644 --- a/submodules/TelegramUI/Sources/ContactMultiselectionController.swift +++ b/submodules/TelegramUI/Sources/ContactMultiselectionController.swift @@ -14,6 +14,8 @@ import PresentationDataUtils import ContactListUI import CounterContollerTitleView import EditableTokenListNode +import PremiumUI +import UndoUI private func peerTokenTitle(accountPeerId: PeerId, peer: Peer, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder) -> String { if peer.id == accountPeerId { @@ -30,7 +32,7 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection private let context: AccountContext private let mode: ContactMultiselectionControllerMode private let isPeerEnabled: ((EnginePeer) -> Bool)? - private let attemptDisabledItemSelection: ((EnginePeer) -> Void)? + private let attemptDisabledItemSelection: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? private let titleView: CounterContollerTitleView @@ -80,6 +82,7 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection private var initialPeersDisposable: Disposable? private let options: [ContactListAdditionalOption] private let filters: [ContactListFilter] + private let onlyWriteable: Bool private let limit: Int32? init(_ params: ContactMultiselectionControllerParams) { @@ -90,6 +93,7 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection self.attemptDisabledItemSelection = params.attemptDisabledItemSelection self.options = params.options self.filters = params.filters + self.onlyWriteable = params.onlyWriteable self.limit = params.limit self.presentationData = params.updatedPresentationData?.initial ?? params.context.sharedContext.currentPresentationData.with { $0 } @@ -239,7 +243,7 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection } override func loadDisplayNode() { - self.displayNode = ContactMultiselectionControllerNode(navigationBar: self.navigationBar, context: self.context, presentationData: self.presentationData, mode: self.mode, isPeerEnabled: self.isPeerEnabled, attemptDisabledItemSelection: self.attemptDisabledItemSelection, options: self.options, filters: self.filters, limit: self.limit, reachedSelectionLimit: self.params.reachedLimit) + self.displayNode = ContactMultiselectionControllerNode(navigationBar: self.navigationBar, context: self.context, presentationData: self.presentationData, mode: self.mode, isPeerEnabled: self.isPeerEnabled, attemptDisabledItemSelection: self.attemptDisabledItemSelection, options: self.options, filters: self.filters, onlyWriteable: self.onlyWriteable, limit: self.limit, reachedSelectionLimit: self.params.reachedLimit) switch self.contactsNode.contentNode { case let .contacts(contactsNode): self._listReady.set(contactsNode.ready) @@ -366,6 +370,35 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection } } + self.contactsNode.openDisabledPeer = { [weak self] peer, reason in + guard let self else { + return + } + switch reason { + case .generic: + break + case .premiumRequired: + //TODO:localize + self.forEachController { c in + if let c = c as? UndoOverlayController { + c.dismiss() + } + return true + } + self.present(UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: nil, text: "**\(peer.compactDisplayTitle)** only accepts messages from contacts and **Premium** users.", customUndoText: "View", timeout: nil, linkAction: { _ in + }), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] action in + guard let self else { + return false + } + if case .undo = action { + let premiumController = PremiumIntroScreen(context: self.context, source: .settings) + self.push(premiumController) + } + return false + }), in: .current) + } + } + self.contactsNode.removeSelectedPeer = { [weak self] peerId in if let strongSelf = self { var updatedCount: Int? diff --git a/submodules/TelegramUI/Sources/ContactMultiselectionControllerNode.swift b/submodules/TelegramUI/Sources/ContactMultiselectionControllerNode.swift index e09805422f..a26be36efb 100644 --- a/submodules/TelegramUI/Sources/ContactMultiselectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/ContactMultiselectionControllerNode.swift @@ -58,6 +58,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode { var requestDeactivateSearch: (() -> Void)? var requestOpenPeerFromSearch: ((ContactListPeerId) -> Void)? var openPeer: ((ContactListPeer) -> Void)? + var openDisabledPeer: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? var removeSelectedPeer: ((ContactListPeerId) -> Void)? var removeSelectedCategory: ((Int) -> Void)? var additionalCategorySelected: ((Int) -> Void)? @@ -76,8 +77,9 @@ final class ContactMultiselectionControllerNode: ASDisplayNode { private let footerPanelNode: FooterPanelNode? private let isPeerEnabled: ((EnginePeer) -> Bool)? + private let onlyWriteable: Bool - init(navigationBar: NavigationBar?, context: AccountContext, presentationData: PresentationData, mode: ContactMultiselectionControllerMode, isPeerEnabled: ((EnginePeer) -> Bool)?, attemptDisabledItemSelection: ((EnginePeer) -> Void)?, options: [ContactListAdditionalOption], filters: [ContactListFilter], limit: Int32?, reachedSelectionLimit: ((Int32) -> Void)?) { + init(navigationBar: NavigationBar?, context: AccountContext, presentationData: PresentationData, mode: ContactMultiselectionControllerMode, isPeerEnabled: ((EnginePeer) -> Bool)?, attemptDisabledItemSelection: ((EnginePeer, ChatListDisabledPeerReason) -> Void)?, options: [ContactListAdditionalOption], filters: [ContactListFilter], onlyWriteable: Bool, limit: Int32?, reachedSelectionLimit: ((Int32) -> Void)?) { self.navigationBar = navigationBar self.context = context @@ -87,6 +89,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode { self.animationRenderer = context.animationRenderer self.isPeerEnabled = isPeerEnabled + self.onlyWriteable = onlyWriteable var proceedImpl: (() -> Void)? @@ -127,8 +130,8 @@ final class ContactMultiselectionControllerNode: ASDisplayNode { placeholder = placeholderValue let chatListNode = ChatListNode(context: context, location: .chatList(groupId: .root), previewing: false, fillPreloadItems: false, mode: .peers(filter: [.excludeSecretChats], isSelecting: true, additionalCategories: additionalCategories?.categories ?? [], chatListFilters: chatListFilters, displayAutoremoveTimeout: chatSelection.displayAutoremoveTimeout, displayPresence: chatSelection.displayPresence), isPeerEnabled: isPeerEnabled, theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, animationCache: self.animationCache, animationRenderer: self.animationRenderer, disableAnimations: true, isInlineMode: false, autoSetReady: true, isMainTab: false) chatListNode.passthroughPeerSelection = true - chatListNode.disabledPeerSelected = { peer, _ in - attemptDisabledItemSelection?(peer) + chatListNode.disabledPeerSelected = { peer, _, reason in + attemptDisabledItemSelection?(peer, reason) } if let limit = limit { chatListNode.selectionLimit = limit @@ -157,7 +160,8 @@ final class ContactMultiselectionControllerNode: ASDisplayNode { } else if case .requestedUsersSelection = mode { displayTopPeers = true } - self.contentNode = .contacts(ContactListNode(context: context, presentation: .single(.natural(options: options, includeChatList: includeChatList, topPeers: displayTopPeers)), filters: filters, selectionState: ContactListNodeGroupSelectionState())) + let contactListNode = ContactListNode(context: context, presentation: .single(.natural(options: options, includeChatList: includeChatList, topPeers: displayTopPeers)), filters: filters, onlyWriteable: onlyWriteable, selectionState: ContactListNodeGroupSelectionState()) + self.contentNode = .contacts(contactListNode) } self.tokenListNode = EditableTokenListNode(context: self.context, presentationTheme: self.presentationData.theme, theme: EditableTokenListNodeTheme(backgroundColor: .clear, separatorColor: self.presentationData.theme.rootController.navigationBar.separatorColor, placeholderTextColor: self.presentationData.theme.list.itemPlaceholderTextColor, primaryTextColor: self.presentationData.theme.list.itemPrimaryTextColor, tokenBackgroundColor: self.presentationData.theme.list.itemCheckColors.strokeColor.withAlphaComponent(0.25), selectedTextColor: self.presentationData.theme.list.itemCheckColors.foregroundColor, selectedBackgroundColor: self.presentationData.theme.list.itemCheckColors.fillColor, accentColor: self.presentationData.theme.list.itemAccentColor, keyboardColor: self.presentationData.theme.rootController.keyboardColor), placeholder: placeholder, shortPlaceholder: shortPlaceholder) @@ -178,6 +182,12 @@ final class ContactMultiselectionControllerNode: ASDisplayNode { contactsNode.openPeer = { [weak self] peer, _ in self?.openPeer?(peer) } + contactsNode.openDisabledPeer = { [weak self] peer, reason in + guard let self else { + return + } + self.openDisabledPeer?(peer, reason) + } case let .chats(chatsNode): chatsNode.peerSelected = { [weak self] peer, _, _, _, _ in self?.openPeer?(.peer(peer: peer._asPeer(), isGlobal: false, participantCount: nil)) @@ -243,11 +253,17 @@ final class ContactMultiselectionControllerNode: ASDisplayNode { case .premiumGifting, .requestedUsersSelection: searchChatList = true } - let searchResultsNode = ContactListNode(context: context, presentation: .single(.search(signal: searchText.get(), searchChatList: searchChatList, searchDeviceContacts: false, searchGroups: searchGroups, searchChannels: searchChannels, globalSearch: globalSearch)), filters: filters, isPeerEnabled: strongSelf.isPeerEnabled, selectionState: selectionState, isSearch: true) + let searchResultsNode = ContactListNode(context: context, presentation: .single(.search(signal: searchText.get(), searchChatList: searchChatList, searchDeviceContacts: false, searchGroups: searchGroups, searchChannels: searchChannels, globalSearch: globalSearch)), filters: filters, onlyWriteable: strongSelf.onlyWriteable, isPeerEnabled: strongSelf.isPeerEnabled, selectionState: selectionState, isSearch: true) searchResultsNode.openPeer = { peer, _ in self?.tokenListNode.setText("") self?.openPeer?(peer) } + searchResultsNode.openDisabledPeer = { peer, reason in + guard let self else { + return + } + self.openDisabledPeer?(peer, reason) + } strongSelf.searchResultsNode = searchResultsNode searchResultsNode.enableUpdates = true searchResultsNode.backgroundColor = strongSelf.presentationData.theme.chatList.backgroundColor diff --git a/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift b/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift index 762797102a..99084f28bd 100644 --- a/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift @@ -37,6 +37,7 @@ final class ContactSelectionControllerNode: ASDisplayNode { var requestDeactivateSearch: (() -> Void)? var requestOpenPeerFromSearch: ((ContactListPeer) -> Void)? + var requestOpenDisabledPeerFromSearch: ((EnginePeer, ChatListDisabledPeerReason) -> Void)? var requestMultipleAction: ((_ silent: Bool, _ scheduleTime: Int32?) -> Void)? var dismiss: (() -> Void)? var cancelSearch: (() -> Void)? @@ -67,7 +68,7 @@ final class ContactSelectionControllerNode: ASDisplayNode { self.filters = filters var contextActionImpl: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? - self.contactListNode = ContactListNode(context: context, updatedPresentationData: (presentationData, self.presentationDataPromise.get()), presentation: .single(.natural(options: options, includeChatList: false, topPeers: false)), filters: filters, displayCallIcons: displayCallIcons, contextAction: multipleSelection ? { peer, node, gesture, _, _ in + self.contactListNode = ContactListNode(context: context, updatedPresentationData: (presentationData, self.presentationDataPromise.get()), presentation: .single(.natural(options: options, includeChatList: false, topPeers: false)), filters: filters, onlyWriteable: false, displayCallIcons: displayCallIcons, contextAction: multipleSelection ? { peer, node, gesture, _, _ in contextActionImpl?(peer, node, gesture, nil) } : nil, multipleSelection: multipleSelection) @@ -223,6 +224,11 @@ final class ContactSelectionControllerNode: ASDisplayNode { strongSelf.requestOpenPeerFromSearch?(peer) } } + }, openDisabledPeer: { [weak self] peer, reason in + guard let self else { + return + } + self.requestOpenDisabledPeerFromSearch?(peer, reason) }, contextAction: nil) searchContainerNode.cancel = { [weak self] in self?.cancelSearch?() @@ -286,6 +292,11 @@ final class ContactSelectionControllerNode: ASDisplayNode { strongSelf.requestOpenPeerFromSearch?(peer) } } + }, openDisabledPeer: { [weak self] peer, reason in + guard let self else { + return + } + self.requestOpenDisabledPeerFromSearch?(peer, reason) }, contextAction: nil), cancel: { [weak self] in if let requestDeactivateSearch = self?.requestDeactivateSearch { requestDeactivateSearch()