diff --git a/Telegram/SiriIntents/IntentContacts.swift b/Telegram/SiriIntents/IntentContacts.swift index dc338bef52..bc9e10590c 100644 --- a/Telegram/SiriIntents/IntentContacts.swift +++ b/Telegram/SiriIntents/IntentContacts.swift @@ -135,7 +135,7 @@ func personWithUser(stableId: String, user: TelegramUser) -> INPerson { let personHandle: INPersonHandle if let phone = user.phone { personHandle = INPersonHandle(value: formatPhoneNumber(phone), type: .phoneNumber) - } else if let username = user.username { + } else if let username = user.addressName { personHandle = INPersonHandle(value: "@\(username)", type: .unknown) } else { personHandle = INPersonHandle(value: user.nameOrPhone, type: .unknown) diff --git a/Telegram/SiriIntents/IntentHandler.swift b/Telegram/SiriIntents/IntentHandler.swift index 5c718a5324..3f5f964256 100644 --- a/Telegram/SiriIntents/IntentHandler.swift +++ b/Telegram/SiriIntents/IntentHandler.swift @@ -790,7 +790,7 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, useCopy: false, transaction: { postbox, transaction -> INObjectSection in var accountTitle: String = "" if let peer = transaction.getPeer(accountPeerId) as? TelegramUser { - if let username = peer.username, !username.isEmpty { + if let username = peer.addressName, !username.isEmpty { accountTitle = "@\(username)" } else { accountTitle = peer.debugDisplayTitle @@ -963,7 +963,7 @@ private final class WidgetIntentHandler { accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, useCopy: false, transaction: { postbox, transaction -> INObjectSection in var accountTitle: String = "" if let peer = transaction.getPeer(accountPeerId) as? TelegramUser { - if let username = peer.username, !username.isEmpty { + if let username = peer.addressName, !username.isEmpty { accountTitle = "@\(username)" } else { accountTitle = peer.debugDisplayTitle diff --git a/Telegram/SiriIntents/IntentMessages.swift b/Telegram/SiriIntents/IntentMessages.swift index 2e05082bbb..ea4a157f35 100644 --- a/Telegram/SiriIntents/IntentMessages.swift +++ b/Telegram/SiriIntents/IntentMessages.swift @@ -129,7 +129,7 @@ private func callWithTelegramMessage(_ telegramMessage: Message, account: Accoun if #available(iOSApplicationExtension 10.2, iOS 10.2, *) { var type: INPersonHandleType var label: INPersonHandleLabel? - if let username = user.username { + if let username = user.addressName { label = INPersonHandleLabel(rawValue: "@\(username)") type = .unknown } else if let phone = user.phone { @@ -168,7 +168,7 @@ private func messageWithTelegramMessage(_ telegramMessage: Message) -> INMessage if #available(iOSApplicationExtension 10.2, iOS 10.2, *) { var type: INPersonHandleType var label: INPersonHandleLabel? - if let username = user.username { + if let username = user.addressName { label = INPersonHandleLabel(rawValue: "@\(username)") type = .unknown } else if let phone = user.phone { diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index f4cc61e1da..b085a0debc 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -737,7 +737,7 @@ public protocol SharedAccountContext: AnyObject { func makePrivacyAndSecurityController(context: AccountContext) -> ViewController func navigateToChatController(_ params: NavigateToChatControllerParams) func navigateToForumChannel(context: AccountContext, peerId: EnginePeer.Id, navigationController: NavigationController) - func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal + func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal func openStorageUsage(context: AccountContext) func openLocationScreen(context: AccountContext, messageId: MessageId, navigationController: NavigationController) func openExternalUrl(context: AccountContext, urlContext: OpenURLContext, url: String, forceExternal: Bool, presentationData: PresentationData, navigationController: NavigationController?, dismissInput: @escaping () -> Void) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index e2f55a2b0a..1dbc3c9889 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -1362,7 +1362,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController strongSelf.context.sharedContext.navigateToForumChannel(context: strongSelf.context, peerId: channel.id, navigationController: navigationController) } else { if let threadId = threadId { - let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, navigationController: navigationController, activateInput: nil).start() + let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil).start() strongSelf.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true) } else { var navigationAnimationOptions: NavigationAnimationOptions = [] @@ -1462,11 +1462,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController if case .chatList(.root) = strongSelf.location { navigationAnimationOptions = .removeOnMasterDetails } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: actualPeerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil), purposefulAction: { - if deactivateOnAction { - self?.deactivateSearch(animated: false) - } - }, scrollToEndIfExists: scrollToEndIfExists, options: navigationAnimationOptions)) + if let threadId = threadId { + let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: nil).start() + } else { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: actualPeerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil), purposefulAction: { + if deactivateOnAction { + self?.deactivateSearch(animated: false) + } + }, scrollToEndIfExists: scrollToEndIfExists, options: navigationAnimationOptions)) + } strongSelf.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true) } } @@ -1474,7 +1478,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } } - self.chatListDisplayNode.requestOpenPeerFromSearch = { [weak self] peer, dismissSearch in + self.chatListDisplayNode.requestOpenPeerFromSearch = { [weak self] peer, threadId, dismissSearch in if let strongSelf = self { let storedPeer = strongSelf.context.engine.peers.ensurePeerIsLocallyAvailable(peer: peer) |> map { _ -> Void in return Void() } strongSelf.openMessageFromSearchDisposable.set((storedPeer |> deliverOnMainQueue).start(completed: { [weak strongSelf] in @@ -1491,9 +1495,13 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController if case .chatList(.root) = strongSelf.location { navigationAnimationOptions = .removeOnMasterDetails } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), purposefulAction: { [weak self] in - self?.deactivateSearch(animated: false) - }, scrollToEndIfExists: scrollToEndIfExists, options: navigationAnimationOptions)) + if let threadId = threadId { + let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil).start() + } else { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), purposefulAction: { [weak self] in + self?.deactivateSearch(animated: false) + }, scrollToEndIfExists: scrollToEndIfExists, options: navigationAnimationOptions)) + } strongSelf.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true) } } @@ -1584,7 +1592,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController let _ = (context.engine.peers.createForumChannelTopic(id: peerId, title: title, iconColor: availableColors.randomElement()!, iconFileId: fileId) |> deliverOnMainQueue).start(next: { topicId in - let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: topicId, navigationController: navigationController, activateInput: .text).start() + let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: topicId, messageId: nil, navigationController: navigationController, activateInput: .text).start() }) } strongSelf.push(controller) @@ -2591,7 +2599,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController let _ = (context.engine.peers.createForumChannelTopic(id: peerId, title: title, iconColor: availableColors.randomElement()!, iconFileId: fileId) |> deliverOnMainQueue).start(next: { topicId in if let navigationController = (sourceController.navigationController as? NavigationController) { - let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: topicId, navigationController: navigationController, activateInput: .text).start() + let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: topicId, messageId: nil, navigationController: navigationController, activateInput: .text).start() } }) } diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index 423ce1866e..a3cf04b1b8 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -1135,7 +1135,7 @@ final class ChatListControllerNode: ASDisplayNode { private var containerLayout: (ContainerViewLayout, CGFloat, CGFloat, CGFloat)? var requestDeactivateSearch: (() -> Void)? - var requestOpenPeerFromSearch: ((EnginePeer, Bool) -> Void)? + var requestOpenPeerFromSearch: ((EnginePeer, Int64?, Bool) -> Void)? var requestOpenRecentPeerOptions: ((EnginePeer) -> Void)? var requestOpenMessageFromSearch: ((EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void)? var requestAddContact: ((String) -> Void)? @@ -1311,8 +1311,8 @@ final class ChatListControllerNode: ASDisplayNode { let filter: ChatListNodePeersFilter = [] - let contentNode = ChatListSearchContainerNode(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, filter: filter, location: location, displaySearchFilters: displaySearchFilters, hasDownloads: hasDownloads, initialFilter: initialFilter, openPeer: { [weak self] peer, _, dismissSearch in - self?.requestOpenPeerFromSearch?(peer, dismissSearch) + let contentNode = ChatListSearchContainerNode(context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, filter: filter, location: location, displaySearchFilters: displaySearchFilters, hasDownloads: hasDownloads, initialFilter: initialFilter, openPeer: { [weak self] peer, _, threadId, dismissSearch in + self?.requestOpenPeerFromSearch?(peer, threadId, dismissSearch) }, openDisabledPeer: { _ in }, openRecentPeerOptions: { [weak self] peer in self?.requestOpenRecentPeerOptions?(peer) diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 52d075dd4b..a43986f7a3 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -43,7 +43,7 @@ private enum ChatListTokenId: Int32 { } final class ChatListSearchInteraction { - let openPeer: (EnginePeer, EnginePeer?, Bool) -> Void + let openPeer: (EnginePeer, EnginePeer?, Int64?, Bool) -> Void let openDisabledPeer: (EnginePeer) -> Void let openMessage: (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void let openUrl: (String) -> Void @@ -57,7 +57,7 @@ final class ChatListSearchInteraction { let dismissInput: () -> Void let getSelectedMessageIds: () -> Set? - init(openPeer: @escaping (EnginePeer, EnginePeer?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer) -> 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?) { + init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer) -> 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?) { self.openPeer = openPeer self.openDisabledPeer = openDisabledPeer self.openMessage = openMessage @@ -133,7 +133,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo private var validLayout: (ContainerViewLayout, CGFloat)? - public init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, filter: ChatListNodePeersFilter, location: ChatListControllerLocation, displaySearchFilters: Bool, hasDownloads: Bool, initialFilter: ChatListSearchFilter = .chats, openPeer originalOpenPeer: @escaping (EnginePeer, EnginePeer?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer) -> 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?) { + public init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, filter: ChatListNodePeersFilter, location: ChatListControllerLocation, displaySearchFilters: Bool, hasDownloads: Bool, initialFilter: ChatListSearchFilter = .chats, openPeer originalOpenPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer) -> 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?) { self.context = context self.peersFilter = filter self.location = location @@ -159,8 +159,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo self.addSubnode(self.paneContainerNode) - let interaction = ChatListSearchInteraction(openPeer: { peer, chatPeer, value in - originalOpenPeer(peer, chatPeer, value) + let interaction = ChatListSearchInteraction(openPeer: { peer, chatPeer, threadId, value in + originalOpenPeer(peer, chatPeer, threadId, value) if peer.id.namespace != Namespaces.Peer.SecretChat { addAppLogEvent(postbox: context.account.postbox, type: "search_global_open_peer", peerId: peer.id) } diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index b1de3c7377..ee724a71a0 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -463,23 +463,23 @@ public enum ChatListSearchEntry: Comparable, Identifiable { public func item(context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, location: ChatListControllerLocation, key: ChatListSearchPaneKey, tagMask: EngineMessage.Tags?, interaction: ChatListNodeInteraction, listInteraction: ListMessageItemInteraction, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, toggleExpandLocalResults: @escaping () -> Void, toggleExpandGlobalResults: @escaping () -> Void, searchPeer: @escaping (EnginePeer) -> Void, searchQuery: String?, searchOptions: ChatListSearchOptions?, messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void)?, openClearRecentlyDownloaded: @escaping () -> Void, toggleAllPaused: @escaping () -> Void) -> ListViewItem { switch self { - case let .topic(peer, threadInfo, _, theme, strings, expandType): - let actionTitle: String? - switch expandType { - case .none: - actionTitle = nil - case .expand: - actionTitle = strings.ChatList_Search_ShowMore - case .collapse: - actionTitle = strings.ChatList_Search_ShowLess - } - let header = ChatListSearchItemHeader(type: .topics, theme: theme, strings: strings, actionTitle: actionTitle, action: actionTitle == nil ? nil : { - toggleExpandGlobalResults() - }) - - return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: .firstLast, displayOrder: .firstLast, context: context, peerMode: .generalSearch, peer: .thread(peer: peer, title: threadInfo.info.title, icon: threadInfo.info.icon, color: 0), 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, threadInfo.id, nil, nil) - }, contextAction: nil, animationCache: interaction.animationCache, animationRenderer: interaction.animationRenderer) + case let .topic(peer, threadInfo, _, theme, strings, expandType): + let actionTitle: String? + switch expandType { + case .none: + actionTitle = nil + case .expand: + actionTitle = strings.ChatList_Search_ShowMore + case .collapse: + actionTitle = strings.ChatList_Search_ShowLess + } + let header = ChatListSearchItemHeader(type: .topics, theme: theme, strings: strings, actionTitle: actionTitle, action: actionTitle == nil ? nil : { + toggleExpandGlobalResults() + }) + + return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: .firstLast, displayOrder: .firstLast, context: context, peerMode: .generalSearch, peer: .thread(peer: peer, title: threadInfo.info.title, icon: threadInfo.info.icon, color: 0), 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): let primaryPeer: EnginePeer var chatPeer: EnginePeer? @@ -543,7 +543,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch, 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 if case let .peer(maybePeer, maybeChatPeer) = contactPeer, let peer = maybePeer, let chatPeer = maybeChatPeer { - interaction.peerSelected(chatPeer, nil, peer, nil) + interaction.peerSelected(chatPeer, peer, nil, nil) } else { interaction.peerSelected(peer, nil, nil, nil) } @@ -630,7 +630,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch, 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 if case let .peer(maybePeer, maybeChatPeer) = contactPeer, let peer = maybePeer, let chatPeer = maybeChatPeer { - interaction.peerSelected(chatPeer, nil, peer, nil) + interaction.peerSelected(chatPeer, peer, nil, nil) } else { interaction.peerSelected(peer, nil, nil, nil) } @@ -739,10 +739,10 @@ public enum ChatListSearchEntry: Comparable, Identifiable { index = .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index)) case .forum: if let threadId = message.threadId, let threadInfo = threadInfo { - chatThreadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadInfo) - index = .forum(timestamp: message.index.timestamp, threadId: threadId, namespace: message.index.id.namespace, id: message.index.id.id) + chatThreadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadInfo, isOwner: false, isClosed: false) + index = .forum(pinnedIndex: .none, timestamp: message.index.timestamp, threadId: threadId, namespace: message.index.id.namespace, id: message.index.id.id) } else { - index = .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index)) + index = .chatList( EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index)) } } return ChatListItem(presentationData: presentationData, context: context, chatListLocation: .chatList(groupId: .root), filterData: nil, index: index, content: .peer(messages: [message], peer: peer, threadInfo: chatThreadInfo, combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, hasUnseenMentions: false, hasUnseenReactions: false, draftState: nil, inputActivities: nil, promoInfo: nil, ignoreUnreadBadge: true, displayAsMessage: false, hasFailedMessages: false, forumTopicData: nil), editing: false, hasActiveRevealControls: false, selected: false, header: tagMask == nil ? header : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction) @@ -1245,7 +1245,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { if let resourceValue = findMediaResourceById(message: item.message, resourceId: item.resourceId), let size = resourceValue.size { resource = (resourceValue.id.stringRepresentation, size, entries.isEmpty) } - + entries.append(.message(message, peer, nil, nil, presentationData, 1, nil, false, .downloading(item.priority), resource, .downloading, allPaused)) } 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) }) { @@ -1490,17 +1490,17 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } }) - let foundThreads: Signal<([Int64: EngineMessageHistoryThread.Info], [EngineChatList.Item]), NoError> = chatListViewForLocation(chatListLocation: location, location: .initial(count: 1000, filter: nil), account: context.account) - |> map { view -> ([Int64: EngineMessageHistoryThread.Info], [EngineChatList.Item]) in - var itemsMap: [Int64: EngineMessageHistoryThread.Info] = [:] + let foundThreads: Signal<([Int64: MessageHistoryThreadData], [EngineChatList.Item]), NoError> = chatListViewForLocation(chatListLocation: location, location: .initial(count: 1000, filter: nil), account: context.account) + |> map { view -> ([Int64: MessageHistoryThreadData], [EngineChatList.Item]) in + var itemsMap: [Int64: MessageHistoryThreadData] = [:] var filteredItems: [EngineChatList.Item] = [] let queryTokens = stringIndexTokens(finalQuery, transliteration: .combined) for item in view.list.items { - if case let .forum(_, index, _, _) = item.index, let threadInfo = item.threadInfo { - itemsMap[index] = threadInfo + if case let .forum(_, _, index, _, _) = item.index, let threadData = item.threadData { + itemsMap[index] = threadData } if !finalQuery.isEmpty { - if let title = item.threadInfo?.title { + if let title = item.threadData?.info.title { let tokens = stringIndexTokens(title, transliteration: .combined) if matchStringIndexTokens(tokens, with: queryTokens) { filteredItems.append(item) @@ -1508,6 +1508,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } } } + return (itemsMap, filteredItems) } @@ -1518,8 +1519,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { var index = 0 for thread in allAndFoundThreads.1 { - if let peer = thread.renderedPeer.peer, let threadInfo = thread.threadInfo, case let .forum(_, id, _, _) = thread.index { - entries.append(.topic(peer, ChatListItemContent.ThreadInfo(id: id, info: threadInfo), index, presentationData.theme, presentationData.strings, .none)) + if let peer = thread.renderedPeer.peer, let threadData = thread.threadData, case let .forum(_, _, id, _, _) = thread.index { + entries.append(.topic(peer, ChatListItemContent.ThreadInfo(id: id, info: threadData.info, isOwner: threadData.isOwnedByMe, isClosed: threadData.isClosed), index, presentationData.theme, presentationData.strings, .none)) index += 1 } } @@ -1715,7 +1716,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { peer = EngineRenderedPeer(peer: EnginePeer(channelPeer)) } } - entries.append(.message(message, peer, nil, message.threadId.flatMap { allAndFoundThreads.0[$0] }, presentationData, 1, nil, true, .index(message.index), nil, .generic, false)) + entries.append(.message(message, peer, nil, message.threadId.flatMap { allAndFoundThreads.0[$0]?.info }, presentationData, 1, nil, true, .index(message.index), nil, .generic, false)) index += 1 } @@ -1738,7 +1739,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { peer = EngineRenderedPeer(peer: EnginePeer(channelPeer)) } } - entries.append(.message(message, peer, foundRemoteMessages.0.1[message.id.peerId], message.threadId.flatMap { allAndFoundThreads.0[$0] }, presentationData, foundRemoteMessages.0.2, selectionState?.contains(message.id), headerId == firstHeaderId, .index(message.index), nil, .generic, false)) + entries.append(.message(message, peer, foundRemoteMessages.0.1[message.id.peerId], message.threadId.flatMap { allAndFoundThreads.0[$0]?.info }, presentationData, foundRemoteMessages.0.2, selectionState?.contains(message.id), headerId == firstHeaderId, .index(message.index), nil, .generic, false)) index += 1 } } @@ -1810,9 +1811,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } let chatListInteraction = ChatListNodeInteraction(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: { - }, peerSelected: { [weak self] peer, _, chatPeer, _ in + }, peerSelected: { [weak self] peer, chatPeer, threadId, _ in interaction.dismissInput() - interaction.openPeer(peer, chatPeer, false) + interaction.openPeer(peer, chatPeer, threadId, false) let _ = context.engine.peers.addRecentlySearchedPeer(peerId: peer.id).start() self?.listNode.clearHighlightAnimated(true) }, disabledPeerSelected: { _ in @@ -2159,7 +2160,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { let firstTime = previousEntries == nil let transition = chatListSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries, context: context, presentationData: presentationData, filter: peersFilter, peerSelected: { peer in - interaction.openPeer(peer, nil, true) + interaction.openPeer(peer, nil, nil, true) let _ = context.engine.peers.addRecentlySearchedPeer(peerId: peer.id).start() self?.recentListNode.clearHighlightAnimated(true) }, disabledPeerSelected: { peer in diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 2aa25ea676..d6a09eee18 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -56,7 +56,7 @@ public final class ChatListNodeInteraction { } let activateSearch: () -> Void - let peerSelected: (EnginePeer, Int64?, EnginePeer?, ChatListNodeEntryPromoInfo?) -> Void + let peerSelected: (EnginePeer, EnginePeer?, Int64?, ChatListNodeEntryPromoInfo?) -> Void let disabledPeerSelected: (EnginePeer) -> Void let togglePeerSelected: (EnginePeer) -> Void let togglePeersSelection: ([PeerEntry], Bool) -> Void @@ -90,7 +90,7 @@ public final class ChatListNodeInteraction { animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, activateSearch: @escaping () -> Void, - peerSelected: @escaping (EnginePeer, Int64?, EnginePeer?, ChatListNodeEntryPromoInfo?) -> Void, + peerSelected: @escaping (EnginePeer, EnginePeer?, Int64?, ChatListNodeEntryPromoInfo?) -> Void, disabledPeerSelected: @escaping (EnginePeer) -> Void, togglePeerSelected: @escaping (EnginePeer) -> Void, togglePeersSelection: @escaping ([PeerEntry], Bool) -> Void, @@ -795,7 +795,7 @@ public final class ChatListNode: ListView { if let strongSelf = self, let activateSearch = strongSelf.activateSearch { activateSearch() } - }, peerSelected: { [weak self] peer, threadId, _, promoInfo in + }, peerSelected: { [weak self] peer, _, threadId, promoInfo in if let strongSelf = self, let peerSelected = strongSelf.peerSelected { peerSelected(peer, threadId, true, true, promoInfo) } diff --git a/submodules/InstantPageUI/Sources/InstantPagePeerReferenceNode.swift b/submodules/InstantPageUI/Sources/InstantPagePeerReferenceNode.swift index 1fb24ddb06..ab4b3d8caa 100644 --- a/submodules/InstantPageUI/Sources/InstantPagePeerReferenceNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPagePeerReferenceNode.swift @@ -149,7 +149,7 @@ final class InstantPagePeerReferenceNode: ASDisplayNode, InstantPageNode { let context = self.context let signal = actualizedPeer(postbox: account.postbox, network: account.network, peer: initialPeer) |> mapToSignal({ peer -> Signal in - if let peer = peer as? TelegramChannel, let username = peer.username, peer.accessHash == nil { + if let peer = peer as? TelegramChannel, let username = peer.addressName, peer.accessHash == nil { return .single(peer) |> then(context.engine.peers.resolvePeerByName(name: username) |> mapToSignal({ updatedPeer -> Signal in if let updatedPeer = updatedPeer { diff --git a/submodules/InviteLinksUI/Sources/AdditionalLinkItem.swift b/submodules/InviteLinksUI/Sources/AdditionalLinkItem.swift index f86b763b42..f8a02d9b45 100644 --- a/submodules/InviteLinksUI/Sources/AdditionalLinkItem.swift +++ b/submodules/InviteLinksUI/Sources/AdditionalLinkItem.swift @@ -203,7 +203,7 @@ public class AdditionalLinkItemNode: ListViewItemNode, ItemListItemNode { let iconColor: UIColor if let username = item.username { - if username.flags.contains(.isEditable) || username.flags.contains(.isActive) { + if username.isActive { iconColor = item.presentationData.theme.list.itemAccentColor } else { iconColor = UIColor(rgb: 0xa8b2bb) @@ -218,7 +218,7 @@ public class AdditionalLinkItemNode: ListViewItemNode, ItemListItemNode { if let username = item.username { titleText = "@\(username.username)" - if username.flags.contains(.isEditable) || username.flags.contains(.isActive) { + if username.isActive { subtitleText = item.presentationData.strings.Group_Setup_LinkActive subtitleColor = item.presentationData.theme.list.itemAccentColor } else { @@ -388,13 +388,14 @@ public class AdditionalLinkItemNode: ListViewItemNode, ItemListItemNode { strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: contentSize.height + UIScreenPixel + UIScreenPixel)) - if strongSelf.reorderControlNode == nil && item.username?.flags.contains(.isActive) == true { + let isReorderable = item.username?.isActive == true + if isReorderable { let reorderControlNode = reorderControlSizeAndApply.1(layout.contentSize.height, false, .immediate) strongSelf.reorderControlNode = reorderControlNode strongSelf.addSubnode(reorderControlNode) reorderControlNode.alpha = 0.0 transition.updateAlpha(node: reorderControlNode, alpha: 1.0) - } else if let reorderControlNode = strongSelf.reorderControlNode, item.username?.flags.contains(.isActive) == false { + } else if let reorderControlNode = strongSelf.reorderControlNode, item.username?.isActive == false { strongSelf.reorderControlNode = nil reorderControlNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak reorderControlNode] _ in reorderControlNode?.removeFromSupernode() diff --git a/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift b/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift index 2ecd791cfa..4116a457a3 100644 --- a/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift +++ b/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift @@ -406,7 +406,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo if let phone = peer.phone, !phone.isEmpty { statusText += formatPhoneNumber(phone) } - if let username = peer.username, !username.isEmpty { + if let username = peer.addressName, !username.isEmpty { if !statusText.isEmpty { statusText += "\n" } diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index ac0f168c09..4e6b4101df 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -943,14 +943,14 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa } } - let currentAddressName: String + let currentUsername: String if let current = state.editingPublicLinkText { - currentAddressName = current + currentUsername = current } else { - if let addressName = peer.addressName { - currentAddressName = addressName + if let username = peer.editableUsername { + currentUsername = username } else { - currentAddressName = "" + currentUsername = "" } } @@ -1019,7 +1019,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa } else { switch selectedType { case .publicChannel: - entries.append(.editablePublicLink(presentationData.theme, presentationData.strings, presentationData.strings.Group_PublicLink_Placeholder, currentAddressName)) + entries.append(.editablePublicLink(presentationData.theme, presentationData.strings, presentationData.strings.Group_PublicLink_Placeholder, currentUsername)) if let status = state.addressNameValidationStatus { let text: String switch status { @@ -1055,7 +1055,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa case let .availability(availability): switch availability { case .available: - text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentAddressName).string + text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentUsername).string case .invalid: text = presentationData.strings.Channel_Username_InvalidCharacters case .taken: @@ -1208,11 +1208,11 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa selectedType = .privateChannel } - let currentAddressName: String + let currentUsername: String if let current = state.editingPublicLinkText { - currentAddressName = current + currentUsername = current } else { - currentAddressName = "" + currentUsername = "" } entries.append(.typeHeader(presentationData.theme, presentationData.strings.Group_Setup_TypeHeader.uppercased())) @@ -1228,7 +1228,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa switch selectedType { case .publicChannel: - entries.append(.editablePublicLink(presentationData.theme, presentationData.strings, "", currentAddressName)) + entries.append(.editablePublicLink(presentationData.theme, presentationData.strings, "", currentUsername)) if let status = state.addressNameValidationStatus { let text: String switch status { @@ -1248,7 +1248,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa case let .availability(availability): switch availability { case .available: - text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentAddressName).string + text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentUsername).string case .invalid: text = presentationData.strings.Channel_Username_InvalidCharacters case .taken: @@ -1319,38 +1319,38 @@ private func updatedAddressName(mode: ChannelVisibilityControllerMode, state: Ch if let peer = peer as? TelegramChannel { let selectedType = effectiveChannelType(mode: mode, state: state, peer: peer, cachedData: cachedData) - let currentAddressName: String + let currentUsername: String switch selectedType { case .privateChannel: - currentAddressName = "" + currentUsername = "" case .publicChannel: if let current = state.editingPublicLinkText { - currentAddressName = current + currentUsername = current } else { - if let addressName = peer.addressName { - currentAddressName = addressName + if let username = peer.editableUsername { + currentUsername = username } else { - currentAddressName = "" + currentUsername = "" } } } - if !currentAddressName.isEmpty { - if currentAddressName != peer.addressName { - return currentAddressName + if !currentUsername.isEmpty { + if currentUsername != peer.editableUsername { + return currentUsername } else { return nil } - } else if peer.addressName != nil { + } else if peer.editableUsername != nil { return "" } else { return nil } } else if let _ = peer as? TelegramGroup { - let currentAddressName = state.editingPublicLinkText ?? "" - if !currentAddressName.isEmpty { - return currentAddressName + let currentUsername = state.editingPublicLinkText ?? "" + if !currentUsername.isEmpty { + return currentUsername } else { return nil } @@ -2082,7 +2082,7 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta switch entry { case let .additionalLink(_, link, _): currentUsernames.append(link.username) - if !link.flags.contains(.isActive) && maxIndex == nil { + if !link.isActive && maxIndex == nil { maxIndex = max(0, i - 1) } i += 1 @@ -2094,7 +2094,7 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta if toIndex < entries.count { switch entries[toIndex] { case let .additionalLink(_, toUsername, _): - if toUsername.flags.contains(.isActive) { + if toUsername.isActive { referenceId = toUsername.username } else { afterAll = true diff --git a/submodules/SettingsUI/Sources/UsernameSetupController.swift b/submodules/SettingsUI/Sources/UsernameSetupController.swift index 1af5c2a653..f256291c5b 100644 --- a/submodules/SettingsUI/Sources/UsernameSetupController.swift +++ b/submodules/SettingsUI/Sources/UsernameSetupController.swift @@ -230,7 +230,7 @@ private enum UsernameSetupEntry: ItemListNodeEntry { case let .additionalLink(_, link, _): return AdditionalLinkItem(presentationData: presentationData, username: link, sectionId: self.section, style: .blocks, tapAction: { if !link.flags.contains(.isEditable) { - if link.flags.contains(.isActive) { + if link.isActive { arguments.deactivateLink(link.username) } else { arguments.activateLink(link.username) @@ -291,19 +291,19 @@ private func usernameSetupControllerEntries(presentationData: PresentationData, var entries: [UsernameSetupEntry] = [] if let peer = view.peers[view.peerId] as? TelegramUser { - let currentAddressName: String + let currentUsername: String if let current = state.editingPublicLinkText { - currentAddressName = current + currentUsername = current } else { - if let addressName = peer.addressName { - currentAddressName = addressName + if let username = peer.editableUsername { + currentUsername = username } else { - currentAddressName = "" + currentUsername = "" } } entries.append(.publicLinkHeader(presentationData.theme, presentationData.strings.Username_Username)) - entries.append(.editablePublicLink(presentationData.theme, presentationData.strings, presentationData.strings.Username_Title, peer.addressName, currentAddressName)) + entries.append(.editablePublicLink(presentationData.theme, presentationData.strings, presentationData.strings.Username_Title, peer.editableUsername, currentUsername)) if let status = state.addressNameValidationStatus { let statusText: String switch status { @@ -323,7 +323,7 @@ private func usernameSetupControllerEntries(presentationData: PresentationData, case let .availability(availability): switch availability { case .available: - statusText = presentationData.strings.Username_UsernameIsAvailable(currentAddressName).string + statusText = presentationData.strings.Username_UsernameIsAvailable(currentUsername).string case .invalid: statusText = presentationData.strings.Username_InvalidCharacters case .taken: @@ -332,7 +332,7 @@ private func usernameSetupControllerEntries(presentationData: PresentationData, case .checking: statusText = presentationData.strings.Username_CheckingUsername } - entries.append(.publicLinkStatus(presentationData.theme, currentAddressName, status, statusText)) + entries.append(.publicLinkStatus(presentationData.theme, currentUsername, status, statusText)) } var infoText = presentationData.strings.Username_Help @@ -341,7 +341,7 @@ private func usernameSetupControllerEntries(presentationData: PresentationData, if otherUsernames.isEmpty { infoText += "\n\n" - let hintText = presentationData.strings.Username_LinkHint(currentAddressName.replacingOccurrences(of: "[", with: "").replacingOccurrences(of: "]", with: "")).string.replacingOccurrences(of: "]", with: "]()") + let hintText = presentationData.strings.Username_LinkHint(currentUsername.replacingOccurrences(of: "[", with: "").replacingOccurrences(of: "]", with: "")).string.replacingOccurrences(of: "]", with: "]()") infoText += hintText } entries.append(.publicLinkInfo(presentationData.theme, infoText)) @@ -546,7 +546,7 @@ public func usernameSetupController(context: AccountContext) -> ViewController { switch entry { case let .additionalLink(_, link, _): currentUsernames.append(link.username) - if !link.flags.contains(.isActive) && maxIndex == nil { + if !link.isActive && maxIndex == nil { maxIndex = max(0, i - 1) } i += 1 @@ -558,7 +558,7 @@ public func usernameSetupController(context: AccountContext) -> ViewController { if toIndex < entries.count { switch entries[toIndex] { case let .additionalLink(_, toUsername, _): - if toUsername.flags.contains(.isActive) { + if toUsername.isActive { referenceId = toUsername.username } else { afterAll = true diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 43cdfa5b82..5d57a49ea6 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -97,6 +97,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1312568665] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeStickerSet($0) } dict[-421545947] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeTitle($0) } dict[1783299128] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeUsername($0) } + dict[-263212119] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeUsernames($0) } dict[771095562] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionDefaultBannedRights($0) } dict[1121994683] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionDeleteMessage($0) } dict[-610299584] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionDiscardGroupCall($0) } @@ -795,7 +796,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[889491791] = { return Api.Update.parse_updateDialogFilters($0) } dict[1852826908] = { return Api.Update.parse_updateDialogPinned($0) } dict[-513517117] = { return Api.Update.parse_updateDialogUnreadMark($0) } - dict[-299124375] = { return Api.Update.parse_updateDraftMessage($0) } + dict[457829485] = { return Api.Update.parse_updateDraftMessage($0) } dict[457133559] = { return Api.Update.parse_updateEditChannelMessage($0) } dict[-469536605] = { return Api.Update.parse_updateEditMessage($0) } dict[386986326] = { return Api.Update.parse_updateEncryptedChatTyping($0) } @@ -815,7 +816,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1318109142] = { return Api.Update.parse_updateMessageID($0) } dict[-1398708869] = { return Api.Update.parse_updateMessagePoll($0) } dict[274961865] = { return Api.Update.parse_updateMessagePollVote($0) } - dict[357013699] = { return Api.Update.parse_updateMessageReactions($0) } + dict[1578843320] = { return Api.Update.parse_updateMessageReactions($0) } dict[-2030252155] = { return Api.Update.parse_updateMoveStickerSetToTop($0) } dict[1656358105] = { return Api.Update.parse_updateNewChannelMessage($0) } dict[314359194] = { return Api.Update.parse_updateNewEncryptedMessage($0) } @@ -855,7 +856,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-2112423005] = { return Api.Update.parse_updateTheme($0) } dict[8703322] = { return Api.Update.parse_updateTranscribedAudio($0) } dict[674706841] = { return Api.Update.parse_updateUserEmojiStatus($0) } - dict[-1007549728] = { return Api.Update.parse_updateUserName($0) } + dict[-1484486364] = { return Api.Update.parse_updateUserName($0) } dict[88680979] = { return Api.Update.parse_updateUserPhone($0) } dict[-232290676] = { return Api.Update.parse_updateUserPhoto($0) } dict[-440534818] = { return Api.Update.parse_updateUserStatus($0) } diff --git a/submodules/TelegramApi/Sources/Api1.swift b/submodules/TelegramApi/Sources/Api1.swift index 5718ccf94d..a819e925dc 100644 --- a/submodules/TelegramApi/Sources/Api1.swift +++ b/submodules/TelegramApi/Sources/Api1.swift @@ -805,7 +805,7 @@ public extension Api { } } public extension Api { - indirect enum BotCommandScope: TypeConstructorDescription { + enum BotCommandScope: TypeConstructorDescription { case botCommandScopeChatAdmins case botCommandScopeChats case botCommandScopeDefault diff --git a/submodules/TelegramApi/Sources/Api10.swift b/submodules/TelegramApi/Sources/Api10.swift index 7676164a2b..e7e10d87f8 100644 --- a/submodules/TelegramApi/Sources/Api10.swift +++ b/submodules/TelegramApi/Sources/Api10.swift @@ -263,7 +263,7 @@ public extension Api { } } public extension Api { - indirect enum InputStorePaymentPurpose: TypeConstructorDescription { + enum InputStorePaymentPurpose: TypeConstructorDescription { case inputStorePaymentGiftPremium(userId: Api.InputUser, currency: String, amount: Int64) case inputStorePaymentPremiumSubscription(flags: Int32) @@ -461,7 +461,7 @@ public extension Api { } } public extension Api { - indirect enum InputUser: TypeConstructorDescription { + enum InputUser: TypeConstructorDescription { case inputUser(userId: Int64, accessHash: Int64) case inputUserEmpty case inputUserFromMessage(peer: Api.InputPeer, msgId: Int32, userId: Int64) diff --git a/submodules/TelegramApi/Sources/Api11.swift b/submodules/TelegramApi/Sources/Api11.swift index 83decd957e..1498a03ff0 100644 --- a/submodules/TelegramApi/Sources/Api11.swift +++ b/submodules/TelegramApi/Sources/Api11.swift @@ -1,5 +1,5 @@ public extension Api { - indirect enum KeyboardButton: TypeConstructorDescription { + enum KeyboardButton: TypeConstructorDescription { case inputKeyboardButtonUrlAuth(flags: Int32, text: String, fwdText: String?, url: String, bot: Api.InputUser) case inputKeyboardButtonUserProfile(text: String, userId: Api.InputUser) case keyboardButton(text: String) @@ -757,7 +757,7 @@ public extension Api { } } public extension Api { - indirect enum Message: TypeConstructorDescription { + enum Message: TypeConstructorDescription { case message(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, forwards: Int32?, replies: Api.MessageReplies?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, reactions: Api.MessageReactions?, restrictionReason: [Api.RestrictionReason]?, ttlPeriod: Int32?) case messageEmpty(flags: Int32, id: Int32, peerId: Api.Peer?) case messageService(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, replyTo: Api.MessageReplyHeader?, date: Int32, action: Api.MessageAction, ttlPeriod: Int32?) diff --git a/submodules/TelegramApi/Sources/Api12.swift b/submodules/TelegramApi/Sources/Api12.swift index c3150a81e3..2e0f03b5fe 100644 --- a/submodules/TelegramApi/Sources/Api12.swift +++ b/submodules/TelegramApi/Sources/Api12.swift @@ -1,5 +1,5 @@ public extension Api { - indirect enum MessageEntity: TypeConstructorDescription { + enum MessageEntity: TypeConstructorDescription { case inputMessageEntityMentionName(offset: Int32, length: Int32, userId: Api.InputUser) case messageEntityBankCard(offset: Int32, length: Int32) case messageEntityBlockquote(offset: Int32, length: Int32) diff --git a/submodules/TelegramApi/Sources/Api14.swift b/submodules/TelegramApi/Sources/Api14.swift index 8bd01dfd9c..4a985aec2a 100644 --- a/submodules/TelegramApi/Sources/Api14.swift +++ b/submodules/TelegramApi/Sources/Api14.swift @@ -891,7 +891,7 @@ public extension Api { } } public extension Api { - indirect enum PageCaption: TypeConstructorDescription { + enum PageCaption: TypeConstructorDescription { case pageCaption(text: Api.RichText, credit: Api.RichText) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { @@ -935,7 +935,7 @@ public extension Api { } } public extension Api { - indirect enum PageListItem: TypeConstructorDescription { + enum PageListItem: TypeConstructorDescription { case pageListItemBlocks(blocks: [Api.PageBlock]) case pageListItemText(text: Api.RichText) diff --git a/submodules/TelegramApi/Sources/Api15.swift b/submodules/TelegramApi/Sources/Api15.swift index 167777f326..b797c99619 100644 --- a/submodules/TelegramApi/Sources/Api15.swift +++ b/submodules/TelegramApi/Sources/Api15.swift @@ -1,5 +1,5 @@ public extension Api { - indirect enum PageListOrderedItem: TypeConstructorDescription { + enum PageListOrderedItem: TypeConstructorDescription { case pageListOrderedItemBlocks(num: String, blocks: [Api.PageBlock]) case pageListOrderedItemText(num: String, text: Api.RichText) @@ -135,7 +135,7 @@ public extension Api { } } public extension Api { - indirect enum PageTableCell: TypeConstructorDescription { + enum PageTableCell: TypeConstructorDescription { case pageTableCell(flags: Int32, text: Api.RichText?, colspan: Int32?, rowspan: Int32?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { diff --git a/submodules/TelegramApi/Sources/Api17.swift b/submodules/TelegramApi/Sources/Api17.swift index ce013ce030..c6b278384d 100644 --- a/submodules/TelegramApi/Sources/Api17.swift +++ b/submodules/TelegramApi/Sources/Api17.swift @@ -157,7 +157,7 @@ public extension Api { } } public extension Api { - indirect enum RecentMeUrl: TypeConstructorDescription { + enum RecentMeUrl: TypeConstructorDescription { case recentMeUrlChat(url: String, chatId: Int64) case recentMeUrlChatInvite(url: String, chatInvite: Api.ChatInvite) case recentMeUrlStickerSet(url: String, set: Api.StickerSetCovered) diff --git a/submodules/TelegramApi/Sources/Api19.swift b/submodules/TelegramApi/Sources/Api19.swift index 9ce012be55..84e54145cb 100644 --- a/submodules/TelegramApi/Sources/Api19.swift +++ b/submodules/TelegramApi/Sources/Api19.swift @@ -433,7 +433,7 @@ public extension Api { } } public extension Api { - indirect enum SponsoredMessage: TypeConstructorDescription { + enum SponsoredMessage: TypeConstructorDescription { case sponsoredMessage(flags: Int32, randomId: Buffer, fromId: Api.Peer?, chatInvite: Api.ChatInvite?, chatInviteHash: String?, channelPost: Int32?, startParam: String?, message: String, entities: [Api.MessageEntity]?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { diff --git a/submodules/TelegramApi/Sources/Api2.swift b/submodules/TelegramApi/Sources/Api2.swift index c61ec4fe10..f8968d648e 100644 --- a/submodules/TelegramApi/Sources/Api2.swift +++ b/submodules/TelegramApi/Sources/Api2.swift @@ -555,7 +555,7 @@ public extension Api { } } public extension Api { - indirect enum ChannelAdminLogEvent: TypeConstructorDescription { + enum ChannelAdminLogEvent: TypeConstructorDescription { case channelAdminLogEvent(id: Int64, date: Int32, userId: Int64, action: Api.ChannelAdminLogEventAction) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { @@ -605,7 +605,7 @@ public extension Api { } } public extension Api { - indirect enum ChannelAdminLogEventAction: TypeConstructorDescription { + enum ChannelAdminLogEventAction: TypeConstructorDescription { case channelAdminLogEventActionChangeAbout(prevValue: String, newValue: String) case channelAdminLogEventActionChangeAvailableReactions(prevValue: Api.ChatReactions, newValue: Api.ChatReactions) case channelAdminLogEventActionChangeHistoryTTL(prevValue: Int32, newValue: Int32) @@ -615,6 +615,7 @@ public extension Api { case channelAdminLogEventActionChangeStickerSet(prevStickerset: Api.InputStickerSet, newStickerset: Api.InputStickerSet) case channelAdminLogEventActionChangeTitle(prevValue: String, newValue: String) case channelAdminLogEventActionChangeUsername(prevValue: String, newValue: String) + case channelAdminLogEventActionChangeUsernames(prevValue: [String], newValue: [String]) case channelAdminLogEventActionDefaultBannedRights(prevBannedRights: Api.ChatBannedRights, newBannedRights: Api.ChatBannedRights) case channelAdminLogEventActionDeleteMessage(message: Api.Message) case channelAdminLogEventActionDiscardGroupCall(call: Api.InputGroupCall) @@ -708,6 +709,21 @@ public extension Api { serializeString(prevValue, buffer: buffer, boxed: false) serializeString(newValue, buffer: buffer, boxed: false) break + case .channelAdminLogEventActionChangeUsernames(let prevValue, let newValue): + if boxed { + buffer.appendInt32(-263212119) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(prevValue.count)) + for item in prevValue { + serializeString(item, buffer: buffer, boxed: false) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(newValue.count)) + for item in newValue { + serializeString(item, buffer: buffer, boxed: false) + } + break case .channelAdminLogEventActionDefaultBannedRights(let prevBannedRights, let newBannedRights): if boxed { buffer.appendInt32(771095562) @@ -900,6 +916,8 @@ public extension Api { return ("channelAdminLogEventActionChangeTitle", [("prevValue", String(describing: prevValue)), ("newValue", String(describing: newValue))]) case .channelAdminLogEventActionChangeUsername(let prevValue, let newValue): return ("channelAdminLogEventActionChangeUsername", [("prevValue", String(describing: prevValue)), ("newValue", String(describing: newValue))]) + case .channelAdminLogEventActionChangeUsernames(let prevValue, let newValue): + return ("channelAdminLogEventActionChangeUsernames", [("prevValue", String(describing: prevValue)), ("newValue", String(describing: newValue))]) case .channelAdminLogEventActionDefaultBannedRights(let prevBannedRights, let newBannedRights): return ("channelAdminLogEventActionDefaultBannedRights", [("prevBannedRights", String(describing: prevBannedRights)), ("newBannedRights", String(describing: newBannedRights))]) case .channelAdminLogEventActionDeleteMessage(let message): @@ -1099,6 +1117,24 @@ public extension Api { return nil } } + public static func parse_channelAdminLogEventActionChangeUsernames(_ reader: BufferReader) -> ChannelAdminLogEventAction? { + var _1: [String]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) + } + var _2: [String]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.ChannelAdminLogEventAction.channelAdminLogEventActionChangeUsernames(prevValue: _1!, newValue: _2!) + } + else { + return nil + } + } public static func parse_channelAdminLogEventActionDefaultBannedRights(_ reader: BufferReader) -> ChannelAdminLogEventAction? { var _1: Api.ChatBannedRights? if let signature = reader.readInt32() { diff --git a/submodules/TelegramApi/Sources/Api20.swift b/submodules/TelegramApi/Sources/Api20.swift index b459faae82..7240ee7358 100644 --- a/submodules/TelegramApi/Sources/Api20.swift +++ b/submodules/TelegramApi/Sources/Api20.swift @@ -653,7 +653,7 @@ public extension Api { } } public extension Api { - indirect enum Update: TypeConstructorDescription { + enum Update: TypeConstructorDescription { case updateAttachMenuBots case updateBotCallbackQuery(flags: Int32, queryId: Int64, userId: Int64, peer: Api.Peer, msgId: Int32, chatInstance: Int64, data: Buffer?, gameShortName: String?) case updateBotChatInviteRequester(peer: Api.Peer, date: Int32, userId: Int64, about: String, invite: Api.ExportedChatInvite, qts: Int32) @@ -695,7 +695,7 @@ public extension Api { case updateDialogFilters case updateDialogPinned(flags: Int32, folderId: Int32?, peer: Api.DialogPeer) case updateDialogUnreadMark(flags: Int32, peer: Api.DialogPeer) - case updateDraftMessage(peer: Api.Peer, draft: Api.DraftMessage) + case updateDraftMessage(flags: Int32, peer: Api.Peer, topMsgId: Int32?, draft: Api.DraftMessage) case updateEditChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32) case updateEditMessage(message: Api.Message, pts: Int32, ptsCount: Int32) case updateEncryptedChatTyping(chatId: Int32) @@ -715,7 +715,7 @@ public extension Api { case updateMessageID(id: Int32, randomId: Int64) case updateMessagePoll(flags: Int32, pollId: Int64, poll: Api.Poll?, results: Api.PollResults) case updateMessagePollVote(pollId: Int64, userId: Int64, options: [Buffer], qts: Int32) - case updateMessageReactions(peer: Api.Peer, msgId: Int32, reactions: Api.MessageReactions) + case updateMessageReactions(flags: Int32, peer: Api.Peer, msgId: Int32, topMsgId: Int32?, reactions: Api.MessageReactions) case updateMoveStickerSetToTop(flags: Int32, stickerset: Int64) case updateNewChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32) case updateNewEncryptedMessage(message: Api.EncryptedMessage, qts: Int32) @@ -755,7 +755,7 @@ public extension Api { case updateTheme(theme: Api.Theme) case updateTranscribedAudio(flags: Int32, peer: Api.Peer, msgId: Int32, transcriptionId: Int64, text: String) case updateUserEmojiStatus(userId: Int64, emojiStatus: Api.EmojiStatus) - case updateUserName(userId: Int64, firstName: String, lastName: String, username: String) + case updateUserName(userId: Int64, firstName: String, lastName: String, usernames: [Api.Username]) case updateUserPhone(userId: Int64, phone: String) case updateUserPhoto(userId: Int64, date: Int32, photo: Api.UserProfilePhoto, previous: Api.Bool) case updateUserStatus(userId: Int64, status: Api.UserStatus) @@ -1139,11 +1139,13 @@ public extension Api { serializeInt32(flags, buffer: buffer, boxed: false) peer.serialize(buffer, true) break - case .updateDraftMessage(let peer, let draft): + case .updateDraftMessage(let flags, let peer, let topMsgId, let draft): if boxed { - buffer.appendInt32(-299124375) + buffer.appendInt32(457829485) } + serializeInt32(flags, buffer: buffer, boxed: false) peer.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)} draft.serialize(buffer, true) break case .updateEditChannelMessage(let message, let pts, let ptsCount): @@ -1301,12 +1303,14 @@ public extension Api { } serializeInt32(qts, buffer: buffer, boxed: false) break - case .updateMessageReactions(let peer, let msgId, let reactions): + case .updateMessageReactions(let flags, let peer, let msgId, let topMsgId, let reactions): if boxed { - buffer.appendInt32(357013699) + buffer.appendInt32(1578843320) } + serializeInt32(flags, buffer: buffer, boxed: false) peer.serialize(buffer, true) serializeInt32(msgId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)} reactions.serialize(buffer, true) break case .updateMoveStickerSetToTop(let flags, let stickerset): @@ -1639,14 +1643,18 @@ public extension Api { serializeInt64(userId, buffer: buffer, boxed: false) emojiStatus.serialize(buffer, true) break - case .updateUserName(let userId, let firstName, let lastName, let username): + case .updateUserName(let userId, let firstName, let lastName, let usernames): if boxed { - buffer.appendInt32(-1007549728) + buffer.appendInt32(-1484486364) } serializeInt64(userId, buffer: buffer, boxed: false) serializeString(firstName, buffer: buffer, boxed: false) serializeString(lastName, buffer: buffer, boxed: false) - serializeString(username, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(usernames.count)) + for item in usernames { + item.serialize(buffer, true) + } break case .updateUserPhone(let userId, let phone): if boxed { @@ -1779,8 +1787,8 @@ public extension Api { return ("updateDialogPinned", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("peer", String(describing: peer))]) case .updateDialogUnreadMark(let flags, let peer): return ("updateDialogUnreadMark", [("flags", String(describing: flags)), ("peer", String(describing: peer))]) - case .updateDraftMessage(let peer, let draft): - return ("updateDraftMessage", [("peer", String(describing: peer)), ("draft", String(describing: draft))]) + case .updateDraftMessage(let flags, let peer, let topMsgId, let draft): + return ("updateDraftMessage", [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("topMsgId", String(describing: topMsgId)), ("draft", String(describing: draft))]) case .updateEditChannelMessage(let message, let pts, let ptsCount): return ("updateEditChannelMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) case .updateEditMessage(let message, let pts, let ptsCount): @@ -1819,8 +1827,8 @@ public extension Api { return ("updateMessagePoll", [("flags", String(describing: flags)), ("pollId", String(describing: pollId)), ("poll", String(describing: poll)), ("results", String(describing: results))]) case .updateMessagePollVote(let pollId, let userId, let options, let qts): return ("updateMessagePollVote", [("pollId", String(describing: pollId)), ("userId", String(describing: userId)), ("options", String(describing: options)), ("qts", String(describing: qts))]) - case .updateMessageReactions(let peer, let msgId, let reactions): - return ("updateMessageReactions", [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("reactions", String(describing: reactions))]) + case .updateMessageReactions(let flags, let peer, let msgId, let topMsgId, let reactions): + return ("updateMessageReactions", [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("topMsgId", String(describing: topMsgId)), ("reactions", String(describing: reactions))]) case .updateMoveStickerSetToTop(let flags, let stickerset): return ("updateMoveStickerSetToTop", [("flags", String(describing: flags)), ("stickerset", String(describing: stickerset))]) case .updateNewChannelMessage(let message, let pts, let ptsCount): @@ -1899,8 +1907,8 @@ public extension Api { return ("updateTranscribedAudio", [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("transcriptionId", String(describing: transcriptionId)), ("text", String(describing: text))]) case .updateUserEmojiStatus(let userId, let emojiStatus): return ("updateUserEmojiStatus", [("userId", String(describing: userId)), ("emojiStatus", String(describing: emojiStatus))]) - case .updateUserName(let userId, let firstName, let lastName, let username): - return ("updateUserName", [("userId", String(describing: userId)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("username", String(describing: username))]) + case .updateUserName(let userId, let firstName, let lastName, let usernames): + return ("updateUserName", [("userId", String(describing: userId)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("usernames", String(describing: usernames))]) case .updateUserPhone(let userId, let phone): return ("updateUserPhone", [("userId", String(describing: userId)), ("phone", String(describing: phone))]) case .updateUserPhoto(let userId, let date, let photo, let previous): @@ -2716,18 +2724,24 @@ public extension Api { } } public static func parse_updateDraftMessage(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.Peer? if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer + _2 = Api.parse(reader, signature: signature) as? Api.Peer } - var _2: Api.DraftMessage? + var _3: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } + var _4: Api.DraftMessage? if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.DraftMessage + _4 = Api.parse(reader, signature: signature) as? Api.DraftMessage } let _c1 = _1 != nil let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateDraftMessage(peer: _1!, draft: _2!) + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateDraftMessage(flags: _1!, peer: _2!, topMsgId: _3, draft: _4!) } else { return nil @@ -3046,21 +3060,27 @@ public extension Api { } } public static func parse_updateMessageReactions(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.Peer? if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer + _2 = Api.parse(reader, signature: signature) as? Api.Peer } - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.MessageReactions? + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt32() } + var _5: Api.MessageReactions? if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.MessageReactions + _5 = Api.parse(reader, signature: signature) as? Api.MessageReactions } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateMessageReactions(peer: _1!, msgId: _2!, reactions: _3!) + let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.Update.updateMessageReactions(flags: _1!, peer: _2!, msgId: _3!, topMsgId: _4, reactions: _5!) } else { return nil @@ -3680,14 +3700,16 @@ public extension Api { _2 = parseString(reader) var _3: String? _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) + var _4: [Api.Username]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Username.self) + } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateUserName(userId: _1!, firstName: _2!, lastName: _3!, username: _4!) + return Api.Update.updateUserName(userId: _1!, firstName: _2!, lastName: _3!, usernames: _4!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api21.swift b/submodules/TelegramApi/Sources/Api21.swift index 1e7d3e5c54..faf9a62c53 100644 --- a/submodules/TelegramApi/Sources/Api21.swift +++ b/submodules/TelegramApi/Sources/Api21.swift @@ -1,5 +1,5 @@ public extension Api { - indirect enum Updates: TypeConstructorDescription { + enum Updates: TypeConstructorDescription { case updateShort(update: Api.Update, date: Int32) case updateShortChatMessage(flags: Int32, id: Int32, fromId: Int64, chatId: Int64, message: String, pts: Int32, ptsCount: Int32, date: Int32, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, entities: [Api.MessageEntity]?, ttlPeriod: Int32?) case updateShortMessage(flags: Int32, id: Int32, userId: Int64, message: String, pts: Int32, ptsCount: Int32, date: Int32, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, entities: [Api.MessageEntity]?, ttlPeriod: Int32?) diff --git a/submodules/TelegramApi/Sources/Api26.swift b/submodules/TelegramApi/Sources/Api26.swift index 77b921c3f0..97bb630fb1 100644 --- a/submodules/TelegramApi/Sources/Api26.swift +++ b/submodules/TelegramApi/Sources/Api26.swift @@ -1291,7 +1291,7 @@ public extension Api.payments { } } public extension Api.payments { - indirect enum PaymentResult: TypeConstructorDescription { + enum PaymentResult: TypeConstructorDescription { case paymentResult(updates: Api.Updates) case paymentVerificationNeeded(url: String) diff --git a/submodules/TelegramApi/Sources/Api29.swift b/submodules/TelegramApi/Sources/Api29.swift index e19c36280e..8c8390befa 100644 --- a/submodules/TelegramApi/Sources/Api29.swift +++ b/submodules/TelegramApi/Sources/Api29.swift @@ -5741,11 +5741,12 @@ public extension Api.functions.messages { } } public extension Api.functions.messages { - static func saveDraft(flags: Int32, replyToMsgId: Int32?, peer: Api.InputPeer, message: String, entities: [Api.MessageEntity]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func saveDraft(flags: Int32, replyToMsgId: Int32?, topMsgId: Int32?, peer: Api.InputPeer, message: String, entities: [Api.MessageEntity]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-1137057461) + buffer.appendInt32(-1271718337) serializeInt32(flags, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)} peer.serialize(buffer, true) serializeString(message, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) @@ -5753,7 +5754,7 @@ public extension Api.functions.messages { for item in entities! { item.serialize(buffer, true) }} - return (FunctionDescription(name: "messages.saveDraft", parameters: [("flags", String(describing: flags)), ("replyToMsgId", String(describing: replyToMsgId)), ("peer", String(describing: peer)), ("message", String(describing: message)), ("entities", String(describing: entities))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + return (FunctionDescription(name: "messages.saveDraft", parameters: [("flags", String(describing: flags)), ("replyToMsgId", String(describing: replyToMsgId)), ("topMsgId", String(describing: topMsgId)), ("peer", String(describing: peer)), ("message", String(describing: message)), ("entities", String(describing: entities))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in let reader = BufferReader(buffer) var result: Api.Bool? if let signature = reader.readInt32() { diff --git a/submodules/TelegramApi/Sources/Api3.swift b/submodules/TelegramApi/Sources/Api3.swift index 0c497a877f..11236a5b1e 100644 --- a/submodules/TelegramApi/Sources/Api3.swift +++ b/submodules/TelegramApi/Sources/Api3.swift @@ -521,7 +521,7 @@ public extension Api { } } public extension Api { - indirect enum Chat: TypeConstructorDescription { + enum Chat: TypeConstructorDescription { case channel(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, title: String, username: String?, photo: Api.ChatPhoto, date: Int32, restrictionReason: [Api.RestrictionReason]?, adminRights: Api.ChatAdminRights?, bannedRights: Api.ChatBannedRights?, defaultBannedRights: Api.ChatBannedRights?, participantsCount: Int32?, usernames: [Api.Username]?) case channelForbidden(flags: Int32, id: Int64, accessHash: Int64, title: String, untilDate: Int32?) case chat(flags: Int32, id: Int64, title: String, photo: Api.ChatPhoto, participantsCount: Int32, date: Int32, version: Int32, migratedTo: Api.InputChannel?, adminRights: Api.ChatAdminRights?, defaultBannedRights: Api.ChatBannedRights?) @@ -1219,7 +1219,7 @@ public extension Api { } } public extension Api { - indirect enum ChatInvite: TypeConstructorDescription { + enum ChatInvite: TypeConstructorDescription { case chatInvite(flags: Int32, title: String, about: String?, photo: Api.Photo, participantsCount: Int32, participants: [Api.User]?) case chatInviteAlready(chat: Api.Chat) case chatInvitePeek(chat: Api.Chat, expires: Int32) diff --git a/submodules/TelegramApi/Sources/Api7.swift b/submodules/TelegramApi/Sources/Api7.swift index 14d86d4ec5..a16bfce8fe 100644 --- a/submodules/TelegramApi/Sources/Api7.swift +++ b/submodules/TelegramApi/Sources/Api7.swift @@ -1,5 +1,5 @@ public extension Api { - indirect enum InputChannel: TypeConstructorDescription { + enum InputChannel: TypeConstructorDescription { case inputChannel(channelId: Int64, accessHash: Int64) case inputChannelEmpty case inputChannelFromMessage(peer: Api.InputPeer, msgId: Int32, channelId: Int64) @@ -311,7 +311,7 @@ public extension Api { } } public extension Api { - indirect enum InputDialogPeer: TypeConstructorDescription { + enum InputDialogPeer: TypeConstructorDescription { case inputDialogPeer(peer: Api.InputPeer) case inputDialogPeerFolder(folderId: Int32) @@ -653,7 +653,7 @@ public extension Api { } } public extension Api { - indirect enum InputFileLocation: TypeConstructorDescription { + enum InputFileLocation: TypeConstructorDescription { case inputDocumentFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String) case inputEncryptedFileLocation(id: Int64, accessHash: Int64) case inputFileLocation(volumeId: Int64, localId: Int32, secret: Int64, fileReference: Buffer) @@ -963,7 +963,7 @@ public extension Api { } } public extension Api { - indirect enum InputFolderPeer: TypeConstructorDescription { + enum InputFolderPeer: TypeConstructorDescription { case inputFolderPeer(peer: Api.InputPeer, folderId: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { diff --git a/submodules/TelegramApi/Sources/Api8.swift b/submodules/TelegramApi/Sources/Api8.swift index 89c644924e..5928a10d55 100644 --- a/submodules/TelegramApi/Sources/Api8.swift +++ b/submodules/TelegramApi/Sources/Api8.swift @@ -1,5 +1,5 @@ public extension Api { - indirect enum InputGame: TypeConstructorDescription { + enum InputGame: TypeConstructorDescription { case inputGameID(id: Int64, accessHash: Int64) case inputGameShortName(botId: Api.InputUser, shortName: String) @@ -165,7 +165,7 @@ public extension Api { } } public extension Api { - indirect enum InputInvoice: TypeConstructorDescription { + enum InputInvoice: TypeConstructorDescription { case inputInvoiceMessage(peer: Api.InputPeer, msgId: Int32) case inputInvoiceSlug(slug: String) @@ -857,7 +857,7 @@ public extension Api { } } public extension Api { - indirect enum InputNotifyPeer: TypeConstructorDescription { + enum InputNotifyPeer: TypeConstructorDescription { case inputNotifyBroadcasts case inputNotifyChats case inputNotifyForumTopic(peer: Api.InputPeer, topMsgId: Int32) diff --git a/submodules/TelegramApi/Sources/Api9.swift b/submodules/TelegramApi/Sources/Api9.swift index dab267e25b..764ed90abf 100644 --- a/submodules/TelegramApi/Sources/Api9.swift +++ b/submodules/TelegramApi/Sources/Api9.swift @@ -781,7 +781,7 @@ public extension Api { } } public extension Api { - indirect enum InputSingleMedia: TypeConstructorDescription { + enum InputSingleMedia: TypeConstructorDescription { case inputSingleMedia(flags: Int32, media: Api.InputMedia, randomId: Int64, message: String, entities: [Api.MessageEntity]?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 9219c3e9f6..8a44138f1b 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -125,7 +125,7 @@ private func peerIdsRequiringLocalChatStateFromUpdates(_ updates: [Api.Update]) peerIds.insert(PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))) case let .updateReadHistoryInbox(_, _, peer, _, _, _, _): peerIds.insert(peer.peerId) - case let .updateDraftMessage(peer, draft): + case let .updateDraftMessage(_, peer, _, draft): switch draft { case .draftMessage: peerIds.insert(peer.peerId) @@ -1236,11 +1236,11 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo }) case let .updateUserStatus(userId, status): updatedState.mergePeerPresences([PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)): status], explicit: true) - case let .updateUserName(userId, _, _, username): + case let .updateUserName(userId, _, _, usernames): //TODO add contact checking for apply first and last name updatedState.updatePeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), { peer in if let user = peer as? TelegramUser { - return user.withUpdatedUsername(username) + return user.withUpdatedUsernames(usernames.map { TelegramPeerUsername(apiUsername: $0) }) } else { return peer } @@ -1410,7 +1410,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo updatedState.addUpdateInstalledStickerPacks(.sync) case .updateSavedGifs: updatedState.addUpdateRecentGifs() - case let .updateDraftMessage(peer, draft): + case let .updateDraftMessage(_, peer, _, draft): let inputState: SynchronizeableChatInputState? switch draft { case .draftMessageEmpty: @@ -1551,7 +1551,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo return current } }) - case let .updateMessageReactions(peer, msgId, reactions): + case let .updateMessageReactions(_, peer, msgId, _, reactions): updatedState.updateMessageReactions(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: msgId), reactions: reactions, eventTimestamp: updatesDate) case .updateAttachMenuBots: updatedState.addUpdateAttachMenuBots() diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index 84f34af9b8..551b43f4bb 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -858,7 +858,7 @@ public final class AccountViewTracker { } for update in updateList { switch update { - case let .updateMessageReactions(peer, msgId, reactions): + case let .updateMessageReactions(_, peer, msgId, _, reactions): transaction.updateMessage(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: msgId), update: { currentMessage in var updatedReactions = ReactionsMessageAttribute(apiReactions: reactions) diff --git a/submodules/TelegramCore/Sources/State/ManagedSynchronizeChatInputStateOperations.swift b/submodules/TelegramCore/Sources/State/ManagedSynchronizeChatInputStateOperations.swift index c6112c68de..1641156675 100644 --- a/submodules/TelegramCore/Sources/State/ManagedSynchronizeChatInputStateOperations.swift +++ b/submodules/TelegramCore/Sources/State/ManagedSynchronizeChatInputStateOperations.swift @@ -141,14 +141,14 @@ private func synchronizeChatInputState(transaction: Transaction, postbox: Postbo flags |= (1 << 3) } } - return network.request(Api.functions.messages.saveDraft(flags: flags, replyToMsgId: inputState?.replyToMessageId?.id, peer: inputPeer, message: inputState?.text ?? "", entities: apiEntitiesFromMessageTextEntities(inputState?.entities ?? [], associatedPeers: SimpleDictionary()))) - |> delay(2.0, queue: Queue.concurrentDefaultQueue()) - |> `catch` { _ -> Signal in - return .single(.boolFalse) - } - |> mapToSignal { _ -> Signal in - return .complete() - } + return network.request(Api.functions.messages.saveDraft(flags: flags, replyToMsgId: inputState?.replyToMessageId?.id, topMsgId: nil, peer: inputPeer, message: inputState?.text ?? "", entities: apiEntitiesFromMessageTextEntities(inputState?.entities ?? [], associatedPeers: SimpleDictionary()))) + |> delay(2.0, queue: Queue.concurrentDefaultQueue()) + |> `catch` { _ -> Signal in + return .single(.boolFalse) + } + |> mapToSignal { _ -> Signal in + return .complete() + } } else { return .complete() } diff --git a/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift b/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift index 8217124be9..2c00487e9a 100644 --- a/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift +++ b/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift @@ -296,7 +296,7 @@ extension Api.Update { } else { return [] } - case let .updateDraftMessage(peer: peer, draft: _): + case let .updateDraftMessage(_, peer, _, _): return [peer.peerId] case let .updateNewScheduledMessage(message): return apiMessagePeerIds(message) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/ClearCloudDrafts.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ClearCloudDrafts.swift index f5ec6920b2..e25582447f 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/ClearCloudDrafts.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ClearCloudDrafts.swift @@ -26,7 +26,7 @@ func _internal_clearCloudDraftsInteractively(postbox: Postbox, network: Network, } for update in updates { switch update { - case let .updateDraftMessage(peer, _): + case let .updateDraftMessage(_, peer, _, _): peerIds.insert(peer.peerId) default: break @@ -42,7 +42,7 @@ func _internal_clearCloudDraftsInteractively(postbox: Postbox, network: Network, _internal_updateChatInputState(transaction: transaction, peerId: peerId, inputState: nil) if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { - signals.append(network.request(Api.functions.messages.saveDraft(flags: 0, replyToMsgId: nil, peer: inputPeer, message: "", entities: nil)) + signals.append(network.request(Api.functions.messages.saveDraft(flags: 0, replyToMsgId: nil, topMsgId: nil, peer: inputPeer, message: "", entities: nil)) |> `catch` { _ -> Signal in return .single(.boolFalse) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift index edb124ef14..5cb76f4eb6 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift @@ -303,7 +303,7 @@ func _internal_reorderAddressNames(account: Account, domain: AddressNameDomain, return account.postbox.transaction { transaction -> Signal in switch domain { case .account: - return account.network.request(Api.functions.account.reorderUsernames(order: names.filter { $0.flags.contains(.isActive) }.map { $0.username }), automaticFloodWait: false) + return account.network.request(Api.functions.account.reorderUsernames(order: names.filter { $0.isActive }.map { $0.username }), automaticFloodWait: false) |> mapError { _ -> ReorderAddressNamesError in return .generic } @@ -319,7 +319,7 @@ func _internal_reorderAddressNames(account: Account, domain: AddressNameDomain, } case let .peer(peerId): if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) { - return account.network.request(Api.functions.channels.reorderUsernames(channel: inputChannel, order: names.filter { $0.flags.contains(.isActive) }.map { $0.username }), automaticFloodWait: false) + return account.network.request(Api.functions.channels.reorderUsernames(channel: inputChannel, order: names.filter { $0.isActive }.map { $0.username }), automaticFloodWait: false) |> mapError { _ -> ReorderAddressNamesError in return .generic } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelAdminEventLogs.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelAdminEventLogs.swift index 47d31d2205..4eb2b67fe2 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelAdminEventLogs.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelAdminEventLogs.swift @@ -68,6 +68,7 @@ public enum AdminLogEventAction { case toggleCopyProtection(Bool) case sendMessage(Message) case changeAvailableReactions(previousValue: PeerAllowedReactions, updatedValue: PeerAllowedReactions) + case changeUsernames(prev: [String], new: [String]) } public enum ChannelAdminLogEventError { @@ -265,6 +266,8 @@ func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, m } case let .channelAdminLogEventActionChangeAvailableReactions(prevValue, newValue): action = .changeAvailableReactions(previousValue: PeerAllowedReactions(apiReactions: prevValue), updatedValue: PeerAllowedReactions(apiReactions: newValue)) + case let .channelAdminLogEventActionChangeUsernames(prevValue, newValue): + action = .changeUsernames(prev: prevValue, new: newValue) } let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)) if let action = action { diff --git a/submodules/TelegramCore/Sources/Utils/CanSendMessagesToPeer.swift b/submodules/TelegramCore/Sources/Utils/CanSendMessagesToPeer.swift index d47364a00b..3ef0fc377f 100644 --- a/submodules/TelegramCore/Sources/Utils/CanSendMessagesToPeer.swift +++ b/submodules/TelegramCore/Sources/Utils/CanSendMessagesToPeer.swift @@ -7,7 +7,7 @@ private final class LinkHelperClass: NSObject { } public func canSendMessagesToPeer(_ peer: Peer) -> Bool { - if let peer = peer as? TelegramUser, peer.username == "replies" { + if let peer = peer as? TelegramUser, peer.addressName == "replies" { return false } else if peer is TelegramUser || peer is TelegramGroup { return !peer.isDeleted diff --git a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift index 3ab16495a9..39134577c0 100644 --- a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift +++ b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift @@ -41,19 +41,20 @@ public extension Peer { return nil } } - + var addressName: String? { switch self { case let user as TelegramUser: - return user.username + return user.usernames.first(where: { $0.isActive }).map { $0.username } ?? user.username case _ as TelegramGroup: return nil case let channel as TelegramChannel: - return channel.username + return channel.usernames.first(where: { $0.isActive }).map { $0.username } ?? channel.username default: return nil } } + var usernames: [TelegramPeerUsername] { switch self { case let user as TelegramUser: @@ -67,6 +68,19 @@ public extension Peer { } } + var editableUsername: String? { + switch self { + case let user as TelegramUser: + return user.usernames.first(where: { $0.flags.contains(.isEditable) }).map { $0.username } ?? user.username + case _ as TelegramGroup: + return nil + case let channel as TelegramChannel: + return channel.usernames.first(where: { $0.flags.contains(.isEditable) }).map { $0.username } ?? channel.username + default: + return nil + } + } + var displayLetters: [String] { switch self { case let user as TelegramUser: @@ -189,6 +203,12 @@ public extension Peer { } } +public extension TelegramPeerUsername { + var isActive: Bool { + return self.flags.contains(.isActive) || self.flags.contains(.isEditable) + } +} + public extension PeerId { var isGroupOrChannel: Bool { switch self.namespace { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 071f3c73be..9769d50761 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -10980,7 +10980,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G canClearForEveryone = nil } } else if let channel = chatPeer as? TelegramChannel { - if let username = channel.username, !username.isEmpty { + if let username = channel.addressName, !username.isEmpty { if isLargeGroupOrChannel { canClearCache = true canClearForMyself = nil @@ -15486,7 +15486,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } self.chatDisplayNode.dismissInput() - if let peer = peer as? TelegramChannel, let username = peer.username, !username.isEmpty { + if let peer = peer as? TelegramChannel, let username = peer.addressName, !username.isEmpty { let actionSheet = ActionSheetController(presentationData: self.presentationData) var items: [ActionSheetItem] = [] diff --git a/submodules/TelegramUI/Sources/ChatInfoTitlePanelNode.swift b/submodules/TelegramUI/Sources/ChatInfoTitlePanelNode.swift index 9a00dc073e..05b056aaee 100644 --- a/submodules/TelegramUI/Sources/ChatInfoTitlePanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatInfoTitlePanelNode.swift @@ -84,7 +84,7 @@ private func peerButtons(_ peer: Peer, interfaceState: ChatPresentationInterface buttons.append(.info) return buttons } else if let channel = peer as? TelegramChannel { - if channel.flags.contains(.isCreator) || channel.username == nil { + if channel.flags.contains(.isCreator) || channel.addressName == nil { return [.search, muteAction, infoButton] } else { return [.search, .report, muteAction, infoButton] diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 46a6bf0b51..b09798b91b 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -1145,7 +1145,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if let attribute = attribute as? InlineBotMessageAttribute { var inlineBotNameString: String? if let peerId = attribute.peerId, let bot = item.message.peers[peerId] as? TelegramUser { - inlineBotNameString = bot.username + inlineBotNameString = bot.addressName } else { inlineBotNameString = attribute.title } @@ -1983,7 +1983,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if let item = self.item, let forwardInfo = item.message.forwardInfo { let performAction: () -> Void = { if let sourceMessageId = forwardInfo.sourceMessageId { - if !item.message.id.peerId.isReplies, let channel = forwardInfo.author as? TelegramChannel, channel.username == nil { + if !item.message.id.peerId.isReplies, let channel = forwardInfo.author as? TelegramChannel, channel.addressName == nil { if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) { } else if case .member = channel.participationStatus { } else { diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index a286281072..86607990e5 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -1412,7 +1412,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode for attribute in firstMessage.attributes { if let attribute = attribute as? InlineBotMessageAttribute { if let peerId = attribute.peerId, let bot = firstMessage.peers[peerId] as? TelegramUser { - inlineBotNameString = bot.username + inlineBotNameString = bot.addressName } else { inlineBotNameString = attribute.title } @@ -3363,7 +3363,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode if let item = self.item, let forwardInfo = item.message.forwardInfo { let performAction: () -> Void = { if let sourceMessageId = forwardInfo.sourceMessageId { - if let channel = forwardInfo.author as? TelegramChannel, channel.username == nil { + if let channel = forwardInfo.author as? TelegramChannel, channel.addressName == nil { if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) { } else if case .member = channel.participationStatus { } else if !item.message.id.peerId.isReplies { diff --git a/submodules/TelegramUI/Sources/ChatMessageForwardInfoNode.swift b/submodules/TelegramUI/Sources/ChatMessageForwardInfoNode.swift index 59f50ed74c..3a918999b5 100644 --- a/submodules/TelegramUI/Sources/ChatMessageForwardInfoNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageForwardInfoNode.swift @@ -184,7 +184,7 @@ class ChatMessageForwardInfoNode: ASDisplayNode { var currentCredibilityIconImage: UIImage? var highlight = true if let peer = peer { - if let channel = peer as? TelegramChannel, channel.username == nil { + if let channel = peer as? TelegramChannel, channel.addressName == nil { if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) { } else if case .member = channel.participationStatus { } else { diff --git a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift index e0e22d2e4b..2914f4bf43 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift @@ -424,7 +424,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD if let attribute = attribute as? InlineBotMessageAttribute { var inlineBotNameString: String? if let peerId = attribute.peerId, let bot = item.message.peers[peerId] as? TelegramUser { - inlineBotNameString = bot.username + inlineBotNameString = bot.addressName } else { inlineBotNameString = attribute.title } @@ -918,7 +918,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD if let item = self.item, let forwardInfo = item.message.forwardInfo { let performAction: () -> Void = { if let sourceMessageId = forwardInfo.sourceMessageId { - if !item.message.id.peerId.isReplies, let channel = forwardInfo.author as? TelegramChannel, channel.username == nil { + if !item.message.id.peerId.isReplies, let channel = forwardInfo.author as? TelegramChannel, channel.addressName == nil { if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) { } else if case .member = channel.participationStatus { } else { diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index eb095d63b6..308ee6f10e 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -590,7 +590,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { if let attribute = attribute as? InlineBotMessageAttribute { var inlineBotNameString: String? if let peerId = attribute.peerId, let bot = item.message.peers[peerId] as? TelegramUser { - inlineBotNameString = bot.username + inlineBotNameString = bot.addressName } else { inlineBotNameString = attribute.title } diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift index 10d06ed9a1..8394b9ac7e 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift @@ -200,6 +200,56 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { attributes.append(TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< text.count, type: .Italic)])) } + let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) + return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.isEmpty ? .eventLogPreviousLink(prevMessage) : nil) + } + case let .changeUsernames(prev, new): + var peers = SimpleDictionary() + var author: Peer? + if let peer = self.entry.peers[self.entry.event.peerId] { + author = peer + peers[peer.id] = peer + } + + switch self.id.contentIndex { + case .header: + var text: String = "" + var entities: [MessageTextEntity] = [] + if let peer = peer as? TelegramChannel, case .broadcast = peer.info { + appendAttributedText(text: self.presentationData.strings.Channel_AdminLog_MessageChangedChannelUsername(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? ""), generateEntities: { index in + if index == 0, let author = author { + return [.TextMention(peerId: author.id)] + } + return [] + }, to: &text, entities: &entities) + } else { + appendAttributedText(text: self.presentationData.strings.Channel_AdminLog_MessageChangedGroupUsername(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? ""), generateEntities: { index in + if index == 0, let author = author { + return [.TextMention(peerId: author.id)] + } + return [] + }, to: &text, entities: &entities) + } + let action: TelegramMediaActionType = TelegramMediaActionType.customText(text: text, entities: entities) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) + return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) + case .content: + var previousAttributes: [MessageAttribute] = [] + var attributes: [MessageAttribute] = [] + + let prevText = "https://t.me/\(prev.first ?? "")" + previousAttributes.append(TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< prevText.count, type: .Url)])) + + let text: String + if !new.isEmpty { + text = "https://t.me/\(new.first ?? "")" + attributes.append(TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< text.count, type: .Url)])) + } else { + text = self.presentationData.strings.Channel_AdminLog_EmptyMessageText + attributes.append(TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< text.count, type: .Italic)])) + } + let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.isEmpty ? .eventLogPreviousLink(prevMessage) : nil) diff --git a/submodules/TelegramUI/Sources/NavigateToChatController.swift b/submodules/TelegramUI/Sources/NavigateToChatController.swift index f7d0889293..70093d9666 100644 --- a/submodules/TelegramUI/Sources/NavigateToChatController.swift +++ b/submodules/TelegramUI/Sources/NavigateToChatController.swift @@ -228,8 +228,8 @@ public func isOverlayControllerForChatNotificationOverlayPresentation(_ controll return false } -public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal { - return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: nil, preload: false) +public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal { + return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: messageId, preload: false) |> deliverOnMainQueue |> beforeNext { [weak context, weak navigationController] result in guard let context = context, let navigationController = navigationController else { @@ -239,7 +239,11 @@ public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePee let chatLocation: ChatLocation = .replyThread(message: result.message) let subject: ChatControllerSubject? - subject = nil + if let messageId = messageId { + subject = .message(id: .id(messageId), highlight: true, timecode: nil) + } else { + subject = nil + } var actualActivateInput: ChatControllerActivateInput? = result.isEmpty ? .text : nil if let activateInput = activateInput { diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index 2e0e762ceb..8dbd8c62c4 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -2614,8 +2614,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { if self.isSettings, let user = peer as? TelegramUser { var subtitle = formatPhoneNumber(user.phone ?? "") - let mainUsername = user.usernames.first(where: { $0.flags.contains(.isActive) })?.username ?? user.username - if let mainUsername = mainUsername, !mainUsername.isEmpty { + if let mainUsername = user.addressName, !mainUsername.isEmpty { subtitle = "\(subtitle) • @\(mainUsername)" } smallSubtitleString = NSAttributedString(string: subtitle, font: Font.regular(15.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.7)) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 68953fc1f1..4b6728954a 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -956,10 +956,9 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese interaction.requestLayout(false) })) } - if let username = user.username { - let mainUsername = user.usernames.first(where: { $0.flags.contains(.isActive) })?.username ?? username + if let mainUsername = user.addressName { var additionalUsernames: String? - let usernames = user.usernames.filter { $0.flags.contains(.isActive) && $0.username != mainUsername } + let usernames = user.usernames.filter { $0.isActive && $0.username != mainUsername } if !usernames.isEmpty { additionalUsernames = presentationData.strings.Profile_AdditionalUsernames(String(usernames.map { "@\($0.username)" }.joined(separator: ", "))).string } @@ -973,7 +972,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese textColor: .accent, icon: .qrCode, action: { _ in - interaction.openUsername(username) + interaction.openUsername(mainUsername) }, longTapAction: { sourceNode in interaction.openPeerInfoContextMenu(.link(customLink: nil), sourceNode, nil) }, linkItemAction: { type, item, _, _ in @@ -1134,11 +1133,9 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese )) } - if let username = channel.username { + if let mainUsername = channel.addressName { var additionalUsernames: String? - let mainUsername = channel.usernames.first(where: { $0.flags.contains(.isActive) })?.username ?? username - - let usernames = channel.usernames.filter { $0.flags.contains(.isActive) && $0.username != mainUsername } + let usernames = channel.usernames.filter { $0.isActive && $0.username != mainUsername } if !usernames.isEmpty { additionalUsernames = presentationData.strings.Profile_AdditionalUsernames(String(usernames.map { "@\($0.username)" }.joined(separator: ", "))).string } @@ -1152,7 +1149,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese textColor: .accent, icon: .qrCode, action: { _ in - interaction.openUsername(username) + interaction.openUsername(mainUsername) }, longTapAction: { sourceNode in interaction.openPeerInfoContextMenu(.link(customLink: nil), sourceNode, nil) }, linkItemAction: { type, item, sourceNode, sourceRect in @@ -1350,7 +1347,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr if isCreator { let linkText: String - if let _ = channel.username { + if let _ = channel.addressName { linkText = presentationData.strings.Channel_Setup_TypePublic } else { linkText = presentationData.strings.Channel_Setup_TypePrivate @@ -1360,7 +1357,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr })) } - if (isCreator && (channel.username?.isEmpty ?? true)) || (!channel.flags.contains(.isCreator) && channel.adminRights?.rights.contains(.canInviteUsers) == true) { + if (isCreator && (channel.addressName?.isEmpty ?? true)) || (!channel.flags.contains(.isCreator) && channel.adminRights?.rights.contains(.canInviteUsers) == true) { let invitesText: String if let count = data.invitations?.count, count > 0 { invitesText = "\(count)" @@ -1488,7 +1485,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr let ItemTopics = 116 let isCreator = channel.flags.contains(.isCreator) - let isPublic = channel.username != nil + let isPublic = channel.addressName != nil if let cachedData = data.cachedData as? CachedChannelData { if isCreator, let location = cachedData.peerGeoLocation { @@ -1515,7 +1512,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr if cachedData.peerGeoLocation != nil { if isCreator { let linkText: String - if let username = channel.username { + if let username = channel.addressName { linkText = "@\(username)" } else { linkText = presentationData.strings.GroupInfo_PublicLinkAdd @@ -1533,7 +1530,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr } } - if (isCreator && (channel.username?.isEmpty ?? true) && cachedData.peerGeoLocation == nil) || (!isCreator && channel.adminRights?.rights.contains(.canInviteUsers) == true) { + if (isCreator && (channel.addressName?.isEmpty ?? true) && cachedData.peerGeoLocation == nil) || (!isCreator && channel.adminRights?.rights.contains(.canInviteUsers) == true) { let invitesText: String if let count = data.invitations?.count, count > 0 { invitesText = "\(count)" @@ -3210,7 +3207,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate })) } - if copyUsername, let username = user.username, !username.isEmpty { + if copyUsername, let username = user.addressName, !username.isEmpty { actions.append(ContextMenuAction(content: .text(title: strongSelf.presentationData.strings.Settings_CopyUsername, accessibilityLabel: strongSelf.presentationData.strings.Settings_CopyUsername), action: { [weak self] in UIPasteboard.general.string = "@\(username)" @@ -4268,7 +4265,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } if let _ = user.botInfo { - if user.username != nil { + if user.addressName != nil { items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_ShareBot, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in @@ -5827,7 +5824,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate guard let strongSelf = self else { return } - if case let .user(peer) = peer, let username = peer.username { + if case let .user(peer) = peer, let username = peer.addressName { let shareController = ShareController(context: strongSelf.context, subject: .url("https://t.me/\(username)"), updatedPresentationData: strongSelf.controller?.updatedPresentationData) shareController.completed = { [weak self] peerIds in guard let strongSelf = self else { @@ -9585,7 +9582,7 @@ struct ClearPeerHistory { var canDeleteLocally = true if case .broadcast = channel.info { canDeleteLocally = false - } else if channel.username != nil { + } else if channel.addressName != nil { canDeleteLocally = false } diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index 09467f36b1..eff9ed453a 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -600,7 +600,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { location: .chatList(groupId: EngineChatList.Group(.root)), displaySearchFilters: false, hasDownloads: false, - openPeer: { [weak self] peer, chatPeer, _ in + openPeer: { [weak self] peer, chatPeer, _, _ in guard let strongSelf = self else { return } diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 1e9b1d2ba6..5e676c4756 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1159,8 +1159,8 @@ public final class SharedAccountContextImpl: SharedAccountContext { navigateToForumChannelImpl(context: context, peerId: peerId, navigationController: navigationController) } - public func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal { - return navigateToForumThreadImpl(context: context, peerId: peerId, threadId: threadId, navigationController: navigationController, activateInput: activateInput) + public func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal { + return navigateToForumThreadImpl(context: context, peerId: peerId, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: activateInput) } public func openStorageUsage(context: AccountContext) {