Various improvements

This commit is contained in:
Ilya Laktyushin 2022-10-15 21:08:11 +03:00
parent da4934dc97
commit 59b593696e
54 changed files with 379 additions and 236 deletions

View File

@ -135,7 +135,7 @@ func personWithUser(stableId: String, user: TelegramUser) -> INPerson {
let personHandle: INPersonHandle let personHandle: INPersonHandle
if let phone = user.phone { if let phone = user.phone {
personHandle = INPersonHandle(value: formatPhoneNumber(phone), type: .phoneNumber) 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) personHandle = INPersonHandle(value: "@\(username)", type: .unknown)
} else { } else {
personHandle = INPersonHandle(value: user.nameOrPhone, type: .unknown) personHandle = INPersonHandle(value: user.nameOrPhone, type: .unknown)

View File

@ -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<Friend> in accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, useCopy: false, transaction: { postbox, transaction -> INObjectSection<Friend> in
var accountTitle: String = "" var accountTitle: String = ""
if let peer = transaction.getPeer(accountPeerId) as? TelegramUser { if let peer = transaction.getPeer(accountPeerId) as? TelegramUser {
if let username = peer.username, !username.isEmpty { if let username = peer.addressName, !username.isEmpty {
accountTitle = "@\(username)" accountTitle = "@\(username)"
} else { } else {
accountTitle = peer.debugDisplayTitle 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<Friend> in accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, useCopy: false, transaction: { postbox, transaction -> INObjectSection<Friend> in
var accountTitle: String = "" var accountTitle: String = ""
if let peer = transaction.getPeer(accountPeerId) as? TelegramUser { if let peer = transaction.getPeer(accountPeerId) as? TelegramUser {
if let username = peer.username, !username.isEmpty { if let username = peer.addressName, !username.isEmpty {
accountTitle = "@\(username)" accountTitle = "@\(username)"
} else { } else {
accountTitle = peer.debugDisplayTitle accountTitle = peer.debugDisplayTitle

View File

@ -129,7 +129,7 @@ private func callWithTelegramMessage(_ telegramMessage: Message, account: Accoun
if #available(iOSApplicationExtension 10.2, iOS 10.2, *) { if #available(iOSApplicationExtension 10.2, iOS 10.2, *) {
var type: INPersonHandleType var type: INPersonHandleType
var label: INPersonHandleLabel? var label: INPersonHandleLabel?
if let username = user.username { if let username = user.addressName {
label = INPersonHandleLabel(rawValue: "@\(username)") label = INPersonHandleLabel(rawValue: "@\(username)")
type = .unknown type = .unknown
} else if let phone = user.phone { } else if let phone = user.phone {
@ -168,7 +168,7 @@ private func messageWithTelegramMessage(_ telegramMessage: Message) -> INMessage
if #available(iOSApplicationExtension 10.2, iOS 10.2, *) { if #available(iOSApplicationExtension 10.2, iOS 10.2, *) {
var type: INPersonHandleType var type: INPersonHandleType
var label: INPersonHandleLabel? var label: INPersonHandleLabel?
if let username = user.username { if let username = user.addressName {
label = INPersonHandleLabel(rawValue: "@\(username)") label = INPersonHandleLabel(rawValue: "@\(username)")
type = .unknown type = .unknown
} else if let phone = user.phone { } else if let phone = user.phone {

View File

@ -737,7 +737,7 @@ public protocol SharedAccountContext: AnyObject {
func makePrivacyAndSecurityController(context: AccountContext) -> ViewController func makePrivacyAndSecurityController(context: AccountContext) -> ViewController
func navigateToChatController(_ params: NavigateToChatControllerParams) func navigateToChatController(_ params: NavigateToChatControllerParams)
func navigateToForumChannel(context: AccountContext, peerId: EnginePeer.Id, navigationController: NavigationController) func navigateToForumChannel(context: AccountContext, peerId: EnginePeer.Id, navigationController: NavigationController)
func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal<Never, NoError> func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal<Never, NoError>
func openStorageUsage(context: AccountContext) func openStorageUsage(context: AccountContext)
func openLocationScreen(context: AccountContext, messageId: MessageId, navigationController: NavigationController) 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) func openExternalUrl(context: AccountContext, urlContext: OpenURLContext, url: String, forceExternal: Bool, presentationData: PresentationData, navigationController: NavigationController?, dismissInput: @escaping () -> Void)

View File

@ -1362,7 +1362,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.context.sharedContext.navigateToForumChannel(context: strongSelf.context, peerId: channel.id, navigationController: navigationController) strongSelf.context.sharedContext.navigateToForumChannel(context: strongSelf.context, peerId: channel.id, navigationController: navigationController)
} else { } else {
if let threadId = threadId { 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) strongSelf.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true)
} else { } else {
var navigationAnimationOptions: NavigationAnimationOptions = [] var navigationAnimationOptions: NavigationAnimationOptions = []
@ -1462,11 +1462,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
if case .chatList(.root) = strongSelf.location { if case .chatList(.root) = strongSelf.location {
navigationAnimationOptions = .removeOnMasterDetails 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 let threadId = threadId {
if deactivateOnAction { let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: nil).start()
self?.deactivateSearch(animated: false) } 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: {
}, scrollToEndIfExists: scrollToEndIfExists, options: navigationAnimationOptions)) if deactivateOnAction {
self?.deactivateSearch(animated: false)
}
}, scrollToEndIfExists: scrollToEndIfExists, options: navigationAnimationOptions))
}
strongSelf.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true) 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 { if let strongSelf = self {
let storedPeer = strongSelf.context.engine.peers.ensurePeerIsLocallyAvailable(peer: peer) |> map { _ -> Void in return Void() } let storedPeer = strongSelf.context.engine.peers.ensurePeerIsLocallyAvailable(peer: peer) |> map { _ -> Void in return Void() }
strongSelf.openMessageFromSearchDisposable.set((storedPeer |> deliverOnMainQueue).start(completed: { [weak strongSelf] in 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 { if case .chatList(.root) = strongSelf.location {
navigationAnimationOptions = .removeOnMasterDetails navigationAnimationOptions = .removeOnMasterDetails
} }
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), purposefulAction: { [weak self] in if let threadId = threadId {
self?.deactivateSearch(animated: false) let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil).start()
}, scrollToEndIfExists: scrollToEndIfExists, options: navigationAnimationOptions)) } 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) 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) let _ = (context.engine.peers.createForumChannelTopic(id: peerId, title: title, iconColor: availableColors.randomElement()!, iconFileId: fileId)
|> deliverOnMainQueue).start(next: { topicId in |> 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) 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) let _ = (context.engine.peers.createForumChannelTopic(id: peerId, title: title, iconColor: availableColors.randomElement()!, iconFileId: fileId)
|> deliverOnMainQueue).start(next: { topicId in |> deliverOnMainQueue).start(next: { topicId in
if let navigationController = (sourceController.navigationController as? NavigationController) { 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()
} }
}) })
} }

View File

@ -1135,7 +1135,7 @@ final class ChatListControllerNode: ASDisplayNode {
private var containerLayout: (ContainerViewLayout, CGFloat, CGFloat, CGFloat)? private var containerLayout: (ContainerViewLayout, CGFloat, CGFloat, CGFloat)?
var requestDeactivateSearch: (() -> Void)? var requestDeactivateSearch: (() -> Void)?
var requestOpenPeerFromSearch: ((EnginePeer, Bool) -> Void)? var requestOpenPeerFromSearch: ((EnginePeer, Int64?, Bool) -> Void)?
var requestOpenRecentPeerOptions: ((EnginePeer) -> Void)? var requestOpenRecentPeerOptions: ((EnginePeer) -> Void)?
var requestOpenMessageFromSearch: ((EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void)? var requestOpenMessageFromSearch: ((EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void)?
var requestAddContact: ((String) -> Void)? var requestAddContact: ((String) -> Void)?
@ -1311,8 +1311,8 @@ final class ChatListControllerNode: ASDisplayNode {
let filter: ChatListNodePeersFilter = [] 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 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, dismissSearch) self?.requestOpenPeerFromSearch?(peer, threadId, dismissSearch)
}, openDisabledPeer: { _ in }, openDisabledPeer: { _ in
}, openRecentPeerOptions: { [weak self] peer in }, openRecentPeerOptions: { [weak self] peer in
self?.requestOpenRecentPeerOptions?(peer) self?.requestOpenRecentPeerOptions?(peer)

View File

@ -43,7 +43,7 @@ private enum ChatListTokenId: Int32 {
} }
final class ChatListSearchInteraction { final class ChatListSearchInteraction {
let openPeer: (EnginePeer, EnginePeer?, Bool) -> Void let openPeer: (EnginePeer, EnginePeer?, Int64?, Bool) -> Void
let openDisabledPeer: (EnginePeer) -> Void let openDisabledPeer: (EnginePeer) -> Void
let openMessage: (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void let openMessage: (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void
let openUrl: (String) -> Void let openUrl: (String) -> Void
@ -57,7 +57,7 @@ final class ChatListSearchInteraction {
let dismissInput: () -> Void let dismissInput: () -> Void
let getSelectedMessageIds: () -> Set<EngineMessage.Id>? let getSelectedMessageIds: () -> Set<EngineMessage.Id>?
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<EngineMessage.Id>?) { 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<EngineMessage.Id>?) {
self.openPeer = openPeer self.openPeer = openPeer
self.openDisabledPeer = openDisabledPeer self.openDisabledPeer = openDisabledPeer
self.openMessage = openMessage self.openMessage = openMessage
@ -133,7 +133,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
private var validLayout: (ContainerViewLayout, CGFloat)? private var validLayout: (ContainerViewLayout, CGFloat)?
public init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = 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<PresentationData, NoError>)? = 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.context = context
self.peersFilter = filter self.peersFilter = filter
self.location = location self.location = location
@ -159,8 +159,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
self.addSubnode(self.paneContainerNode) self.addSubnode(self.paneContainerNode)
let interaction = ChatListSearchInteraction(openPeer: { peer, chatPeer, value in let interaction = ChatListSearchInteraction(openPeer: { peer, chatPeer, threadId, value in
originalOpenPeer(peer, chatPeer, value) originalOpenPeer(peer, chatPeer, threadId, value)
if peer.id.namespace != Namespaces.Peer.SecretChat { if peer.id.namespace != Namespaces.Peer.SecretChat {
addAppLogEvent(postbox: context.account.postbox, type: "search_global_open_peer", peerId: peer.id) addAppLogEvent(postbox: context.account.postbox, type: "search_global_open_peer", peerId: peer.id)
} }

View File

@ -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 { 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 { switch self {
case let .topic(peer, threadInfo, _, theme, strings, expandType): case let .topic(peer, threadInfo, _, theme, strings, expandType):
let actionTitle: String? let actionTitle: String?
switch expandType { switch expandType {
case .none: case .none:
actionTitle = nil actionTitle = nil
case .expand: case .expand:
actionTitle = strings.ChatList_Search_ShowMore actionTitle = strings.ChatList_Search_ShowMore
case .collapse: case .collapse:
actionTitle = strings.ChatList_Search_ShowLess actionTitle = strings.ChatList_Search_ShowLess
} }
let header = ChatListSearchItemHeader(type: .topics, theme: theme, strings: strings, actionTitle: actionTitle, action: actionTitle == nil ? nil : { let header = ChatListSearchItemHeader(type: .topics, theme: theme, strings: strings, actionTitle: actionTitle, action: actionTitle == nil ? nil : {
toggleExpandGlobalResults() 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 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) interaction.peerSelected(peer, nil, threadInfo.id, nil)
}, contextAction: nil, animationCache: interaction.animationCache, animationRenderer: interaction.animationRenderer) }, contextAction: nil, animationCache: interaction.animationCache, animationRenderer: interaction.animationRenderer)
case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder): case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder):
let primaryPeer: EnginePeer let primaryPeer: EnginePeer
var chatPeer: 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 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 { 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 { } else {
interaction.peerSelected(peer, nil, nil, nil) 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 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 { 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 { } else {
interaction.peerSelected(peer, nil, nil, nil) 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)) index = .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index))
case .forum: case .forum:
if let threadId = message.threadId, let threadInfo = threadInfo { if let threadId = message.threadId, let threadInfo = threadInfo {
chatThreadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadInfo) chatThreadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadInfo, isOwner: false, isClosed: false)
index = .forum(timestamp: message.index.timestamp, threadId: threadId, namespace: message.index.id.namespace, id: message.index.id.id) index = .forum(pinnedIndex: .none, timestamp: message.index.timestamp, threadId: threadId, namespace: message.index.id.namespace, id: message.index.id.id)
} else { } 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) 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 { if let resourceValue = findMediaResourceById(message: item.message, resourceId: item.resourceId), let size = resourceValue.size {
resource = (resourceValue.id.stringRepresentation, size, entries.isEmpty) resource = (resourceValue.id.stringRepresentation, size, entries.isEmpty)
} }
entries.append(.message(message, peer, nil, nil, presentationData, 1, nil, false, .downloading(item.priority), resource, .downloading, allPaused)) 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) }) { 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) let foundThreads: Signal<([Int64: MessageHistoryThreadData], [EngineChatList.Item]), NoError> = chatListViewForLocation(chatListLocation: location, location: .initial(count: 1000, filter: nil), account: context.account)
|> map { view -> ([Int64: EngineMessageHistoryThread.Info], [EngineChatList.Item]) in |> map { view -> ([Int64: MessageHistoryThreadData], [EngineChatList.Item]) in
var itemsMap: [Int64: EngineMessageHistoryThread.Info] = [:] var itemsMap: [Int64: MessageHistoryThreadData] = [:]
var filteredItems: [EngineChatList.Item] = [] var filteredItems: [EngineChatList.Item] = []
let queryTokens = stringIndexTokens(finalQuery, transliteration: .combined) let queryTokens = stringIndexTokens(finalQuery, transliteration: .combined)
for item in view.list.items { for item in view.list.items {
if case let .forum(_, index, _, _) = item.index, let threadInfo = item.threadInfo { if case let .forum(_, _, index, _, _) = item.index, let threadData = item.threadData {
itemsMap[index] = threadInfo itemsMap[index] = threadData
} }
if !finalQuery.isEmpty { if !finalQuery.isEmpty {
if let title = item.threadInfo?.title { if let title = item.threadData?.info.title {
let tokens = stringIndexTokens(title, transliteration: .combined) let tokens = stringIndexTokens(title, transliteration: .combined)
if matchStringIndexTokens(tokens, with: queryTokens) { if matchStringIndexTokens(tokens, with: queryTokens) {
filteredItems.append(item) filteredItems.append(item)
@ -1508,6 +1508,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
} }
} }
} }
return (itemsMap, filteredItems) return (itemsMap, filteredItems)
} }
@ -1518,8 +1519,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
var index = 0 var index = 0
for thread in allAndFoundThreads.1 { for thread in allAndFoundThreads.1 {
if let peer = thread.renderedPeer.peer, let threadInfo = thread.threadInfo, case let .forum(_, id, _, _) = thread.index { 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: threadInfo), index, presentationData.theme, presentationData.strings, .none)) 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 index += 1
} }
} }
@ -1715,7 +1716,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
peer = EngineRenderedPeer(peer: EnginePeer(channelPeer)) 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 index += 1
} }
@ -1738,7 +1739,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
peer = EngineRenderedPeer(peer: EnginePeer(channelPeer)) 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 index += 1
} }
} }
@ -1810,9 +1811,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
} }
let chatListInteraction = ChatListNodeInteraction(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, activateSearch: { 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.dismissInput()
interaction.openPeer(peer, chatPeer, false) interaction.openPeer(peer, chatPeer, threadId, false)
let _ = context.engine.peers.addRecentlySearchedPeer(peerId: peer.id).start() let _ = context.engine.peers.addRecentlySearchedPeer(peerId: peer.id).start()
self?.listNode.clearHighlightAnimated(true) self?.listNode.clearHighlightAnimated(true)
}, disabledPeerSelected: { _ in }, disabledPeerSelected: { _ in
@ -2159,7 +2160,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
let firstTime = previousEntries == nil let firstTime = previousEntries == nil
let transition = chatListSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries, context: context, presentationData: presentationData, filter: peersFilter, peerSelected: { peer in 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() let _ = context.engine.peers.addRecentlySearchedPeer(peerId: peer.id).start()
self?.recentListNode.clearHighlightAnimated(true) self?.recentListNode.clearHighlightAnimated(true)
}, disabledPeerSelected: { peer in }, disabledPeerSelected: { peer in

View File

@ -56,7 +56,7 @@ public final class ChatListNodeInteraction {
} }
let activateSearch: () -> Void let activateSearch: () -> Void
let peerSelected: (EnginePeer, Int64?, EnginePeer?, ChatListNodeEntryPromoInfo?) -> Void let peerSelected: (EnginePeer, EnginePeer?, Int64?, ChatListNodeEntryPromoInfo?) -> Void
let disabledPeerSelected: (EnginePeer) -> Void let disabledPeerSelected: (EnginePeer) -> Void
let togglePeerSelected: (EnginePeer) -> Void let togglePeerSelected: (EnginePeer) -> Void
let togglePeersSelection: ([PeerEntry], Bool) -> Void let togglePeersSelection: ([PeerEntry], Bool) -> Void
@ -90,7 +90,7 @@ public final class ChatListNodeInteraction {
animationCache: AnimationCache, animationCache: AnimationCache,
animationRenderer: MultiAnimationRenderer, animationRenderer: MultiAnimationRenderer,
activateSearch: @escaping () -> Void, activateSearch: @escaping () -> Void,
peerSelected: @escaping (EnginePeer, Int64?, EnginePeer?, ChatListNodeEntryPromoInfo?) -> Void, peerSelected: @escaping (EnginePeer, EnginePeer?, Int64?, ChatListNodeEntryPromoInfo?) -> Void,
disabledPeerSelected: @escaping (EnginePeer) -> Void, disabledPeerSelected: @escaping (EnginePeer) -> Void,
togglePeerSelected: @escaping (EnginePeer) -> Void, togglePeerSelected: @escaping (EnginePeer) -> Void,
togglePeersSelection: @escaping ([PeerEntry], Bool) -> Void, togglePeersSelection: @escaping ([PeerEntry], Bool) -> Void,
@ -795,7 +795,7 @@ public final class ChatListNode: ListView {
if let strongSelf = self, let activateSearch = strongSelf.activateSearch { if let strongSelf = self, let activateSearch = strongSelf.activateSearch {
activateSearch() activateSearch()
} }
}, peerSelected: { [weak self] peer, threadId, _, promoInfo in }, peerSelected: { [weak self] peer, _, threadId, promoInfo in
if let strongSelf = self, let peerSelected = strongSelf.peerSelected { if let strongSelf = self, let peerSelected = strongSelf.peerSelected {
peerSelected(peer, threadId, true, true, promoInfo) peerSelected(peer, threadId, true, true, promoInfo)
} }

View File

@ -149,7 +149,7 @@ final class InstantPagePeerReferenceNode: ASDisplayNode, InstantPageNode {
let context = self.context let context = self.context
let signal = actualizedPeer(postbox: account.postbox, network: account.network, peer: initialPeer) let signal = actualizedPeer(postbox: account.postbox, network: account.network, peer: initialPeer)
|> mapToSignal({ peer -> Signal<Peer, NoError> in |> mapToSignal({ peer -> Signal<Peer, NoError> 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) return .single(peer) |> then(context.engine.peers.resolvePeerByName(name: username)
|> mapToSignal({ updatedPeer -> Signal<Peer, NoError> in |> mapToSignal({ updatedPeer -> Signal<Peer, NoError> in
if let updatedPeer = updatedPeer { if let updatedPeer = updatedPeer {

View File

@ -203,7 +203,7 @@ public class AdditionalLinkItemNode: ListViewItemNode, ItemListItemNode {
let iconColor: UIColor let iconColor: UIColor
if let username = item.username { if let username = item.username {
if username.flags.contains(.isEditable) || username.flags.contains(.isActive) { if username.isActive {
iconColor = item.presentationData.theme.list.itemAccentColor iconColor = item.presentationData.theme.list.itemAccentColor
} else { } else {
iconColor = UIColor(rgb: 0xa8b2bb) iconColor = UIColor(rgb: 0xa8b2bb)
@ -218,7 +218,7 @@ public class AdditionalLinkItemNode: ListViewItemNode, ItemListItemNode {
if let username = item.username { if let username = item.username {
titleText = "@\(username.username)" titleText = "@\(username.username)"
if username.flags.contains(.isEditable) || username.flags.contains(.isActive) { if username.isActive {
subtitleText = item.presentationData.strings.Group_Setup_LinkActive subtitleText = item.presentationData.strings.Group_Setup_LinkActive
subtitleColor = item.presentationData.theme.list.itemAccentColor subtitleColor = item.presentationData.theme.list.itemAccentColor
} else { } 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)) 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) let reorderControlNode = reorderControlSizeAndApply.1(layout.contentSize.height, false, .immediate)
strongSelf.reorderControlNode = reorderControlNode strongSelf.reorderControlNode = reorderControlNode
strongSelf.addSubnode(reorderControlNode) strongSelf.addSubnode(reorderControlNode)
reorderControlNode.alpha = 0.0 reorderControlNode.alpha = 0.0
transition.updateAlpha(node: reorderControlNode, alpha: 1.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 strongSelf.reorderControlNode = nil
reorderControlNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak reorderControlNode] _ in reorderControlNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak reorderControlNode] _ in
reorderControlNode?.removeFromSupernode() reorderControlNode?.removeFromSupernode()

View File

@ -406,7 +406,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
if let phone = peer.phone, !phone.isEmpty { if let phone = peer.phone, !phone.isEmpty {
statusText += formatPhoneNumber(phone) statusText += formatPhoneNumber(phone)
} }
if let username = peer.username, !username.isEmpty { if let username = peer.addressName, !username.isEmpty {
if !statusText.isEmpty { if !statusText.isEmpty {
statusText += "\n" statusText += "\n"
} }

View File

@ -943,14 +943,14 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
} }
} }
let currentAddressName: String let currentUsername: String
if let current = state.editingPublicLinkText { if let current = state.editingPublicLinkText {
currentAddressName = current currentUsername = current
} else { } else {
if let addressName = peer.addressName { if let username = peer.editableUsername {
currentAddressName = addressName currentUsername = username
} else { } else {
currentAddressName = "" currentUsername = ""
} }
} }
@ -1019,7 +1019,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
} else { } else {
switch selectedType { switch selectedType {
case .publicChannel: 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 { if let status = state.addressNameValidationStatus {
let text: String let text: String
switch status { switch status {
@ -1055,7 +1055,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
case let .availability(availability): case let .availability(availability):
switch availability { switch availability {
case .available: case .available:
text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentAddressName).string text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentUsername).string
case .invalid: case .invalid:
text = presentationData.strings.Channel_Username_InvalidCharacters text = presentationData.strings.Channel_Username_InvalidCharacters
case .taken: case .taken:
@ -1208,11 +1208,11 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
selectedType = .privateChannel selectedType = .privateChannel
} }
let currentAddressName: String let currentUsername: String
if let current = state.editingPublicLinkText { if let current = state.editingPublicLinkText {
currentAddressName = current currentUsername = current
} else { } else {
currentAddressName = "" currentUsername = ""
} }
entries.append(.typeHeader(presentationData.theme, presentationData.strings.Group_Setup_TypeHeader.uppercased())) entries.append(.typeHeader(presentationData.theme, presentationData.strings.Group_Setup_TypeHeader.uppercased()))
@ -1228,7 +1228,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
switch selectedType { switch selectedType {
case .publicChannel: case .publicChannel:
entries.append(.editablePublicLink(presentationData.theme, presentationData.strings, "", currentAddressName)) entries.append(.editablePublicLink(presentationData.theme, presentationData.strings, "", currentUsername))
if let status = state.addressNameValidationStatus { if let status = state.addressNameValidationStatus {
let text: String let text: String
switch status { switch status {
@ -1248,7 +1248,7 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
case let .availability(availability): case let .availability(availability):
switch availability { switch availability {
case .available: case .available:
text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentAddressName).string text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentUsername).string
case .invalid: case .invalid:
text = presentationData.strings.Channel_Username_InvalidCharacters text = presentationData.strings.Channel_Username_InvalidCharacters
case .taken: case .taken:
@ -1319,38 +1319,38 @@ private func updatedAddressName(mode: ChannelVisibilityControllerMode, state: Ch
if let peer = peer as? TelegramChannel { if let peer = peer as? TelegramChannel {
let selectedType = effectiveChannelType(mode: mode, state: state, peer: peer, cachedData: cachedData) let selectedType = effectiveChannelType(mode: mode, state: state, peer: peer, cachedData: cachedData)
let currentAddressName: String let currentUsername: String
switch selectedType { switch selectedType {
case .privateChannel: case .privateChannel:
currentAddressName = "" currentUsername = ""
case .publicChannel: case .publicChannel:
if let current = state.editingPublicLinkText { if let current = state.editingPublicLinkText {
currentAddressName = current currentUsername = current
} else { } else {
if let addressName = peer.addressName { if let username = peer.editableUsername {
currentAddressName = addressName currentUsername = username
} else { } else {
currentAddressName = "" currentUsername = ""
} }
} }
} }
if !currentAddressName.isEmpty { if !currentUsername.isEmpty {
if currentAddressName != peer.addressName { if currentUsername != peer.editableUsername {
return currentAddressName return currentUsername
} else { } else {
return nil return nil
} }
} else if peer.addressName != nil { } else if peer.editableUsername != nil {
return "" return ""
} else { } else {
return nil return nil
} }
} else if let _ = peer as? TelegramGroup { } else if let _ = peer as? TelegramGroup {
let currentAddressName = state.editingPublicLinkText ?? "" let currentUsername = state.editingPublicLinkText ?? ""
if !currentAddressName.isEmpty { if !currentUsername.isEmpty {
return currentAddressName return currentUsername
} else { } else {
return nil return nil
} }
@ -2082,7 +2082,7 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
switch entry { switch entry {
case let .additionalLink(_, link, _): case let .additionalLink(_, link, _):
currentUsernames.append(link.username) currentUsernames.append(link.username)
if !link.flags.contains(.isActive) && maxIndex == nil { if !link.isActive && maxIndex == nil {
maxIndex = max(0, i - 1) maxIndex = max(0, i - 1)
} }
i += 1 i += 1
@ -2094,7 +2094,7 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
if toIndex < entries.count { if toIndex < entries.count {
switch entries[toIndex] { switch entries[toIndex] {
case let .additionalLink(_, toUsername, _): case let .additionalLink(_, toUsername, _):
if toUsername.flags.contains(.isActive) { if toUsername.isActive {
referenceId = toUsername.username referenceId = toUsername.username
} else { } else {
afterAll = true afterAll = true

View File

@ -230,7 +230,7 @@ private enum UsernameSetupEntry: ItemListNodeEntry {
case let .additionalLink(_, link, _): case let .additionalLink(_, link, _):
return AdditionalLinkItem(presentationData: presentationData, username: link, sectionId: self.section, style: .blocks, tapAction: { return AdditionalLinkItem(presentationData: presentationData, username: link, sectionId: self.section, style: .blocks, tapAction: {
if !link.flags.contains(.isEditable) { if !link.flags.contains(.isEditable) {
if link.flags.contains(.isActive) { if link.isActive {
arguments.deactivateLink(link.username) arguments.deactivateLink(link.username)
} else { } else {
arguments.activateLink(link.username) arguments.activateLink(link.username)
@ -291,19 +291,19 @@ private func usernameSetupControllerEntries(presentationData: PresentationData,
var entries: [UsernameSetupEntry] = [] var entries: [UsernameSetupEntry] = []
if let peer = view.peers[view.peerId] as? TelegramUser { if let peer = view.peers[view.peerId] as? TelegramUser {
let currentAddressName: String let currentUsername: String
if let current = state.editingPublicLinkText { if let current = state.editingPublicLinkText {
currentAddressName = current currentUsername = current
} else { } else {
if let addressName = peer.addressName { if let username = peer.editableUsername {
currentAddressName = addressName currentUsername = username
} else { } else {
currentAddressName = "" currentUsername = ""
} }
} }
entries.append(.publicLinkHeader(presentationData.theme, presentationData.strings.Username_Username)) 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 { if let status = state.addressNameValidationStatus {
let statusText: String let statusText: String
switch status { switch status {
@ -323,7 +323,7 @@ private func usernameSetupControllerEntries(presentationData: PresentationData,
case let .availability(availability): case let .availability(availability):
switch availability { switch availability {
case .available: case .available:
statusText = presentationData.strings.Username_UsernameIsAvailable(currentAddressName).string statusText = presentationData.strings.Username_UsernameIsAvailable(currentUsername).string
case .invalid: case .invalid:
statusText = presentationData.strings.Username_InvalidCharacters statusText = presentationData.strings.Username_InvalidCharacters
case .taken: case .taken:
@ -332,7 +332,7 @@ private func usernameSetupControllerEntries(presentationData: PresentationData,
case .checking: case .checking:
statusText = presentationData.strings.Username_CheckingUsername 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 var infoText = presentationData.strings.Username_Help
@ -341,7 +341,7 @@ private func usernameSetupControllerEntries(presentationData: PresentationData,
if otherUsernames.isEmpty { if otherUsernames.isEmpty {
infoText += "\n\n" 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 infoText += hintText
} }
entries.append(.publicLinkInfo(presentationData.theme, infoText)) entries.append(.publicLinkInfo(presentationData.theme, infoText))
@ -546,7 +546,7 @@ public func usernameSetupController(context: AccountContext) -> ViewController {
switch entry { switch entry {
case let .additionalLink(_, link, _): case let .additionalLink(_, link, _):
currentUsernames.append(link.username) currentUsernames.append(link.username)
if !link.flags.contains(.isActive) && maxIndex == nil { if !link.isActive && maxIndex == nil {
maxIndex = max(0, i - 1) maxIndex = max(0, i - 1)
} }
i += 1 i += 1
@ -558,7 +558,7 @@ public func usernameSetupController(context: AccountContext) -> ViewController {
if toIndex < entries.count { if toIndex < entries.count {
switch entries[toIndex] { switch entries[toIndex] {
case let .additionalLink(_, toUsername, _): case let .additionalLink(_, toUsername, _):
if toUsername.flags.contains(.isActive) { if toUsername.isActive {
referenceId = toUsername.username referenceId = toUsername.username
} else { } else {
afterAll = true afterAll = true

View File

@ -97,6 +97,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1312568665] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeStickerSet($0) } dict[-1312568665] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeStickerSet($0) }
dict[-421545947] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeTitle($0) } dict[-421545947] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeTitle($0) }
dict[1783299128] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeUsername($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[771095562] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionDefaultBannedRights($0) }
dict[1121994683] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionDeleteMessage($0) } dict[1121994683] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionDeleteMessage($0) }
dict[-610299584] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionDiscardGroupCall($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[889491791] = { return Api.Update.parse_updateDialogFilters($0) }
dict[1852826908] = { return Api.Update.parse_updateDialogPinned($0) } dict[1852826908] = { return Api.Update.parse_updateDialogPinned($0) }
dict[-513517117] = { return Api.Update.parse_updateDialogUnreadMark($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[457133559] = { return Api.Update.parse_updateEditChannelMessage($0) }
dict[-469536605] = { return Api.Update.parse_updateEditMessage($0) } dict[-469536605] = { return Api.Update.parse_updateEditMessage($0) }
dict[386986326] = { return Api.Update.parse_updateEncryptedChatTyping($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[1318109142] = { return Api.Update.parse_updateMessageID($0) }
dict[-1398708869] = { return Api.Update.parse_updateMessagePoll($0) } dict[-1398708869] = { return Api.Update.parse_updateMessagePoll($0) }
dict[274961865] = { return Api.Update.parse_updateMessagePollVote($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[-2030252155] = { return Api.Update.parse_updateMoveStickerSetToTop($0) }
dict[1656358105] = { return Api.Update.parse_updateNewChannelMessage($0) } dict[1656358105] = { return Api.Update.parse_updateNewChannelMessage($0) }
dict[314359194] = { return Api.Update.parse_updateNewEncryptedMessage($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[-2112423005] = { return Api.Update.parse_updateTheme($0) }
dict[8703322] = { return Api.Update.parse_updateTranscribedAudio($0) } dict[8703322] = { return Api.Update.parse_updateTranscribedAudio($0) }
dict[674706841] = { return Api.Update.parse_updateUserEmojiStatus($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[88680979] = { return Api.Update.parse_updateUserPhone($0) }
dict[-232290676] = { return Api.Update.parse_updateUserPhoto($0) } dict[-232290676] = { return Api.Update.parse_updateUserPhoto($0) }
dict[-440534818] = { return Api.Update.parse_updateUserStatus($0) } dict[-440534818] = { return Api.Update.parse_updateUserStatus($0) }

View File

@ -805,7 +805,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum BotCommandScope: TypeConstructorDescription { enum BotCommandScope: TypeConstructorDescription {
case botCommandScopeChatAdmins case botCommandScopeChatAdmins
case botCommandScopeChats case botCommandScopeChats
case botCommandScopeDefault case botCommandScopeDefault

View File

@ -263,7 +263,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum InputStorePaymentPurpose: TypeConstructorDescription { enum InputStorePaymentPurpose: TypeConstructorDescription {
case inputStorePaymentGiftPremium(userId: Api.InputUser, currency: String, amount: Int64) case inputStorePaymentGiftPremium(userId: Api.InputUser, currency: String, amount: Int64)
case inputStorePaymentPremiumSubscription(flags: Int32) case inputStorePaymentPremiumSubscription(flags: Int32)
@ -461,7 +461,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum InputUser: TypeConstructorDescription { enum InputUser: TypeConstructorDescription {
case inputUser(userId: Int64, accessHash: Int64) case inputUser(userId: Int64, accessHash: Int64)
case inputUserEmpty case inputUserEmpty
case inputUserFromMessage(peer: Api.InputPeer, msgId: Int32, userId: Int64) case inputUserFromMessage(peer: Api.InputPeer, msgId: Int32, userId: Int64)

View File

@ -1,5 +1,5 @@
public extension Api { public extension Api {
indirect enum KeyboardButton: TypeConstructorDescription { enum KeyboardButton: TypeConstructorDescription {
case inputKeyboardButtonUrlAuth(flags: Int32, text: String, fwdText: String?, url: String, bot: Api.InputUser) case inputKeyboardButtonUrlAuth(flags: Int32, text: String, fwdText: String?, url: String, bot: Api.InputUser)
case inputKeyboardButtonUserProfile(text: String, userId: Api.InputUser) case inputKeyboardButtonUserProfile(text: String, userId: Api.InputUser)
case keyboardButton(text: String) case keyboardButton(text: String)
@ -757,7 +757,7 @@ public extension Api {
} }
} }
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 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 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?) case messageService(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, replyTo: Api.MessageReplyHeader?, date: Int32, action: Api.MessageAction, ttlPeriod: Int32?)

View File

@ -1,5 +1,5 @@
public extension Api { public extension Api {
indirect enum MessageEntity: TypeConstructorDescription { enum MessageEntity: TypeConstructorDescription {
case inputMessageEntityMentionName(offset: Int32, length: Int32, userId: Api.InputUser) case inputMessageEntityMentionName(offset: Int32, length: Int32, userId: Api.InputUser)
case messageEntityBankCard(offset: Int32, length: Int32) case messageEntityBankCard(offset: Int32, length: Int32)
case messageEntityBlockquote(offset: Int32, length: Int32) case messageEntityBlockquote(offset: Int32, length: Int32)

View File

@ -891,7 +891,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum PageCaption: TypeConstructorDescription { enum PageCaption: TypeConstructorDescription {
case pageCaption(text: Api.RichText, credit: Api.RichText) case pageCaption(text: Api.RichText, credit: Api.RichText)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
@ -935,7 +935,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum PageListItem: TypeConstructorDescription { enum PageListItem: TypeConstructorDescription {
case pageListItemBlocks(blocks: [Api.PageBlock]) case pageListItemBlocks(blocks: [Api.PageBlock])
case pageListItemText(text: Api.RichText) case pageListItemText(text: Api.RichText)

View File

@ -1,5 +1,5 @@
public extension Api { public extension Api {
indirect enum PageListOrderedItem: TypeConstructorDescription { enum PageListOrderedItem: TypeConstructorDescription {
case pageListOrderedItemBlocks(num: String, blocks: [Api.PageBlock]) case pageListOrderedItemBlocks(num: String, blocks: [Api.PageBlock])
case pageListOrderedItemText(num: String, text: Api.RichText) case pageListOrderedItemText(num: String, text: Api.RichText)
@ -135,7 +135,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum PageTableCell: TypeConstructorDescription { enum PageTableCell: TypeConstructorDescription {
case pageTableCell(flags: Int32, text: Api.RichText?, colspan: Int32?, rowspan: Int32?) case pageTableCell(flags: Int32, text: Api.RichText?, colspan: Int32?, rowspan: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {

View File

@ -157,7 +157,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum RecentMeUrl: TypeConstructorDescription { enum RecentMeUrl: TypeConstructorDescription {
case recentMeUrlChat(url: String, chatId: Int64) case recentMeUrlChat(url: String, chatId: Int64)
case recentMeUrlChatInvite(url: String, chatInvite: Api.ChatInvite) case recentMeUrlChatInvite(url: String, chatInvite: Api.ChatInvite)
case recentMeUrlStickerSet(url: String, set: Api.StickerSetCovered) case recentMeUrlStickerSet(url: String, set: Api.StickerSetCovered)

View File

@ -433,7 +433,7 @@ public extension Api {
} }
} }
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]?) 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) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {

View File

@ -555,7 +555,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum ChannelAdminLogEvent: TypeConstructorDescription { enum ChannelAdminLogEvent: TypeConstructorDescription {
case channelAdminLogEvent(id: Int64, date: Int32, userId: Int64, action: Api.ChannelAdminLogEventAction) case channelAdminLogEvent(id: Int64, date: Int32, userId: Int64, action: Api.ChannelAdminLogEventAction)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
@ -605,7 +605,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum ChannelAdminLogEventAction: TypeConstructorDescription { enum ChannelAdminLogEventAction: TypeConstructorDescription {
case channelAdminLogEventActionChangeAbout(prevValue: String, newValue: String) case channelAdminLogEventActionChangeAbout(prevValue: String, newValue: String)
case channelAdminLogEventActionChangeAvailableReactions(prevValue: Api.ChatReactions, newValue: Api.ChatReactions) case channelAdminLogEventActionChangeAvailableReactions(prevValue: Api.ChatReactions, newValue: Api.ChatReactions)
case channelAdminLogEventActionChangeHistoryTTL(prevValue: Int32, newValue: Int32) case channelAdminLogEventActionChangeHistoryTTL(prevValue: Int32, newValue: Int32)
@ -615,6 +615,7 @@ public extension Api {
case channelAdminLogEventActionChangeStickerSet(prevStickerset: Api.InputStickerSet, newStickerset: Api.InputStickerSet) case channelAdminLogEventActionChangeStickerSet(prevStickerset: Api.InputStickerSet, newStickerset: Api.InputStickerSet)
case channelAdminLogEventActionChangeTitle(prevValue: String, newValue: String) case channelAdminLogEventActionChangeTitle(prevValue: String, newValue: String)
case channelAdminLogEventActionChangeUsername(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 channelAdminLogEventActionDefaultBannedRights(prevBannedRights: Api.ChatBannedRights, newBannedRights: Api.ChatBannedRights)
case channelAdminLogEventActionDeleteMessage(message: Api.Message) case channelAdminLogEventActionDeleteMessage(message: Api.Message)
case channelAdminLogEventActionDiscardGroupCall(call: Api.InputGroupCall) case channelAdminLogEventActionDiscardGroupCall(call: Api.InputGroupCall)
@ -708,6 +709,21 @@ public extension Api {
serializeString(prevValue, buffer: buffer, boxed: false) serializeString(prevValue, buffer: buffer, boxed: false)
serializeString(newValue, buffer: buffer, boxed: false) serializeString(newValue, buffer: buffer, boxed: false)
break 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): case .channelAdminLogEventActionDefaultBannedRights(let prevBannedRights, let newBannedRights):
if boxed { if boxed {
buffer.appendInt32(771095562) buffer.appendInt32(771095562)
@ -900,6 +916,8 @@ public extension Api {
return ("channelAdminLogEventActionChangeTitle", [("prevValue", String(describing: prevValue)), ("newValue", String(describing: newValue))]) return ("channelAdminLogEventActionChangeTitle", [("prevValue", String(describing: prevValue)), ("newValue", String(describing: newValue))])
case .channelAdminLogEventActionChangeUsername(let prevValue, let newValue): case .channelAdminLogEventActionChangeUsername(let prevValue, let newValue):
return ("channelAdminLogEventActionChangeUsername", [("prevValue", String(describing: prevValue)), ("newValue", String(describing: 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): case .channelAdminLogEventActionDefaultBannedRights(let prevBannedRights, let newBannedRights):
return ("channelAdminLogEventActionDefaultBannedRights", [("prevBannedRights", String(describing: prevBannedRights)), ("newBannedRights", String(describing: newBannedRights))]) return ("channelAdminLogEventActionDefaultBannedRights", [("prevBannedRights", String(describing: prevBannedRights)), ("newBannedRights", String(describing: newBannedRights))])
case .channelAdminLogEventActionDeleteMessage(let message): case .channelAdminLogEventActionDeleteMessage(let message):
@ -1099,6 +1117,24 @@ public extension Api {
return nil 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? { public static func parse_channelAdminLogEventActionDefaultBannedRights(_ reader: BufferReader) -> ChannelAdminLogEventAction? {
var _1: Api.ChatBannedRights? var _1: Api.ChatBannedRights?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {

View File

@ -653,7 +653,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum Update: TypeConstructorDescription { enum Update: TypeConstructorDescription {
case updateAttachMenuBots case updateAttachMenuBots
case updateBotCallbackQuery(flags: Int32, queryId: Int64, userId: Int64, peer: Api.Peer, msgId: Int32, chatInstance: Int64, data: Buffer?, gameShortName: String?) 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) 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 updateDialogFilters
case updateDialogPinned(flags: Int32, folderId: Int32?, peer: Api.DialogPeer) case updateDialogPinned(flags: Int32, folderId: Int32?, peer: Api.DialogPeer)
case updateDialogUnreadMark(flags: 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 updateEditChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32)
case updateEditMessage(message: Api.Message, pts: Int32, ptsCount: Int32) case updateEditMessage(message: Api.Message, pts: Int32, ptsCount: Int32)
case updateEncryptedChatTyping(chatId: Int32) case updateEncryptedChatTyping(chatId: Int32)
@ -715,7 +715,7 @@ public extension Api {
case updateMessageID(id: Int32, randomId: Int64) case updateMessageID(id: Int32, randomId: Int64)
case updateMessagePoll(flags: Int32, pollId: Int64, poll: Api.Poll?, results: Api.PollResults) case updateMessagePoll(flags: Int32, pollId: Int64, poll: Api.Poll?, results: Api.PollResults)
case updateMessagePollVote(pollId: Int64, userId: Int64, options: [Buffer], qts: Int32) 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 updateMoveStickerSetToTop(flags: Int32, stickerset: Int64)
case updateNewChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32) case updateNewChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32)
case updateNewEncryptedMessage(message: Api.EncryptedMessage, qts: Int32) case updateNewEncryptedMessage(message: Api.EncryptedMessage, qts: Int32)
@ -755,7 +755,7 @@ public extension Api {
case updateTheme(theme: Api.Theme) case updateTheme(theme: Api.Theme)
case updateTranscribedAudio(flags: Int32, peer: Api.Peer, msgId: Int32, transcriptionId: Int64, text: String) case updateTranscribedAudio(flags: Int32, peer: Api.Peer, msgId: Int32, transcriptionId: Int64, text: String)
case updateUserEmojiStatus(userId: Int64, emojiStatus: Api.EmojiStatus) 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 updateUserPhone(userId: Int64, phone: String)
case updateUserPhoto(userId: Int64, date: Int32, photo: Api.UserProfilePhoto, previous: Api.Bool) case updateUserPhoto(userId: Int64, date: Int32, photo: Api.UserProfilePhoto, previous: Api.Bool)
case updateUserStatus(userId: Int64, status: Api.UserStatus) case updateUserStatus(userId: Int64, status: Api.UserStatus)
@ -1139,11 +1139,13 @@ public extension Api {
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true) peer.serialize(buffer, true)
break break
case .updateDraftMessage(let peer, let draft): case .updateDraftMessage(let flags, let peer, let topMsgId, let draft):
if boxed { if boxed {
buffer.appendInt32(-299124375) buffer.appendInt32(457829485)
} }
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true) peer.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)}
draft.serialize(buffer, true) draft.serialize(buffer, true)
break break
case .updateEditChannelMessage(let message, let pts, let ptsCount): case .updateEditChannelMessage(let message, let pts, let ptsCount):
@ -1301,12 +1303,14 @@ public extension Api {
} }
serializeInt32(qts, buffer: buffer, boxed: false) serializeInt32(qts, buffer: buffer, boxed: false)
break break
case .updateMessageReactions(let peer, let msgId, let reactions): case .updateMessageReactions(let flags, let peer, let msgId, let topMsgId, let reactions):
if boxed { if boxed {
buffer.appendInt32(357013699) buffer.appendInt32(1578843320)
} }
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true) peer.serialize(buffer, true)
serializeInt32(msgId, buffer: buffer, boxed: false) serializeInt32(msgId, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)}
reactions.serialize(buffer, true) reactions.serialize(buffer, true)
break break
case .updateMoveStickerSetToTop(let flags, let stickerset): case .updateMoveStickerSetToTop(let flags, let stickerset):
@ -1639,14 +1643,18 @@ public extension Api {
serializeInt64(userId, buffer: buffer, boxed: false) serializeInt64(userId, buffer: buffer, boxed: false)
emojiStatus.serialize(buffer, true) emojiStatus.serialize(buffer, true)
break break
case .updateUserName(let userId, let firstName, let lastName, let username): case .updateUserName(let userId, let firstName, let lastName, let usernames):
if boxed { if boxed {
buffer.appendInt32(-1007549728) buffer.appendInt32(-1484486364)
} }
serializeInt64(userId, buffer: buffer, boxed: false) serializeInt64(userId, buffer: buffer, boxed: false)
serializeString(firstName, buffer: buffer, boxed: false) serializeString(firstName, buffer: buffer, boxed: false)
serializeString(lastName, 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 break
case .updateUserPhone(let userId, let phone): case .updateUserPhone(let userId, let phone):
if boxed { if boxed {
@ -1779,8 +1787,8 @@ public extension Api {
return ("updateDialogPinned", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("peer", String(describing: peer))]) return ("updateDialogPinned", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("peer", String(describing: peer))])
case .updateDialogUnreadMark(let flags, let peer): case .updateDialogUnreadMark(let flags, let peer):
return ("updateDialogUnreadMark", [("flags", String(describing: flags)), ("peer", String(describing: peer))]) return ("updateDialogUnreadMark", [("flags", String(describing: flags)), ("peer", String(describing: peer))])
case .updateDraftMessage(let peer, let draft): case .updateDraftMessage(let flags, let peer, let topMsgId, let draft):
return ("updateDraftMessage", [("peer", String(describing: peer)), ("draft", String(describing: 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): case .updateEditChannelMessage(let message, let pts, let ptsCount):
return ("updateEditChannelMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) return ("updateEditChannelMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))])
case .updateEditMessage(let message, let pts, let 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))]) 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): 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))]) 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): case .updateMessageReactions(let flags, let peer, let msgId, let topMsgId, let reactions):
return ("updateMessageReactions", [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("reactions", String(describing: 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): case .updateMoveStickerSetToTop(let flags, let stickerset):
return ("updateMoveStickerSetToTop", [("flags", String(describing: flags)), ("stickerset", String(describing: stickerset))]) return ("updateMoveStickerSetToTop", [("flags", String(describing: flags)), ("stickerset", String(describing: stickerset))])
case .updateNewChannelMessage(let message, let pts, let ptsCount): 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))]) 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): case .updateUserEmojiStatus(let userId, let emojiStatus):
return ("updateUserEmojiStatus", [("userId", String(describing: userId)), ("emojiStatus", String(describing: emojiStatus))]) return ("updateUserEmojiStatus", [("userId", String(describing: userId)), ("emojiStatus", String(describing: emojiStatus))])
case .updateUserName(let userId, let firstName, let lastName, let 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)), ("username", String(describing: username))]) return ("updateUserName", [("userId", String(describing: userId)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("usernames", String(describing: usernames))])
case .updateUserPhone(let userId, let phone): case .updateUserPhone(let userId, let phone):
return ("updateUserPhone", [("userId", String(describing: userId)), ("phone", String(describing: phone))]) return ("updateUserPhone", [("userId", String(describing: userId)), ("phone", String(describing: phone))])
case .updateUserPhoto(let userId, let date, let photo, let previous): 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? { 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() { 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() { 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 _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
if _c1 && _c2 { let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
return Api.Update.updateDraftMessage(peer: _1!, draft: _2!) let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.Update.updateDraftMessage(flags: _1!, peer: _2!, topMsgId: _3, draft: _4!)
} }
else { else {
return nil return nil
@ -3046,21 +3060,27 @@ public extension Api {
} }
} }
public static func parse_updateMessageReactions(_ reader: BufferReader) -> Update? { 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() { 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? var _3: Int32?
_2 = reader.readInt32() _3 = reader.readInt32()
var _3: Api.MessageReactions? var _4: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt32() }
var _5: Api.MessageReactions?
if let signature = reader.readInt32() { 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 _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = _3 != nil
if _c1 && _c2 && _c3 { let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
return Api.Update.updateMessageReactions(peer: _1!, msgId: _2!, reactions: _3!) 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 { else {
return nil return nil
@ -3680,14 +3700,16 @@ public extension Api {
_2 = parseString(reader) _2 = parseString(reader)
var _3: String? var _3: String?
_3 = parseString(reader) _3 = parseString(reader)
var _4: String? var _4: [Api.Username]?
_4 = parseString(reader) if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Username.self)
}
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
let _c3 = _3 != nil let _c3 = _3 != nil
let _c4 = _4 != nil let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 { 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 { else {
return nil return nil

View File

@ -1,5 +1,5 @@
public extension Api { public extension Api {
indirect enum Updates: TypeConstructorDescription { enum Updates: TypeConstructorDescription {
case updateShort(update: Api.Update, date: Int32) 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 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?) 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?)

View File

@ -1291,7 +1291,7 @@ public extension Api.payments {
} }
} }
public extension Api.payments { public extension Api.payments {
indirect enum PaymentResult: TypeConstructorDescription { enum PaymentResult: TypeConstructorDescription {
case paymentResult(updates: Api.Updates) case paymentResult(updates: Api.Updates)
case paymentVerificationNeeded(url: String) case paymentVerificationNeeded(url: String)

View File

@ -5741,11 +5741,12 @@ public extension Api.functions.messages {
} }
} }
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<Api.Bool>) { static func saveDraft(flags: Int32, replyToMsgId: Int32?, topMsgId: Int32?, peer: Api.InputPeer, message: String, entities: [Api.MessageEntity]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer() let buffer = Buffer()
buffer.appendInt32(-1137057461) buffer.appendInt32(-1271718337)
serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, 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) peer.serialize(buffer, true)
serializeString(message, buffer: buffer, boxed: false) serializeString(message, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261)
@ -5753,7 +5754,7 @@ public extension Api.functions.messages {
for item in entities! { for item in entities! {
item.serialize(buffer, true) 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) let reader = BufferReader(buffer)
var result: Api.Bool? var result: Api.Bool?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {

View File

@ -521,7 +521,7 @@ public extension Api {
} }
} }
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 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 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?) 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 { 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 chatInvite(flags: Int32, title: String, about: String?, photo: Api.Photo, participantsCount: Int32, participants: [Api.User]?)
case chatInviteAlready(chat: Api.Chat) case chatInviteAlready(chat: Api.Chat)
case chatInvitePeek(chat: Api.Chat, expires: Int32) case chatInvitePeek(chat: Api.Chat, expires: Int32)

View File

@ -1,5 +1,5 @@
public extension Api { public extension Api {
indirect enum InputChannel: TypeConstructorDescription { enum InputChannel: TypeConstructorDescription {
case inputChannel(channelId: Int64, accessHash: Int64) case inputChannel(channelId: Int64, accessHash: Int64)
case inputChannelEmpty case inputChannelEmpty
case inputChannelFromMessage(peer: Api.InputPeer, msgId: Int32, channelId: Int64) case inputChannelFromMessage(peer: Api.InputPeer, msgId: Int32, channelId: Int64)
@ -311,7 +311,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum InputDialogPeer: TypeConstructorDescription { enum InputDialogPeer: TypeConstructorDescription {
case inputDialogPeer(peer: Api.InputPeer) case inputDialogPeer(peer: Api.InputPeer)
case inputDialogPeerFolder(folderId: Int32) case inputDialogPeerFolder(folderId: Int32)
@ -653,7 +653,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum InputFileLocation: TypeConstructorDescription { enum InputFileLocation: TypeConstructorDescription {
case inputDocumentFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String) case inputDocumentFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String)
case inputEncryptedFileLocation(id: Int64, accessHash: Int64) case inputEncryptedFileLocation(id: Int64, accessHash: Int64)
case inputFileLocation(volumeId: Int64, localId: Int32, secret: Int64, fileReference: Buffer) case inputFileLocation(volumeId: Int64, localId: Int32, secret: Int64, fileReference: Buffer)
@ -963,7 +963,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum InputFolderPeer: TypeConstructorDescription { enum InputFolderPeer: TypeConstructorDescription {
case inputFolderPeer(peer: Api.InputPeer, folderId: Int32) case inputFolderPeer(peer: Api.InputPeer, folderId: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {

View File

@ -1,5 +1,5 @@
public extension Api { public extension Api {
indirect enum InputGame: TypeConstructorDescription { enum InputGame: TypeConstructorDescription {
case inputGameID(id: Int64, accessHash: Int64) case inputGameID(id: Int64, accessHash: Int64)
case inputGameShortName(botId: Api.InputUser, shortName: String) case inputGameShortName(botId: Api.InputUser, shortName: String)
@ -165,7 +165,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum InputInvoice: TypeConstructorDescription { enum InputInvoice: TypeConstructorDescription {
case inputInvoiceMessage(peer: Api.InputPeer, msgId: Int32) case inputInvoiceMessage(peer: Api.InputPeer, msgId: Int32)
case inputInvoiceSlug(slug: String) case inputInvoiceSlug(slug: String)
@ -857,7 +857,7 @@ public extension Api {
} }
} }
public extension Api { public extension Api {
indirect enum InputNotifyPeer: TypeConstructorDescription { enum InputNotifyPeer: TypeConstructorDescription {
case inputNotifyBroadcasts case inputNotifyBroadcasts
case inputNotifyChats case inputNotifyChats
case inputNotifyForumTopic(peer: Api.InputPeer, topMsgId: Int32) case inputNotifyForumTopic(peer: Api.InputPeer, topMsgId: Int32)

View File

@ -781,7 +781,7 @@ public extension Api {
} }
} }
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]?) case inputSingleMedia(flags: Int32, media: Api.InputMedia, randomId: Int64, message: String, entities: [Api.MessageEntity]?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {

View File

@ -125,7 +125,7 @@ private func peerIdsRequiringLocalChatStateFromUpdates(_ updates: [Api.Update])
peerIds.insert(PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))) peerIds.insert(PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)))
case let .updateReadHistoryInbox(_, _, peer, _, _, _, _): case let .updateReadHistoryInbox(_, _, peer, _, _, _, _):
peerIds.insert(peer.peerId) peerIds.insert(peer.peerId)
case let .updateDraftMessage(peer, draft): case let .updateDraftMessage(_, peer, _, draft):
switch draft { switch draft {
case .draftMessage: case .draftMessage:
peerIds.insert(peer.peerId) peerIds.insert(peer.peerId)
@ -1236,11 +1236,11 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
}) })
case let .updateUserStatus(userId, status): case let .updateUserStatus(userId, status):
updatedState.mergePeerPresences([PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)): status], explicit: true) 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 //TODO add contact checking for apply first and last name
updatedState.updatePeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), { peer in updatedState.updatePeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), { peer in
if let user = peer as? TelegramUser { if let user = peer as? TelegramUser {
return user.withUpdatedUsername(username) return user.withUpdatedUsernames(usernames.map { TelegramPeerUsername(apiUsername: $0) })
} else { } else {
return peer return peer
} }
@ -1410,7 +1410,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
updatedState.addUpdateInstalledStickerPacks(.sync) updatedState.addUpdateInstalledStickerPacks(.sync)
case .updateSavedGifs: case .updateSavedGifs:
updatedState.addUpdateRecentGifs() updatedState.addUpdateRecentGifs()
case let .updateDraftMessage(peer, draft): case let .updateDraftMessage(_, peer, _, draft):
let inputState: SynchronizeableChatInputState? let inputState: SynchronizeableChatInputState?
switch draft { switch draft {
case .draftMessageEmpty: case .draftMessageEmpty:
@ -1551,7 +1551,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
return current 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) updatedState.updateMessageReactions(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: msgId), reactions: reactions, eventTimestamp: updatesDate)
case .updateAttachMenuBots: case .updateAttachMenuBots:
updatedState.addUpdateAttachMenuBots() updatedState.addUpdateAttachMenuBots()

View File

@ -858,7 +858,7 @@ public final class AccountViewTracker {
} }
for update in updateList { for update in updateList {
switch update { 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 transaction.updateMessage(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: msgId), update: { currentMessage in
var updatedReactions = ReactionsMessageAttribute(apiReactions: reactions) var updatedReactions = ReactionsMessageAttribute(apiReactions: reactions)

View File

@ -141,14 +141,14 @@ private func synchronizeChatInputState(transaction: Transaction, postbox: Postbo
flags |= (1 << 3) 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()))) 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()) |> delay(2.0, queue: Queue.concurrentDefaultQueue())
|> `catch` { _ -> Signal<Api.Bool, NoError> in |> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse) return .single(.boolFalse)
} }
|> mapToSignal { _ -> Signal<Void, NoError> in |> mapToSignal { _ -> Signal<Void, NoError> in
return .complete() return .complete()
} }
} else { } else {
return .complete() return .complete()
} }

View File

@ -296,7 +296,7 @@ extension Api.Update {
} else { } else {
return [] return []
} }
case let .updateDraftMessage(peer: peer, draft: _): case let .updateDraftMessage(_, peer, _, _):
return [peer.peerId] return [peer.peerId]
case let .updateNewScheduledMessage(message): case let .updateNewScheduledMessage(message):
return apiMessagePeerIds(message) return apiMessagePeerIds(message)

View File

@ -26,7 +26,7 @@ func _internal_clearCloudDraftsInteractively(postbox: Postbox, network: Network,
} }
for update in updates { for update in updates {
switch update { switch update {
case let .updateDraftMessage(peer, _): case let .updateDraftMessage(_, peer, _, _):
peerIds.insert(peer.peerId) peerIds.insert(peer.peerId)
default: default:
break break
@ -42,7 +42,7 @@ func _internal_clearCloudDraftsInteractively(postbox: Postbox, network: Network,
_internal_updateChatInputState(transaction: transaction, peerId: peerId, inputState: nil) _internal_updateChatInputState(transaction: transaction, peerId: peerId, inputState: nil)
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { 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<Api.Bool, NoError> in |> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse) return .single(.boolFalse)
} }

View File

@ -303,7 +303,7 @@ func _internal_reorderAddressNames(account: Account, domain: AddressNameDomain,
return account.postbox.transaction { transaction -> Signal<Void, ReorderAddressNamesError> in return account.postbox.transaction { transaction -> Signal<Void, ReorderAddressNamesError> in
switch domain { switch domain {
case .account: 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 |> mapError { _ -> ReorderAddressNamesError in
return .generic return .generic
} }
@ -319,7 +319,7 @@ func _internal_reorderAddressNames(account: Account, domain: AddressNameDomain,
} }
case let .peer(peerId): case let .peer(peerId):
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) { 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 |> mapError { _ -> ReorderAddressNamesError in
return .generic return .generic
} }

View File

@ -68,6 +68,7 @@ public enum AdminLogEventAction {
case toggleCopyProtection(Bool) case toggleCopyProtection(Bool)
case sendMessage(Message) case sendMessage(Message)
case changeAvailableReactions(previousValue: PeerAllowedReactions, updatedValue: PeerAllowedReactions) case changeAvailableReactions(previousValue: PeerAllowedReactions, updatedValue: PeerAllowedReactions)
case changeUsernames(prev: [String], new: [String])
} }
public enum ChannelAdminLogEventError { public enum ChannelAdminLogEventError {
@ -265,6 +266,8 @@ func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, m
} }
case let .channelAdminLogEventActionChangeAvailableReactions(prevValue, newValue): case let .channelAdminLogEventActionChangeAvailableReactions(prevValue, newValue):
action = .changeAvailableReactions(previousValue: PeerAllowedReactions(apiReactions: prevValue), updatedValue: PeerAllowedReactions(apiReactions: 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)) let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
if let action = action { if let action = action {

View File

@ -7,7 +7,7 @@ private final class LinkHelperClass: NSObject {
} }
public func canSendMessagesToPeer(_ peer: Peer) -> Bool { 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 return false
} else if peer is TelegramUser || peer is TelegramGroup { } else if peer is TelegramUser || peer is TelegramGroup {
return !peer.isDeleted return !peer.isDeleted

View File

@ -41,19 +41,20 @@ public extension Peer {
return nil return nil
} }
} }
var addressName: String? { var addressName: String? {
switch self { switch self {
case let user as TelegramUser: case let user as TelegramUser:
return user.username return user.usernames.first(where: { $0.isActive }).map { $0.username } ?? user.username
case _ as TelegramGroup: case _ as TelegramGroup:
return nil return nil
case let channel as TelegramChannel: case let channel as TelegramChannel:
return channel.username return channel.usernames.first(where: { $0.isActive }).map { $0.username } ?? channel.username
default: default:
return nil return nil
} }
} }
var usernames: [TelegramPeerUsername] { var usernames: [TelegramPeerUsername] {
switch self { switch self {
case let user as TelegramUser: 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] { var displayLetters: [String] {
switch self { switch self {
case let user as TelegramUser: 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 { public extension PeerId {
var isGroupOrChannel: Bool { var isGroupOrChannel: Bool {
switch self.namespace { switch self.namespace {

View File

@ -10980,7 +10980,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
canClearForEveryone = nil canClearForEveryone = nil
} }
} else if let channel = chatPeer as? TelegramChannel { } else if let channel = chatPeer as? TelegramChannel {
if let username = channel.username, !username.isEmpty { if let username = channel.addressName, !username.isEmpty {
if isLargeGroupOrChannel { if isLargeGroupOrChannel {
canClearCache = true canClearCache = true
canClearForMyself = nil canClearForMyself = nil
@ -15486,7 +15486,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
self.chatDisplayNode.dismissInput() 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) let actionSheet = ActionSheetController(presentationData: self.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []

View File

@ -84,7 +84,7 @@ private func peerButtons(_ peer: Peer, interfaceState: ChatPresentationInterface
buttons.append(.info) buttons.append(.info)
return buttons return buttons
} else if let channel = peer as? TelegramChannel { } 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] return [.search, muteAction, infoButton]
} else { } else {
return [.search, .report, muteAction, infoButton] return [.search, .report, muteAction, infoButton]

View File

@ -1145,7 +1145,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
if let attribute = attribute as? InlineBotMessageAttribute { if let attribute = attribute as? InlineBotMessageAttribute {
var inlineBotNameString: String? var inlineBotNameString: String?
if let peerId = attribute.peerId, let bot = item.message.peers[peerId] as? TelegramUser { if let peerId = attribute.peerId, let bot = item.message.peers[peerId] as? TelegramUser {
inlineBotNameString = bot.username inlineBotNameString = bot.addressName
} else { } else {
inlineBotNameString = attribute.title inlineBotNameString = attribute.title
} }
@ -1983,7 +1983,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
if let item = self.item, let forwardInfo = item.message.forwardInfo { if let item = self.item, let forwardInfo = item.message.forwardInfo {
let performAction: () -> Void = { let performAction: () -> Void = {
if let sourceMessageId = forwardInfo.sourceMessageId { 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) { if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) {
} else if case .member = channel.participationStatus { } else if case .member = channel.participationStatus {
} else { } else {

View File

@ -1412,7 +1412,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
for attribute in firstMessage.attributes { for attribute in firstMessage.attributes {
if let attribute = attribute as? InlineBotMessageAttribute { if let attribute = attribute as? InlineBotMessageAttribute {
if let peerId = attribute.peerId, let bot = firstMessage.peers[peerId] as? TelegramUser { if let peerId = attribute.peerId, let bot = firstMessage.peers[peerId] as? TelegramUser {
inlineBotNameString = bot.username inlineBotNameString = bot.addressName
} else { } else {
inlineBotNameString = attribute.title inlineBotNameString = attribute.title
} }
@ -3363,7 +3363,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
if let item = self.item, let forwardInfo = item.message.forwardInfo { if let item = self.item, let forwardInfo = item.message.forwardInfo {
let performAction: () -> Void = { let performAction: () -> Void = {
if let sourceMessageId = forwardInfo.sourceMessageId { 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) { if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) {
} else if case .member = channel.participationStatus { } else if case .member = channel.participationStatus {
} else if !item.message.id.peerId.isReplies { } else if !item.message.id.peerId.isReplies {

View File

@ -184,7 +184,7 @@ class ChatMessageForwardInfoNode: ASDisplayNode {
var currentCredibilityIconImage: UIImage? var currentCredibilityIconImage: UIImage?
var highlight = true var highlight = true
if let peer = peer { 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) { if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) {
} else if case .member = channel.participationStatus { } else if case .member = channel.participationStatus {
} else { } else {

View File

@ -424,7 +424,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
if let attribute = attribute as? InlineBotMessageAttribute { if let attribute = attribute as? InlineBotMessageAttribute {
var inlineBotNameString: String? var inlineBotNameString: String?
if let peerId = attribute.peerId, let bot = item.message.peers[peerId] as? TelegramUser { if let peerId = attribute.peerId, let bot = item.message.peers[peerId] as? TelegramUser {
inlineBotNameString = bot.username inlineBotNameString = bot.addressName
} else { } else {
inlineBotNameString = attribute.title inlineBotNameString = attribute.title
} }
@ -918,7 +918,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
if let item = self.item, let forwardInfo = item.message.forwardInfo { if let item = self.item, let forwardInfo = item.message.forwardInfo {
let performAction: () -> Void = { let performAction: () -> Void = {
if let sourceMessageId = forwardInfo.sourceMessageId { 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) { if case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) {
} else if case .member = channel.participationStatus { } else if case .member = channel.participationStatus {
} else { } else {

View File

@ -590,7 +590,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
if let attribute = attribute as? InlineBotMessageAttribute { if let attribute = attribute as? InlineBotMessageAttribute {
var inlineBotNameString: String? var inlineBotNameString: String?
if let peerId = attribute.peerId, let bot = item.message.peers[peerId] as? TelegramUser { if let peerId = attribute.peerId, let bot = item.message.peers[peerId] as? TelegramUser {
inlineBotNameString = bot.username inlineBotNameString = bot.addressName
} else { } else {
inlineBotNameString = attribute.title inlineBotNameString = attribute.title
} }

View File

@ -200,6 +200,56 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
attributes.append(TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< text.count, type: .Italic)])) 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<PeerId, Peer>()
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 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: [:]) 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) 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)

View File

@ -228,8 +228,8 @@ public func isOverlayControllerForChatNotificationOverlayPresentation(_ controll
return false return false
} }
public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal<Never, NoError> { public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal<Never, NoError> {
return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: nil, preload: false) return fetchAndPreloadReplyThreadInfo(context: context, subject: .groupMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))), atMessageId: messageId, preload: false)
|> deliverOnMainQueue |> deliverOnMainQueue
|> beforeNext { [weak context, weak navigationController] result in |> beforeNext { [weak context, weak navigationController] result in
guard let context = context, let navigationController = navigationController else { 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 chatLocation: ChatLocation = .replyThread(message: result.message)
let subject: ChatControllerSubject? 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 var actualActivateInput: ChatControllerActivateInput? = result.isEmpty ? .text : nil
if let activateInput = activateInput { if let activateInput = activateInput {

View File

@ -2614,8 +2614,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
if self.isSettings, let user = peer as? TelegramUser { if self.isSettings, let user = peer as? TelegramUser {
var subtitle = formatPhoneNumber(user.phone ?? "") var subtitle = formatPhoneNumber(user.phone ?? "")
let mainUsername = user.usernames.first(where: { $0.flags.contains(.isActive) })?.username ?? user.username if let mainUsername = user.addressName, !mainUsername.isEmpty {
if let mainUsername = mainUsername, !mainUsername.isEmpty {
subtitle = "\(subtitle) • @\(mainUsername)" subtitle = "\(subtitle) • @\(mainUsername)"
} }
smallSubtitleString = NSAttributedString(string: subtitle, font: Font.regular(15.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.7)) smallSubtitleString = NSAttributedString(string: subtitle, font: Font.regular(15.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.7))

View File

@ -956,10 +956,9 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
interaction.requestLayout(false) interaction.requestLayout(false)
})) }))
} }
if let username = user.username { if let mainUsername = user.addressName {
let mainUsername = user.usernames.first(where: { $0.flags.contains(.isActive) })?.username ?? username
var additionalUsernames: String? 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 { if !usernames.isEmpty {
additionalUsernames = presentationData.strings.Profile_AdditionalUsernames(String(usernames.map { "@\($0.username)" }.joined(separator: ", "))).string 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, textColor: .accent,
icon: .qrCode, icon: .qrCode,
action: { _ in action: { _ in
interaction.openUsername(username) interaction.openUsername(mainUsername)
}, longTapAction: { sourceNode in }, longTapAction: { sourceNode in
interaction.openPeerInfoContextMenu(.link(customLink: nil), sourceNode, nil) interaction.openPeerInfoContextMenu(.link(customLink: nil), sourceNode, nil)
}, linkItemAction: { type, item, _, _ in }, 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? var additionalUsernames: String?
let mainUsername = channel.usernames.first(where: { $0.flags.contains(.isActive) })?.username ?? username let usernames = channel.usernames.filter { $0.isActive && $0.username != mainUsername }
let usernames = channel.usernames.filter { $0.flags.contains(.isActive) && $0.username != mainUsername }
if !usernames.isEmpty { if !usernames.isEmpty {
additionalUsernames = presentationData.strings.Profile_AdditionalUsernames(String(usernames.map { "@\($0.username)" }.joined(separator: ", "))).string 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, textColor: .accent,
icon: .qrCode, icon: .qrCode,
action: { _ in action: { _ in
interaction.openUsername(username) interaction.openUsername(mainUsername)
}, longTapAction: { sourceNode in }, longTapAction: { sourceNode in
interaction.openPeerInfoContextMenu(.link(customLink: nil), sourceNode, nil) interaction.openPeerInfoContextMenu(.link(customLink: nil), sourceNode, nil)
}, linkItemAction: { type, item, sourceNode, sourceRect in }, linkItemAction: { type, item, sourceNode, sourceRect in
@ -1350,7 +1347,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
if isCreator { if isCreator {
let linkText: String let linkText: String
if let _ = channel.username { if let _ = channel.addressName {
linkText = presentationData.strings.Channel_Setup_TypePublic linkText = presentationData.strings.Channel_Setup_TypePublic
} else { } else {
linkText = presentationData.strings.Channel_Setup_TypePrivate 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 let invitesText: String
if let count = data.invitations?.count, count > 0 { if let count = data.invitations?.count, count > 0 {
invitesText = "\(count)" invitesText = "\(count)"
@ -1488,7 +1485,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
let ItemTopics = 116 let ItemTopics = 116
let isCreator = channel.flags.contains(.isCreator) let isCreator = channel.flags.contains(.isCreator)
let isPublic = channel.username != nil let isPublic = channel.addressName != nil
if let cachedData = data.cachedData as? CachedChannelData { if let cachedData = data.cachedData as? CachedChannelData {
if isCreator, let location = cachedData.peerGeoLocation { if isCreator, let location = cachedData.peerGeoLocation {
@ -1515,7 +1512,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
if cachedData.peerGeoLocation != nil { if cachedData.peerGeoLocation != nil {
if isCreator { if isCreator {
let linkText: String let linkText: String
if let username = channel.username { if let username = channel.addressName {
linkText = "@\(username)" linkText = "@\(username)"
} else { } else {
linkText = presentationData.strings.GroupInfo_PublicLinkAdd 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 let invitesText: String
if let count = data.invitations?.count, count > 0 { if let count = data.invitations?.count, count > 0 {
invitesText = "\(count)" 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 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)" UIPasteboard.general.string = "@\(username)"
@ -4268,7 +4265,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
if let _ = user.botInfo { if let _ = user.botInfo {
if user.username != nil { if user.addressName != nil {
items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_ShareBot, icon: { theme in items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_ShareBot, icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in }, action: { [weak self] _, f in
@ -5827,7 +5824,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
guard let strongSelf = self else { guard let strongSelf = self else {
return 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) let shareController = ShareController(context: strongSelf.context, subject: .url("https://t.me/\(username)"), updatedPresentationData: strongSelf.controller?.updatedPresentationData)
shareController.completed = { [weak self] peerIds in shareController.completed = { [weak self] peerIds in
guard let strongSelf = self else { guard let strongSelf = self else {
@ -9585,7 +9582,7 @@ struct ClearPeerHistory {
var canDeleteLocally = true var canDeleteLocally = true
if case .broadcast = channel.info { if case .broadcast = channel.info {
canDeleteLocally = false canDeleteLocally = false
} else if channel.username != nil { } else if channel.addressName != nil {
canDeleteLocally = false canDeleteLocally = false
} }

View File

@ -600,7 +600,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
location: .chatList(groupId: EngineChatList.Group(.root)), location: .chatList(groupId: EngineChatList.Group(.root)),
displaySearchFilters: false, displaySearchFilters: false,
hasDownloads: false, hasDownloads: false,
openPeer: { [weak self] peer, chatPeer, _ in openPeer: { [weak self] peer, chatPeer, _, _ in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }

View File

@ -1159,8 +1159,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
navigateToForumChannelImpl(context: context, peerId: peerId, navigationController: navigationController) navigateToForumChannelImpl(context: context, peerId: peerId, navigationController: navigationController)
} }
public func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal<Never, NoError> { public func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?) -> Signal<Never, NoError> {
return navigateToForumThreadImpl(context: context, peerId: peerId, threadId: threadId, navigationController: navigationController, activateInput: activateInput) return navigateToForumThreadImpl(context: context, peerId: peerId, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: activateInput)
} }
public func openStorageUsage(context: AccountContext) { public func openStorageUsage(context: AccountContext) {