From 93a7f7ece862b5626842c664d542171fb83d54c0 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 23 Oct 2022 18:03:26 +0400 Subject: [PATCH] [WIP] Topics --- .../Sources/NotificationService.swift | 1 + .../Sources/AccountContext.swift | 36 +- .../ChatListUI/Sources/ChatContextMenus.swift | 27 +- .../Sources/ChatListController.swift | 12 +- .../Sources/ChatListSearchListPaneNode.swift | 4 +- .../Sources/Node/ChatListItem.swift | 10 +- .../Sources/Node/ChatListNodeEntries.swift | 4 +- .../ChatPresentationInterfaceState.swift | 6 +- .../Sources/ContactContextMenus.swift | 46 ++- .../Sources/ContactsController.swift | 2 +- .../Sources/HashtagSearchController.swift | 4 +- .../Sources/InstantPageController.swift | 2 +- .../Sources/InstantPageControllerNode.swift | 12 +- .../Sources/InviteLinkViewController.swift | 13 +- .../Sources/InviteRequestsController.swift | 2 +- .../Sources/ChannelBlacklistController.swift | 2 +- ...hannelDiscussionGroupSetupController.swift | 15 +- .../ChannelPermissionsController.swift | 12 +- .../Sources/ChannelVisibilityController.swift | 41 ++- .../Sources/DeviceContactInfoController.swift | 13 +- .../GroupStickerPackSetupController.swift | 13 +- .../Sources/PeersNearbyController.swift | 2 +- submodules/Postbox/Sources/Postbox.swift | 7 +- .../Sources/UnreadMessageCountsView.swift | 27 +- .../QrCodeUI/Sources/QrCodeScanScreen.swift | 2 +- .../DeleteAccountOptionsController.swift | 15 +- .../Sources/LogoutOptionsController.swift | 15 +- .../InstalledStickerPacksController.swift | 13 +- .../Sources/ThemePickerController.swift | 84 +++-- .../Themes/ThemeSettingsController.swift | 60 +++- .../Sources/ChannelStatsController.swift | 13 +- .../Sources/GroupStatsController.swift | 13 +- .../Sources/MessageStatsController.swift | 14 +- .../StickerPackPreviewController.swift | 2 +- .../Sources/StickerPackScreen.swift | 2 +- .../Sources/VoiceChatController.swift | 10 +- .../Account/AccountIntermediateState.swift | 7 +- .../Sources/ApiUtils/TelegramChannel.swift | 18 + .../TelegramCore/Sources/ForumChannels.swift | 324 +++++++++++------- .../State/AccountStateManagementUtils.swift | 114 ++++-- .../Sources/State/AccountStateManager.swift | 6 +- .../Sources/State/AccountViewTracker.swift | 2 +- .../Sources/State/ManagedChatListHoles.swift | 9 +- .../Messages/ReplyThreadHistory.swift | 10 + .../Peers/TelegramEnginePeers.swift | 5 +- .../Utils/StoredMessageFromSearchPeer.swift | 12 +- .../Sources/ApplicationContext.swift | 47 ++- .../TelegramUI/Sources/ChatController.swift | 101 ++++-- .../Sources/ChatEntityKeyboardInputNode.swift | 33 +- .../ChatInterfaceStateContextMenus.swift | 9 +- .../ChatInterfaceStateInputPanels.swift | 4 +- .../ChatInterfaceTitlePanelNodes.swift | 4 +- .../ChatRecentActionsControllerNode.swift | 6 +- .../ChatReportPeerTitlePanelNode.swift | 4 +- .../Sources/ComposeController.swift | 2 +- .../Sources/NavigateToChatController.swift | 28 +- .../TelegramUI/Sources/OpenResolvedUrl.swift | 81 +++-- submodules/TelegramUI/Sources/OpenUrl.swift | 6 +- .../Sources/PeerInfo/PeerInfoData.swift | 2 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 141 ++++---- .../TelegramUI/Sources/TextLinkHandling.swift | 4 +- .../WebUI/Sources/WebAppController.swift | 18 +- 62 files changed, 1080 insertions(+), 473 deletions(-) diff --git a/Telegram/NotificationService/Sources/NotificationService.swift b/Telegram/NotificationService/Sources/NotificationService.swift index c08eeadfdf..ee0c4185ac 100644 --- a/Telegram/NotificationService/Sources/NotificationService.swift +++ b/Telegram/NotificationService/Sources/NotificationService.swift @@ -1360,6 +1360,7 @@ private final class NotificationServiceHandler { Logger.shared.log("NotificationService \(episode)", "Will poll channel \(peerId)") pollSignal = standalonePollChannelOnce( + accountPeerId: stateManager.accountPeerId, postbox: stateManager.postbox, network: stateManager.network, peerId: peerId, diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 84d60d1e93..81fb8a1a4b 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -379,10 +379,42 @@ public enum ChatControllerActivateInput { } public final class NavigateToChatControllerParams { + public enum Location { + case peer(EnginePeer) + case replyThread(ChatReplyThreadMessage) + + public var peerId: EnginePeer.Id { + switch self { + case let .peer(peer): + return peer.id + case let .replyThread(message): + return message.messageId.peerId + } + } + + public var threadId: Int64? { + switch self { + case .peer: + return nil + case let .replyThread(message): + return Int64(message.messageId.id) + } + } + + public var asChatLocation: ChatLocation { + switch self { + case let .peer(peer): + return .peer(id: peer.id) + case let .replyThread(message): + return .replyThread(message: message) + } + } + } + public let navigationController: NavigationController public let chatController: ChatController? public let context: AccountContext - public let chatLocation: ChatLocation + public let chatLocation: Location public let chatLocationContextHolder: Atomic public let subject: ChatControllerSubject? public let botStart: ChatControllerInitialBotStart? @@ -407,7 +439,7 @@ public final class NavigateToChatControllerParams { public let setupController: (ChatController) -> Void public let completion: (ChatController) -> Void - public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic = Atomic(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotStart: ChatControllerInitialAttachBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: ChatControllerActivateInput? = nil, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, useBackAnimation: Bool = false, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [PeerId] = [], changeColors: Bool = false, setupController: @escaping (ChatController) -> Void = { _ in }, completion: @escaping (ChatController) -> Void = { _ in }) { + public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: Location, chatLocationContextHolder: Atomic = Atomic(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotStart: ChatControllerInitialAttachBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: ChatControllerActivateInput? = nil, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, useBackAnimation: Bool = false, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [PeerId] = [], changeColors: Bool = false, setupController: @escaping (ChatController) -> Void = { _ in }, completion: @escaping (ChatController) -> Void = { _ in }) { self.navigationController = navigationController self.chatController = chatController self.chatLocationContextHolder = chatLocationContextHolder diff --git a/submodules/ChatListUI/Sources/ChatContextMenus.swift b/submodules/ChatListUI/Sources/ChatContextMenus.swift index eb6b6bcd93..6855db3d88 100644 --- a/submodules/ChatListUI/Sources/ChatContextMenus.swift +++ b/submodules/ChatListUI/Sources/ChatContextMenus.swift @@ -457,9 +457,15 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch chatListController.present(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) } }, completed: { - if let navigationController = (chatListController?.navigationController as? NavigationController) { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = (chatListController?.navigationController as? NavigationController) { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) })) f(.default) }))) @@ -709,22 +715,23 @@ func chatForumTopicMenuItems(context: AccountContext, peerId: PeerId, threadId: } }))) - var canManage = false + var canOpenClose = false if channel.flags.contains(.isCreator) { - canManage = true - } else if channel.adminRights != nil { - canManage = true + canOpenClose = true + } else if channel.hasPermission(.manageTopics) { + canOpenClose = true } else if threadData.isOwnedByMe { - canManage = true + canOpenClose = true } - if canManage { + if canOpenClose { //TODO:localize items.append(.action(ContextMenuActionItem(text: threadData.isClosed ? "Restart" : "Close", icon: { theme in generateTintedImage(image: UIImage(bundleImageName: threadData.isClosed ? "Chat/Context Menu/Play": "Chat/Context Menu/Pause"), color: theme.contextMenu.primaryColor) }, action: { _, f in f(.default) let _ = context.engine.peers.setForumChannelTopicClosed(id: peerId, threadId: threadId, isClosed: !threadData.isClosed).start() }))) - + } + if channel.hasPermission(.deleteAllMessages) { items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Delete, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) }, action: { [weak chatListController] _, f in f(.default) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index a0473729da..cb2605ed78 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -1384,8 +1384,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } } - let chatLocation: ChatLocation - chatLocation = .peer(id: peer.id) + let chatLocation: NavigateToChatControllerParams.Location + chatLocation = .peer(peer) strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: chatLocation, activateInput: (activateInput && !peer.isDeleted) ? .text : nil, scrollToEndIfExists: scrollToEndIfExists, animated: !scrollToEndIfExists, options: navigationAnimationOptions, parentGroupId: groupId._asGroup(), chatListFilter: strongSelf.chatListDisplayNode.containerNode.currentItemNode.chatListFilter?.id, completion: { [weak self] controller in self?.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true) @@ -1461,7 +1461,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController self.chatListDisplayNode.requestOpenMessageFromSearch = { [weak self] peer, threadId, messageId, deactivateOnAction in if let strongSelf = self { strongSelf.openMessageFromSearchDisposable.set((strongSelf.context.engine.peers.ensurePeerIsLocallyAvailable(peer: peer) - |> deliverOnMainQueue).start(next: { [weak strongSelf] actualPeerId in + |> deliverOnMainQueue).start(next: { [weak strongSelf] actualPeer in if let strongSelf = strongSelf { if let navigationController = strongSelf.navigationController as? NavigationController { var scrollToEndIfExists = false @@ -1475,7 +1475,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController if let threadId = threadId { let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: nil, keepStack: .never).start() } else { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: actualPeerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil), purposefulAction: { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeer), subject: .message(id: .id(messageId), highlight: true, timecode: nil), purposefulAction: { if deactivateOnAction { self?.deactivateSearch(animated: false) } @@ -1508,7 +1508,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController if let threadId = threadId { let _ = strongSelf.context.sharedContext.navigateToForumThread(context: strongSelf.context, peerId: peer.id, threadId: threadId, messageId: nil, navigationController: navigationController, activateInput: nil, keepStack: .never).start() } else { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), purposefulAction: { [weak self] in + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), purposefulAction: { [weak self] in self?.deactivateSearch(animated: false) }, scrollToEndIfExists: scrollToEndIfExists, options: navigationAnimationOptions)) } @@ -2652,7 +2652,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController sourceController?.beginMessageSearch("") }))) - } else if channel.hasPermission(.manageTopics) { + } else if channel.hasPermission(.createTopics) { items.append(.separator) //TODO:localize diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 50c60ec833..69c42db163 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -739,7 +739,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable { index = .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index)) case .forum: if let threadId = message.threadId, let threadInfo = threadInfo { - chatThreadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadInfo, isOwner: false, isClosed: false) + chatThreadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadInfo, isOwnedByMe: false, isClosed: false) index = .forum(pinnedIndex: .none, timestamp: message.index.timestamp, threadId: threadId, namespace: message.index.id.namespace, id: message.index.id.id) } else { index = .chatList( EngineChatList.Item.Index.ChatList(pinningIndex: nil, messageIndex: message.index)) @@ -1522,7 +1522,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { for thread in allAndFoundThreads { if let peer = thread.renderedPeer.peer, let threadData = thread.threadData, case let .forum(_, _, id, _, _) = thread.index { - entries.append(.topic(peer, ChatListItemContent.ThreadInfo(id: id, info: threadData.info, isOwner: threadData.isOwnedByMe, isClosed: threadData.isClosed), index, presentationData.theme, presentationData.strings, .none)) + entries.append(.topic(peer, ChatListItemContent.ThreadInfo(id: id, info: threadData.info, isOwnedByMe: threadData.isOwnedByMe, isClosed: threadData.isClosed), index, presentationData.theme, presentationData.strings, .none)) index += 1 } } diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index aa6e1922ab..6a74b4bf32 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -32,13 +32,13 @@ public enum ChatListItemContent { public struct ThreadInfo: Equatable { public var id: Int64 public var info: EngineMessageHistoryThread.Info - public var isOwner: Bool + public var isOwnedByMe: Bool public var isClosed: Bool - public init(id: Int64, info: EngineMessageHistoryThread.Info, isOwner: Bool, isClosed: Bool) { + public init(id: Int64, info: EngineMessageHistoryThread.Info, isOwnedByMe: Bool, isClosed: Bool) { self.id = id self.info = info - self.isOwner = isOwner + self.isOwnedByMe = isOwnedByMe self.isClosed = isClosed } } @@ -2010,9 +2010,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { var canOpenClose = false if channel.flags.contains(.isCreator) { canOpenClose = true - } else if channel.hasPermission(.pinMessages) { + } else if channel.hasPermission(.manageTopics) { canOpenClose = true - } else if let threadInfo = threadInfo, threadInfo.isOwner { + } else if let threadInfo = threadInfo, threadInfo.isOwnedByMe { canOpenClose = true } let canDelete = channel.hasPermission(.deleteAllMessages) diff --git a/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift b/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift index 7034036428..048e9acf7c 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift @@ -394,7 +394,7 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState isSelected = state.selectedPeerIds.contains(peerId) } - result.append(.PeerEntry(index: offsetPinnedIndex(entry.index, offset: pinnedIndexOffset), presentationData: state.presentationData, messages: updatedMessages, readState: updatedCombinedReadState, isRemovedFromTotalUnreadCount: entry.isMuted, draftState: draftState, peer: entry.renderedPeer, threadInfo: entry.threadData.flatMap { ChatListItemContent.ThreadInfo(id: threadId, info: $0.info, isOwner: $0.isOwnedByMe, isClosed: $0.isClosed) }, presence: entry.presence, hasUnseenMentions: entry.hasUnseenMentions, hasUnseenReactions: entry.hasUnseenReactions, editing: state.editing, hasActiveRevealControls: hasActiveRevealControls, selected: isSelected, inputActivities: inputActivities, promoInfo: nil, hasFailedMessages: entry.hasFailed, isContact: entry.isContact, forumTopicData: entry.forumTopicData)) + result.append(.PeerEntry(index: offsetPinnedIndex(entry.index, offset: pinnedIndexOffset), presentationData: state.presentationData, messages: updatedMessages, readState: updatedCombinedReadState, isRemovedFromTotalUnreadCount: entry.isMuted, draftState: draftState, peer: entry.renderedPeer, threadInfo: entry.threadData.flatMap { ChatListItemContent.ThreadInfo(id: threadId, info: $0.info, isOwnedByMe: $0.isOwnedByMe, isClosed: $0.isClosed) }, presence: entry.presence, hasUnseenMentions: entry.hasUnseenMentions, hasUnseenReactions: entry.hasUnseenReactions, editing: state.editing, hasActiveRevealControls: hasActiveRevealControls, selected: isSelected, inputActivities: inputActivities, promoInfo: nil, hasFailedMessages: entry.hasFailed, isContact: entry.isContact, forumTopicData: entry.forumTopicData)) } if !view.hasLater { var pinningIndex: UInt16 = UInt16(pinnedIndexOffset == 0 ? 0 : (pinnedIndexOffset - 1)) @@ -472,7 +472,7 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState isRemovedFromTotalUnreadCount: item.item.isMuted, draftState: draftState, peer: item.item.renderedPeer, - threadInfo: item.item.threadData.flatMap { ChatListItemContent.ThreadInfo(id: threadId, info: $0.info, isOwner: $0.isOwnedByMe, isClosed: $0.isClosed) }, + threadInfo: item.item.threadData.flatMap { ChatListItemContent.ThreadInfo(id: threadId, info: $0.info, isOwnedByMe: $0.isOwnedByMe, isClosed: $0.isClosed) }, presence: item.item.presence, hasUnseenMentions: item.item.hasUnseenMentions, hasUnseenReactions: item.item.hasUnseenReactions, diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift index 2c4888d3ca..d6e9ccc707 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift @@ -345,14 +345,14 @@ public final class ChatPresentationInterfaceState: Equatable { public var title: String public var icon: Int64? public var iconColor: Int32 - public var isOwn: Bool + public var isOwnedByMe: Bool public var isClosed: Bool - public init(title: String, icon: Int64?, iconColor: Int32, isOwn: Bool, isClosed: Bool) { + public init(title: String, icon: Int64?, iconColor: Int32, isOwnedByMe: Bool, isClosed: Bool) { self.title = title self.icon = icon self.iconColor = iconColor - self.isOwn = isOwn + self.isOwnedByMe = isOwnedByMe self.isClosed = isClosed } } diff --git a/submodules/ContactListUI/Sources/ContactContextMenus.swift b/submodules/ContactListUI/Sources/ContactContextMenus.swift index 2723713e4c..0a01ee8426 100644 --- a/submodules/ContactListUI/Sources/ContactContextMenus.swift +++ b/submodules/ContactListUI/Sources/ContactContextMenus.swift @@ -22,10 +22,18 @@ func contactContextMenuItems(context: AccountContext, peerId: EnginePeer.Id, con var items: [ContextMenuItem] = [] items.append(.action(ContextMenuActionItem(text: strings.ContactList_Context_SendMessage, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Message"), color: theme.contextMenu.primaryColor) }, action: { _, f in - if let contactsController = contactsController, let navigationController = contactsController.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId), peekData: nil)) - } - f(.default) + let _ = (context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: peerId) + ) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let contactsController = contactsController, let navigationController = contactsController.navigationController as? NavigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), peekData: nil)) + } + f(.default) + }) }))) var canStartSecretChat = true @@ -38,9 +46,18 @@ func contactContextMenuItems(context: AccountContext, peerId: EnginePeer.Id, con let _ = (context.engine.peers.mostRecentSecretChat(id: peerId) |> deliverOnMainQueue).start(next: { currentPeerId in if let currentPeerId = currentPeerId { - if let contactsController = contactsController, let navigationController = (contactsController.navigationController as? NavigationController) { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: currentPeerId), peekData: nil)) - } + let _ = (context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: currentPeerId) + ) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + if let contactsController = contactsController, let navigationController = (contactsController.navigationController as? NavigationController) { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), peekData: nil)) + } + }) } else { var createSignal = context.engine.peers.createSecretChat(peerId: peerId) var cancelImpl: (() -> Void)? @@ -73,9 +90,18 @@ func contactContextMenuItems(context: AccountContext, peerId: EnginePeer.Id, con createSecretChatDisposable.set((createSignal |> deliverOnMainQueue).start(next: { peerId in - if let navigationController = (contactsController?.navigationController as? NavigationController) { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId), peekData: nil)) - } + let _ = (context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: peerId) + ) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + if let navigationController = (contactsController?.navigationController as? NavigationController) { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), peekData: nil)) + } + }) }, error: { error in if let contactsController = contactsController { let presentationData = context.sharedContext.currentPresentationData.with { $0 } diff --git a/submodules/ContactListUI/Sources/ContactsController.swift b/submodules/ContactListUI/Sources/ContactsController.swift index e3cbe7d661..55c20a8002 100644 --- a/submodules/ContactListUI/Sources/ContactsController.swift +++ b/submodules/ContactListUI/Sources/ContactsController.swift @@ -323,7 +323,7 @@ public class ContactsController: ViewController { scrollToEndIfExists = true } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), purposefulAction: { [weak self] in + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)), purposefulAction: { [weak self] in if fromSearch { self?.deactivateSearch(animated: false) self?.switchToChatsController?() diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift index ba06f978ba..b0bfae6a9d 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift @@ -64,9 +64,9 @@ public final class HashtagSearchController: TelegramBaseController { }, additionalCategorySelected: { _ in }, messageSelected: { [weak self] peer, _, message, _ in if let strongSelf = self { - strongSelf.openMessageFromSearchDisposable.set((strongSelf.context.engine.peers.ensurePeerIsLocallyAvailable(peer: peer) |> deliverOnMainQueue).start(next: { actualPeerId in + strongSelf.openMessageFromSearchDisposable.set((strongSelf.context.engine.peers.ensurePeerIsLocallyAvailable(peer: peer) |> deliverOnMainQueue).start(next: { actualPeer in if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: actualPeerId), subject: message.id.peerId == actualPeerId ? .message(id: .id(message.id), highlight: true, timecode: nil) : nil, keepStack: .always)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeer), subject: message.id.peerId == actualPeer.id ? .message(id: .id(message.id), highlight: true, timecode: nil) : nil, keepStack: .always)) } })) strongSelf.controllerNode.listNode.clearHighlightAnimated(true) diff --git a/submodules/InstantPageUI/Sources/InstantPageController.swift b/submodules/InstantPageUI/Sources/InstantPageController.swift index 9843215f74..05cabd89dd 100644 --- a/submodules/InstantPageUI/Sources/InstantPageController.swift +++ b/submodules/InstantPageUI/Sources/InstantPageController.swift @@ -153,7 +153,7 @@ public final class InstantPageController: ViewController { (self?.navigationController as? NavigationController)?.pushViewController(c) }, openPeer: { [weak self] peer in if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), animated: true)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), animated: true)) } }, navigateBack: { [weak self] in if let strongSelf = self, let controllers = strongSelf.navigationController?.viewControllers.reversed() { diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index ac66805218..61a4a38927 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -1330,21 +1330,21 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { switch navigation { case let .chat(_, subject, peekData): if let navigationController = strongSelf.getNavigationController() { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), subject: subject, peekData: peekData)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), subject: subject, peekData: peekData)) } case let .withBotStartPayload(botStart): if let navigationController = strongSelf.getNavigationController() { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), botStart: botStart, keepStack: .always)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), botStart: botStart, keepStack: .always)) } case let .withAttachBot(attachBotStart): if let navigationController = strongSelf.getNavigationController() { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), attachBotStart: attachBotStart)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), attachBotStart: attachBotStart)) } case .info: - let _ = (strongSelf.context.account.postbox.loadedPeerWithId(peer.id) + let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peer.id)) |> deliverOnMainQueue).start(next: { peer in - if let strongSelf = self { - if let controller = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) { + if let strongSelf = self, let peer = peer { + if let controller = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer._asPeer(), mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) { strongSelf.getNavigationController()?.pushViewController(controller) } } diff --git a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift index c0ef30c836..18d0e8b409 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift @@ -472,9 +472,16 @@ public final class InviteLinkViewController: ViewController { self.isOpaque = false self.interaction = InviteLinkViewInteraction(context: context, openPeer: { [weak self] peerId in - if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId), keepStack: .always)) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), keepStack: .always)) + } + }) }, copyLink: { [weak self] invite in UIPasteboard.general.string = invite.link diff --git a/submodules/InviteLinksUI/Sources/InviteRequestsController.swift b/submodules/InviteLinksUI/Sources/InviteRequestsController.swift index 3e7fc38ccb..ae6e8244e2 100644 --- a/submodules/InviteLinksUI/Sources/InviteRequestsController.swift +++ b/submodules/InviteLinksUI/Sources/InviteRequestsController.swift @@ -383,7 +383,7 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio } navigateToChatImpl = { [weak controller] peer in if let navigationController = controller?.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), keepStack: .always)) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), keepStack: .always)) } } dismissInputImpl = { [weak controller] in diff --git a/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift b/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift index 9c2870d1db..3412d5a1d4 100644 --- a/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelBlacklistController.swift @@ -369,7 +369,7 @@ public func channelBlacklistController(context: AccountContext, updatedPresentat actionSheet?.dismissAnimated() if participant.peer is TelegramChannel { if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: participant.peer.id))) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(EnginePeer(participant.peer)))) } } else if let infoController = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: participant.peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) { pushControllerImpl?(infoController) diff --git a/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift b/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift index e7ee39e2d0..d86049d007 100644 --- a/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift @@ -637,10 +637,17 @@ public func channelDiscussionGroupSetupController(context: AccountContext, updat controller?.present(c, in: .window(.root), with: a) } navigateToGroupImpl = { [weak controller] groupId in - guard let navigationController = controller?.navigationController as? NavigationController else { - return - } - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: groupId), keepStack: .always)) + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: groupId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + guard let navigationController = controller?.navigationController as? NavigationController else { + return + } + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), keepStack: .always)) + }) } return controller } diff --git a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift index 264eee9fe5..cd06ea1325 100644 --- a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift @@ -963,9 +963,15 @@ public func channelPermissionsController(context: AccountContext, updatedPresent } } navigateToChatControllerImpl = { [weak controller] peerId in - if let controller = controller, let navigationController = controller.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId), keepStack: .always)) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let controller = controller, let navigationController = controller.navigationController as? NavigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), keepStack: .always)) + } + }) } dismissInputImpl = { [weak controller] in controller?.view.endEditing(true) diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index 6bb01fc170..de7c0813d3 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -2251,22 +2251,41 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta } }) if filteredPeerIds.isEmpty { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(id: peerId), keepStack: .never, animated: true)) + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(peer), keepStack: .never, animated: true)) + }) } else { selectionController.displayProgress = true let _ = (context.engine.peers.addChannelMembers(peerId: peerId, memberIds: filteredPeerIds) |> deliverOnMainQueue).start(error: { [weak selectionController] _ in - guard let selectionController = selectionController, let navigationController = selectionController.navigationController as? NavigationController else { - return - } - - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(id: peerId), keepStack: .never, animated: true)) + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + guard let selectionController = selectionController, let navigationController = selectionController.navigationController as? NavigationController else { + return + } + + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(peer), keepStack: .never, animated: true)) + }) }, completed: { [weak selectionController] in - guard let selectionController = selectionController, let navigationController = selectionController.navigationController as? NavigationController else { - return - } - - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(id: peerId), keepStack: .never, animated: true)) + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + guard let selectionController = selectionController, let navigationController = selectionController.navigationController as? NavigationController else { + return + } + + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(peer), keepStack: .never, animated: true)) + }) }) } }) diff --git a/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift b/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift index f38b84554a..78af966f4f 100644 --- a/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift +++ b/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift @@ -1249,9 +1249,16 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta }) } openChatImpl = { [weak controller] peerId in - if let navigationController = (controller?.navigationController as? NavigationController) { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + if let navigationController = (controller?.navigationController as? NavigationController) { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) } replaceControllerImpl = { [weak controller] value in (controller?.navigationController as? NavigationController)?.replaceTopController(value, animated: true) diff --git a/submodules/PeerInfoUI/Sources/GroupStickerPackSetupController.swift b/submodules/PeerInfoUI/Sources/GroupStickerPackSetupController.swift index 09fd24a8b4..d7107012ed 100644 --- a/submodules/PeerInfoUI/Sources/GroupStickerPackSetupController.swift +++ b/submodules/PeerInfoUI/Sources/GroupStickerPackSetupController.swift @@ -486,9 +486,16 @@ public func groupStickerPackSetupController(context: AccountContext, updatedPres presentControllerImpl?(StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: controller?.navigationController as? NavigationController), nil) } navigateToChatControllerImpl = { [weak controller] peerId in - if let controller = controller, let navigationController = controller.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + if let controller = controller, let navigationController = controller.navigationController as? NavigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) } dismissImpl = { [weak controller] in dismissInputImpl?() diff --git a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift index 2a26508fb9..2411edffdb 100644 --- a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift +++ b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift @@ -615,7 +615,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController { } navigateToChatImpl = { [weak controller] peer in if let navigationController = controller?.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), keepStack: .always, purposefulAction: {}, peekData: nil)) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), keepStack: .always, purposefulAction: {}, peekData: nil)) } } pushControllerImpl = { [weak controller] c in diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index 615e476ff1..017539e063 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -91,6 +91,11 @@ public final class Transaction { assert(!self.disposed) return self.postbox!.messageHistoryThreadHoleIndexTable.closest(peerId: peerId, threadId: threadId, namespace: namespace, space: .everywhere, range: 1 ... (Int32.max - 1)) } + + public func getThreadIndexHole(peerId: PeerId, threadId: Int64, namespace: MessageId.Namespace, containing id: MessageId.Id) -> [MessageHistoryHoleSpace: ClosedRange] { + assert(!self.disposed) + return self.postbox!.messageHistoryThreadHoleIndexTable.containing(threadId: threadId, id: MessageId(peerId: peerId, namespace: namespace, id: id)) + } public func getThreadMessageCount(peerId: PeerId, threadId: Int64, namespace: MessageId.Namespace, fromIdExclusive: Int32?, toIndex: MessageIndex) -> Int? { assert(!self.disposed) @@ -1268,7 +1273,7 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, #if DEBUG //debugSaveState(basePath: basePath, name: "previous1") - //debugRestoreState(basePath: basePath, name: "previous1") + debugRestoreState(basePath: basePath, name: "previous1") #endif let startTime = CFAbsoluteTimeGetCurrent() diff --git a/submodules/Postbox/Sources/UnreadMessageCountsView.swift b/submodules/Postbox/Sources/UnreadMessageCountsView.swift index 8e2d19a12b..72d37aeb03 100644 --- a/submodules/Postbox/Sources/UnreadMessageCountsView.swift +++ b/submodules/Postbox/Sources/UnreadMessageCountsView.swift @@ -64,7 +64,15 @@ final class MutableUnreadMessageCountsView: MutablePostboxView { case let .totalInGroup(groupId): return .totalInGroup(groupId, postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId)) case let .peer(peerId): - return .peer(peerId, postbox.readStateTable.getCombinedState(peerId)) + if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) { + var count: Int32 = 0 + if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) { + count = summary.effectiveUnreadCount + } + return .peer(peerId, CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 1, maxOutgoingReadId: 1, maxKnownId: 1, count: count, markedUnread: false))])) + } else { + return .peer(peerId, postbox.readStateTable.getCombinedState(peerId)) + } } } } @@ -105,9 +113,20 @@ final class MutableUnreadMessageCountsView: MutablePostboxView { } } case let .peer(peerId, _): - if transaction.alteredInitialPeerCombinedReadStates[peerId] != nil { - self.entries[i] = .peer(peerId, postbox.readStateTable.getCombinedState(peerId)) - updated = true + if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) { + if transaction.updatedPeerThreadsSummaries.contains(peerId) { + var count: Int32 = 0 + if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) { + count = summary.effectiveUnreadCount + } + self.entries[i] = .peer(peerId, CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 1, maxOutgoingReadId: 1, maxKnownId: 1, count: count, markedUnread: false))])) + updated = true + } + } else { + if transaction.alteredInitialPeerCombinedReadStates[peerId] != nil { + self.entries[i] = .peer(peerId, postbox.readStateTable.getCombinedState(peerId)) + updated = true + } } } } diff --git a/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift b/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift index 34cbfd3363..dd6715a40e 100644 --- a/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift +++ b/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift @@ -696,7 +696,7 @@ private final class QrCodeScanScreenNode: ViewControllerTracingNode, UIScrollVie guard let strongSelf = self else { return } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), subject: nil, keepStack: .always, peekData: nil, completion: { [weak navigationController] _ in + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), subject: nil, keepStack: .always, peekData: nil, completion: { [weak navigationController] _ in if let navigationController = navigationController { var viewControllers = navigationController.viewControllers viewControllers = viewControllers.filter { controller in diff --git a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift index ee5d3026bb..51c95be1a2 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift @@ -356,10 +356,19 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo supportPeerDisposable.set((supportPeer.get() |> take(1) |> deliverOnMainQueue).start(next: { peerId in - if let peerId = peerId, let navigationController = navigationController { - dismissImpl?() - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) + guard let peerId = peerId else { + return } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = navigationController { + dismissImpl?() + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) })) }) ]) diff --git a/submodules/SettingsUI/Sources/LogoutOptionsController.swift b/submodules/SettingsUI/Sources/LogoutOptionsController.swift index 75b3927881..bef523364a 100644 --- a/submodules/SettingsUI/Sources/LogoutOptionsController.swift +++ b/submodules/SettingsUI/Sources/LogoutOptionsController.swift @@ -229,10 +229,19 @@ public func logoutOptionsController(context: AccountContext, navigationControlle supportPeerDisposable.set((supportPeer.get() |> take(1) |> deliverOnMainQueue).start(next: { peerId in - if let peerId = peerId, let navigationController = navigationController { - dismissImpl?() - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) + guard let peerId = peerId else { + return } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = navigationController { + dismissImpl?() + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) })) }) ]), nil) diff --git a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift index 9d26026883..77eceee8e1 100644 --- a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift @@ -1322,9 +1322,16 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta (controller?.navigationController as? NavigationController)?.pushViewController(c) } navigateToChatControllerImpl = { [weak controller] peerId in - if let controller = controller, let navigationController = controller.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + if let controller = controller, let navigationController = controller.navigationController as? NavigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) } dismissImpl = { [weak controller] in controller?.dismiss() diff --git a/submodules/SettingsUI/Sources/ThemePickerController.swift b/submodules/SettingsUI/Sources/ThemePickerController.swift index a620c20fa7..dcb6fa184e 100644 --- a/submodules/SettingsUI/Sources/ThemePickerController.swift +++ b/submodules/SettingsUI/Sources/ThemePickerController.swift @@ -416,9 +416,15 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme openAccentColorPickerImpl?(themeReference, create) }, editTheme: { theme in let controller = editThemeController(context: context, mode: .edit(theme), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) pushControllerImpl?(controller) }, editCurrentTheme: { @@ -438,9 +444,15 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme |> deliverOnMainQueue).start(next: { themeReference in if case let .cloud(cloudTheme) = themeReference, cloudTheme.theme.settings?.isEmpty ?? true { let controller = editThemeController(context: context, mode: .edit(cloudTheme), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) pushControllerImpl?(controller) } else { @@ -463,9 +475,15 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme } |> deliverOnMainQueue).start(next: { themeReference in let controller = editThemeController(context: context, mode: .create(nil, nil), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) pushControllerImpl?(controller) }) @@ -525,9 +543,15 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme if theme.theme.isCreator { items.append(.action(ContextMenuActionItem(text: presentationData.strings.Appearance_EditTheme, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor) }, action: { c, f in let controller = editThemeController(context: context, mode: .edit(theme), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) c.dismiss(completion: { @@ -555,9 +579,15 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme let controller = ThemeAccentColorController(context: context, mode: .edit(settings: nil, theme: theme, wallpaper: wallpaper, generalThemeReference: reference.generalThemeReference, defaultThemeReference: nil, create: true, completion: { result, settings in let controller = editThemeController(context: context, mode: .create(result, settings ), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) updateControllersImpl?({ controllers in var controllers = controllers @@ -761,9 +791,15 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme if cloudTheme.theme.isCreator && cloudThemeExists { items.append(.action(ContextMenuActionItem(text: presentationData.strings.Appearance_EditTheme, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor) }, action: { c, f in let controller = editThemeController(context: context, mode: .edit(cloudTheme), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) c.dismiss(completion: { @@ -796,9 +832,15 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme } let controller = ThemeAccentColorController(context: context, mode: .edit(settings: settings, theme: theme, wallpaper: wallpaper, generalThemeReference: effectiveThemeReference.generalThemeReference, defaultThemeReference: nil, create: true, completion: { result, settings in let controller = editThemeController(context: context, mode: .create(hasSettings ? nil : result, hasSettings ? settings : nil), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) updateControllersImpl?({ controllers in var controllers = controllers diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index 137d752d52..7ab7c169d1 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -522,9 +522,15 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The }) }, editTheme: { theme in let controller = editThemeController(context: context, mode: .edit(theme), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) pushControllerImpl?(controller) }, themeContextAction: { isCurrent, reference, node, gesture in @@ -583,9 +589,15 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The if theme.theme.isCreator { items.append(.action(ContextMenuActionItem(text: presentationData.strings.Appearance_EditTheme, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor) }, action: { c, f in let controller = editThemeController(context: context, mode: .edit(theme), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) c.dismiss(completion: { @@ -613,9 +625,15 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The let controller = ThemeAccentColorController(context: context, mode: .edit(settings: nil, theme: theme, wallpaper: wallpaper, generalThemeReference: reference.generalThemeReference, defaultThemeReference: nil, create: true, completion: { result, settings in let controller = editThemeController(context: context, mode: .create(result, settings ), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) updateControllersImpl?({ controllers in var controllers = controllers @@ -817,9 +835,15 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The if cloudTheme.theme.isCreator && cloudThemeExists { items.append(.action(ContextMenuActionItem(text: presentationData.strings.Appearance_EditTheme, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor) }, action: { c, f in let controller = editThemeController(context: context, mode: .edit(cloudTheme), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) c.dismiss(completion: { @@ -852,9 +876,15 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The } let controller = ThemeAccentColorController(context: context, mode: .edit(settings: settings, theme: theme, wallpaper: wallpaper, generalThemeReference: effectiveThemeReference.generalThemeReference, defaultThemeReference: nil, create: true, completion: { result, settings in let controller = editThemeController(context: context, mode: .create(hasSettings ? nil : result, hasSettings ? settings : nil), navigateToChat: { peerId in - if let navigationController = getNavigationControllerImpl?() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + }) }) updateControllersImpl?({ controllers in var controllers = controllers diff --git a/submodules/StatisticsUI/Sources/ChannelStatsController.swift b/submodules/StatisticsUI/Sources/ChannelStatsController.swift index 497f0f737c..c5241ff0a8 100644 --- a/submodules/StatisticsUI/Sources/ChannelStatsController.swift +++ b/submodules/StatisticsUI/Sources/ChannelStatsController.swift @@ -514,9 +514,16 @@ public func channelStatsController(context: AccountContext, updatedPresentationD var items: [ContextMenuItem] = [] items.append(.action(ContextMenuActionItem(text: presentationData.strings.SharedMedia_ViewInChat, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor) }, action: { [weak controller] c, _ in c.dismiss(completion: { - if let navigationController = controller?.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + if let navigationController = controller?.navigationController as? NavigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(messageId), highlight: true, timecode: nil))) + } + }) }) }))) diff --git a/submodules/StatisticsUI/Sources/GroupStatsController.swift b/submodules/StatisticsUI/Sources/GroupStatsController.swift index dbb709b20c..aea2de6d6f 100644 --- a/submodules/StatisticsUI/Sources/GroupStatsController.swift +++ b/submodules/StatisticsUI/Sources/GroupStatsController.swift @@ -877,10 +877,15 @@ public func groupStatsController(context: AccountContext, updatedPresentationDat } openPeerHistoryImpl = { [weak controller] participantPeerId in if let navigationController = controller?.navigationController as? NavigationController { - let _ = (context.account.postbox.loadedPeerWithId(participantPeerId) - |> take(1) - |> deliverOnMainQueue).start(next: { peer in - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, updateTextInputState: nil, keepStack: .always, useExisting: false, purposefulAction: nil, scrollToEndIfExists: false, activateMessageSearch: (.member(peer), ""), animated: true)) + let _ = (context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: peerId), + TelegramEngine.EngineData.Item.Peer.Peer(id: participantPeerId) + ) + |> deliverOnMainQueue).start(next: { chatPeer, peer in + guard let chatPeer, let peer else { + return + } + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(chatPeer), subject: nil, botStart: nil, updateTextInputState: nil, keepStack: .always, useExisting: false, purposefulAction: nil, scrollToEndIfExists: false, activateMessageSearch: (.member(peer._asPeer()), ""), animated: true)) }) } } diff --git a/submodules/StatisticsUI/Sources/MessageStatsController.swift b/submodules/StatisticsUI/Sources/MessageStatsController.swift index e8192abc43..ce419b28e0 100644 --- a/submodules/StatisticsUI/Sources/MessageStatsController.swift +++ b/submodules/StatisticsUI/Sources/MessageStatsController.swift @@ -259,9 +259,17 @@ public func messageStatsController(context: AccountContext, messageId: MessageId controller?.clearItemNodesHighlight(animated: true) } navigateToMessageImpl = { [weak controller] messageId in - if let navigationController = controller?.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: messageId.peerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: {}, peekData: nil)) - } + let _ = (context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: messageId.peerId) + ) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = controller?.navigationController as? NavigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: {}, peekData: nil)) + } + }) } return controller } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift index 482a6dc37c..5e3e66a6c6 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift @@ -149,7 +149,7 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese } if let peer = peer, let parentNavigationController = strongSelf.parentNavigationController { strongSelf.dismiss() - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: parentNavigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), animated: true)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: parentNavigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)), animated: true)) } })) }, actionPerformed: self.actionPerformed) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index bab1ec6d9e..0808de4c7d 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -1732,7 +1732,7 @@ public final class StickerPackScreenImpl: ViewController { } if let peer = peer, let parentNavigationController = strongSelf.parentNavigationController { strongSelf.dismiss() - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: parentNavigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), animated: true)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: parentNavigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)), animated: true)) } })) }) diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index 7fd9db2844..428669cca3 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -1694,7 +1694,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController let context = strongSelf.context strongSelf.controller?.dismiss(completion: { Queue.mainQueue().after(0.3) { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), keepStack: .always, purposefulAction: {}, peekData: nil)) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(EnginePeer(peer)), keepStack: .always, purposefulAction: {}, peekData: nil)) } }) @@ -2671,7 +2671,13 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController let context = strongSelf.context strongSelf.controller?.dismiss(completion: { Queue.mainQueue().justDispatch { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: context.account.peerId), keepStack: .always, purposefulAction: {}, peekData: nil)) + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), keepStack: .always, purposefulAction: {}, peekData: nil)) + }) } }) diff --git a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift index 9ef572b664..adb0f1a6dc 100644 --- a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift +++ b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift @@ -137,6 +137,11 @@ struct HoleFromPreviousState { } } +enum StateResetForumTopics { + case result(LoadMessageHistoryThreadsResult) + case error(PeerId) +} + struct AccountMutableState { let initialState: AccountInitialState let branchOperationIndex: Int @@ -153,7 +158,7 @@ struct AccountMutableState { var namespacesWithHolesFromPreviousState: [PeerId: [MessageId.Namespace: HoleFromPreviousState]] var updatedOutgoingUniqueMessageIds: [Int64: Int32] - var resetForumTopicLists: [PeerId: [MessageHistoryThreadData]] = [:] + var resetForumTopicLists: [PeerId: StateResetForumTopics] = [:] var storedMessagesByPeerIdAndTimestamp: [PeerId: Set] var displayAlerts: [(text: String, isDropAuth: Bool)] = [] diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramChannel.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramChannel.swift index 9895010b23..fafb10a228 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramChannel.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramChannel.swift @@ -6,6 +6,7 @@ public enum TelegramChannelPermission { case sendMessages case pinMessages case manageTopics + case createTopics case inviteMembers case editAllMessages case deleteAllMessages @@ -68,6 +69,23 @@ public extension TelegramChannel { return true } case .manageTopics: + if self.flags.contains(.isCreator) { + return true + } + if self.adminRights == nil { + return false + } + if let adminRights = self.adminRights, adminRights.rights.contains(.canManageTopics) { + return true + } + if let bannedRights = self.bannedRights, bannedRights.flags.contains(.banManageTopics) { + return false + } + if let defaultBannedRights = self.defaultBannedRights, defaultBannedRights.flags.contains(.banManageTopics) { + return false + } + return true + case .createTopics: if self.flags.contains(.isCreator) { return true } diff --git a/submodules/TelegramCore/Sources/ForumChannels.swift b/submodules/TelegramCore/Sources/ForumChannels.swift index b23502cd9f..21bf65483d 100644 --- a/submodules/TelegramCore/Sources/ForumChannels.swift +++ b/submodules/TelegramCore/Sources/ForumChannels.swift @@ -433,16 +433,69 @@ func _internal_setChannelForumMode(account: Account, peerId: PeerId, isForum: Bo } } +struct LoadMessageHistoryThreadsResult { + struct Item { + var threadId: Int64 + var data: MessageHistoryThreadData + var topMessage: Int32 + var unreadMentionsCount: Int32 + var unreadReactionsCount: Int32 + var index: StoredPeerThreadCombinedState.Index? + + init( + threadId: Int64, + data: MessageHistoryThreadData, + topMessage: Int32, + unreadMentionsCount: Int32, + unreadReactionsCount: Int32, + index: StoredPeerThreadCombinedState.Index + ) { + self.threadId = threadId + self.data = data + self.topMessage = topMessage + self.unreadMentionsCount = unreadMentionsCount + self.unreadReactionsCount = unreadReactionsCount + self.index = index + } + } + + var peerId: PeerId + var items: [Item] + var pinnedThreadIds: [Int64]? + var combinedState: PeerThreadCombinedState + var messages: [StoreMessage] + var users: [Api.User] + var chats: [Api.Chat] + + init( + peerId: PeerId, + items: [Item], + messages: [StoreMessage], + pinnedThreadIds: [Int64]?, + combinedState: PeerThreadCombinedState, + users: [Api.User], + chats: [Api.Chat] + ) { + self.peerId = peerId + self.items = items + self.messages = messages + self.pinnedThreadIds = pinnedThreadIds + self.combinedState = combinedState + self.users = users + self.chats = chats + } +} + enum LoadMessageHistoryThreadsError { case generic } -func _internal_loadMessageHistoryThreads(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, offsetIndex: StoredPeerThreadCombinedState.Index?, limit: Int) -> Signal { - let signal: Signal = postbox.transaction { transaction -> Api.InputChannel? in +func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, offsetIndex: StoredPeerThreadCombinedState.Index?, limit: Int) -> Signal { + let signal: Signal = postbox.transaction { transaction -> Api.InputChannel? in return transaction.getPeer(peerId).flatMap(apiInputChannel) } |> castError(LoadMessageHistoryThreadsError.self) - |> mapToSignal { inputChannel -> Signal in + |> mapToSignal { inputChannel -> Signal in guard let inputChannel = inputChannel else { return .fail(.generic) } @@ -455,7 +508,7 @@ func _internal_loadMessageHistoryThreads(accountPeerId: PeerId, postbox: Postbox offsetId = offsetIndex.messageId offsetTopic = Int32(clamping: offsetIndex.threadId) } - let signal: Signal = network.request(Api.functions.channels.getForumTopics( + let signal: Signal = network.request(Api.functions.channels.getForumTopics( flags: flags, channel: inputChannel, q: nil, @@ -467,130 +520,105 @@ func _internal_loadMessageHistoryThreads(accountPeerId: PeerId, postbox: Postbox |> mapError { _ -> LoadMessageHistoryThreadsError in return .generic } - |> mapToSignal { result -> Signal in - return postbox.transaction { transaction -> Void in + |> mapToSignal { result -> Signal in + switch result { + case let .forumTopics(_, _, topics, messages, chats, users, pts): + var items: [LoadMessageHistoryThreadsResult.Item] = [] var pinnedId: Int64? - switch result { - case let .forumTopics(_, _, topics, messages, chats, users, pts): - var peers: [Peer] = [] - var peerPresences: [PeerId: Api.User] = [:] - for chat in chats { - if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { - peers.append(groupOrChannel) + + let addedMessages = messages.compactMap { message -> StoreMessage? in + return StoreMessage(apiMessage: message) + } + + let _ = pts + var minIndex: StoredPeerThreadCombinedState.Index? + + for topic in topics { + switch topic { + case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft): + let _ = draft + + if (flags & (1 << 3)) != 0 { + pinnedId = Int64(id) } - } - for user in users { - let telegramUser = TelegramUser(user: user) - peers.append(telegramUser) - peerPresences[telegramUser.id] = user - } - updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in - return updated - }) - - updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences) - - let addedMessages = messages.compactMap { message -> StoreMessage? in - return StoreMessage(apiMessage: message) - } - - let _ = InternalAccountState.addMessages(transaction: transaction, messages: addedMessages, location: .Random) - - let _ = pts - var minIndex: StoredPeerThreadCombinedState.Index? - - for topic in topics { - switch topic { - case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft): - let _ = draft - - if (flags & (1 << 3)) != 0 { - pinnedId = Int64(id) + + let data = MessageHistoryThreadData( + creationDate: date, + isOwnedByMe: (flags & (1 << 1)) != 0, + author: fromId.peerId, + info: EngineMessageHistoryThread.Info( + title: title, + icon: iconEmojiId == 0 ? nil : iconEmojiId, + iconColor: iconColor + ), + incomingUnreadCount: unreadCount, + maxIncomingReadId: readInboxMaxId, + maxKnownMessageId: topMessage, + maxOutgoingReadId: readOutboxMaxId, + isClosed: (flags & (1 << 2)) != 0, + notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings) + ) + + var topTimestamp = date + for message in addedMessages { + if message.id.peerId == peerId && message.threadId == Int64(id) { + topTimestamp = max(topTimestamp, message.timestamp) } - - let data = MessageHistoryThreadData( - creationDate: date, - isOwnedByMe: (flags & (1 << 1)) != 0, - author: fromId.peerId, - info: EngineMessageHistoryThread.Info( - title: title, - icon: iconEmojiId == 0 ? nil : iconEmojiId, - iconColor: iconColor - ), - incomingUnreadCount: unreadCount, - maxIncomingReadId: readInboxMaxId, - maxKnownMessageId: topMessage, - maxOutgoingReadId: readOutboxMaxId, - isClosed: (flags & (1 << 2)) != 0, - notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings) - ) - guard let info = StoredMessageHistoryThreadInfo(data) else { - continue - } - transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: Int64(id), info: info) - - transaction.replaceMessageTagSummary(peerId: peerId, threadId: Int64(id), tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: unreadMentionsCount, maxId: topMessage) - transaction.replaceMessageTagSummary(peerId: peerId, threadId: Int64(id), tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: unreadReactionsCount, maxId: topMessage) - - if topMessage != 0 { - transaction.removeHole(peerId: peerId, threadId: Int64(id), namespace: Namespaces.Message.Cloud, space: .everywhere, range: topMessage ... (Int32.max - 1)) - } - - var topTimestamp = date - for message in addedMessages { - if message.id.peerId == peerId && message.threadId == Int64(id) { - topTimestamp = max(topTimestamp, message.timestamp) - - if case let .Id(messageId) = message.id { - for media in message.media { - if let action = media as? TelegramMediaAction { - if case .topicCreated = action.action { - transaction.removeHole(peerId: messageId.peerId, threadId: Int64(id), namespace: Namespaces.Message.Cloud, space: .everywhere, range: 1 ... messageId.id) - } - } - } - } - } - } - - let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: Int64(id), messageId: topMessage) - if let minIndexValue = minIndex { - if topicIndex < minIndexValue { - minIndex = topicIndex - } - } else { + } + + let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: Int64(id), messageId: topMessage) + if let minIndexValue = minIndex { + if topicIndex < minIndexValue { minIndex = topicIndex } - case .forumTopicDeleted: - break - } - } - - if offsetIndex != nil { - if let pinnedId = pinnedId { - transaction.setPeerPinnedThreads(peerId: peerId, threadIds: [pinnedId]) } else { - transaction.setPeerPinnedThreads(peerId: peerId, threadIds: []) + minIndex = topicIndex } - } - - var nextIndex: StoredPeerThreadCombinedState.Index - if topics.count != 0 { - nextIndex = minIndex ?? StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1) - } else { - nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1) - } - if let offsetIndex = offsetIndex, nextIndex == offsetIndex { - nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1) - } - - if let entry = StoredPeerThreadCombinedState(PeerThreadCombinedState(validIndexBoundary: nextIndex)) { - transaction.setPeerThreadCombinedState(peerId: peerId, state: entry) + + items.append(LoadMessageHistoryThreadsResult.Item( + threadId: Int64(id), + data: data, + topMessage: topMessage, + unreadMentionsCount: unreadMentionsCount, + unreadReactionsCount: unreadReactionsCount, + index: topicIndex + )) + case .forumTopicDeleted: + break } } + + var pinnedThreadIds: [Int64]? + if offsetIndex == nil { + if let pinnedId = pinnedId { + pinnedThreadIds = [pinnedId] + } else { + pinnedThreadIds = [] + } + } + + var nextIndex: StoredPeerThreadCombinedState.Index + if topics.count != 0 { + nextIndex = minIndex ?? StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1) + } else { + nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1) + } + if let offsetIndex = offsetIndex, nextIndex == offsetIndex { + nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1) + } + + let combinedState = PeerThreadCombinedState(validIndexBoundary: nextIndex) + + return .single(LoadMessageHistoryThreadsResult( + peerId: peerId, + items: items, + messages: addedMessages, + pinnedThreadIds: pinnedThreadIds, + combinedState: combinedState, + users: users, + chats: chats + )) } - |> castError(LoadMessageHistoryThreadsError.self) - |> ignoreValues } return signal } @@ -598,6 +626,66 @@ func _internal_loadMessageHistoryThreads(accountPeerId: PeerId, postbox: Postbox return signal } +func applyLoadMessageHistoryThreadsResults(accountPeerId: PeerId, transaction: Transaction, results: [LoadMessageHistoryThreadsResult]) { + for result in results { + var peers: [Peer] = [] + var peerPresences: [PeerId: Api.User] = [:] + for chat in result.chats { + if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { + peers.append(groupOrChannel) + } + } + for user in result.users { + let telegramUser = TelegramUser(user: user) + peers.append(telegramUser) + peerPresences[telegramUser.id] = user + } + updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in + return updated + }) + + updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences) + + let _ = InternalAccountState.addMessages(transaction: transaction, messages: result.messages, location: .Random) + + for item in result.items { + guard let info = StoredMessageHistoryThreadInfo(item.data) else { + continue + } + transaction.setMessageHistoryThreadInfo(peerId: result.peerId, threadId: item.threadId, info: info) + + transaction.replaceMessageTagSummary(peerId: result.peerId, threadId: item.threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: item.unreadMentionsCount, maxId: item.topMessage) + transaction.replaceMessageTagSummary(peerId: result.peerId, threadId: item.threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, count: item.unreadReactionsCount, maxId: item.topMessage) + + if item.topMessage != 0 { + transaction.removeHole(peerId: result.peerId, threadId: item.threadId, namespace: Namespaces.Message.Cloud, space: .everywhere, range: item.topMessage ... (Int32.max - 1)) + } + + for message in result.messages { + if message.id.peerId == result.peerId && message.threadId == item.threadId { + if case let .Id(messageId) = message.id { + for media in message.media { + if let action = media as? TelegramMediaAction { + if case .topicCreated = action.action { + transaction.removeHole(peerId: messageId.peerId, threadId: item.threadId, namespace: Namespaces.Message.Cloud, space: .everywhere, range: 1 ... messageId.id) + } + } + } + } + } + } + } + + if let pinnedThreadIds = result.pinnedThreadIds { + transaction.setPeerPinnedThreads(peerId: result.peerId, threadIds: pinnedThreadIds) + } + + if let entry = StoredPeerThreadCombinedState(result.combinedState) { + transaction.setPeerThreadCombinedState(peerId: result.peerId, state: entry) + } + } +} + public extension EngineMessageHistoryThread { struct NotificationException: Equatable { public var threadId: Int64 diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 47cc5c9d71..96da863315 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -527,7 +527,7 @@ func initialStateWithDifference(postbox: Postbox, difference: Api.updates.Differ } } -func finalStateWithUpdateGroups(postbox: Postbox, network: Network, state: AccountMutableState, groups: [UpdateGroup]) -> Signal { +func finalStateWithUpdateGroups(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, groups: [UpdateGroup]) -> Signal { var updatedState = state var hadReset = false @@ -651,10 +651,10 @@ func finalStateWithUpdateGroups(postbox: Postbox, network: Network, state: Accou collectedUpdates.append(Api.Update.updateDeleteChannelMessages(channelId: channelId, messages: [], pts: pts, ptsCount: ptsCount)) } - return finalStateWithUpdates(postbox: postbox, network: network, state: updatedState, updates: collectedUpdates, shouldPoll: hadReset, missingUpdates: !ptsUpdatesAfterHole.isEmpty || !qtsUpdatesAfterHole.isEmpty || !seqGroupsAfterHole.isEmpty, shouldResetChannels: false, updatesDate: updatesDate) + return finalStateWithUpdates(accountPeerId: accountPeerId, postbox: postbox, network: network, state: updatedState, updates: collectedUpdates, shouldPoll: hadReset, missingUpdates: !ptsUpdatesAfterHole.isEmpty || !qtsUpdatesAfterHole.isEmpty || !seqGroupsAfterHole.isEmpty, shouldResetChannels: false, updatesDate: updatesDate) } -func finalStateWithDifference(postbox: Postbox, network: Network, state: AccountMutableState, difference: Api.updates.Difference) -> Signal { +func finalStateWithDifference(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, difference: Api.updates.Difference) -> Signal { var updatedState = state var messages: [Api.Message] = [] @@ -709,7 +709,7 @@ func finalStateWithDifference(postbox: Postbox, network: Network, state: Account updatedState.addSecretMessages(encryptedMessages) } - return finalStateWithUpdates(postbox: postbox, network: network, state: updatedState, updates: updates, shouldPoll: false, missingUpdates: false, shouldResetChannels: true, updatesDate: nil) + return finalStateWithUpdates(accountPeerId: accountPeerId, postbox: postbox, network: network, state: updatedState, updates: updates, shouldPoll: false, missingUpdates: false, shouldResetChannels: true, updatesDate: nil) } private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] { @@ -830,15 +830,15 @@ private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] { return result } -private func finalStateWithUpdates(postbox: Postbox, network: Network, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool, shouldResetChannels: Bool, updatesDate: Int32?) -> Signal { +private func finalStateWithUpdates(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool, shouldResetChannels: Bool, updatesDate: Int32?) -> Signal { return network.currentGlobalTime |> take(1) |> mapToSignal { serverTime -> Signal in - return finalStateWithUpdatesAndServerTime(postbox: postbox, network: network, state: state, updates: updates, shouldPoll: shouldPoll, missingUpdates: missingUpdates, shouldResetChannels: shouldResetChannels, updatesDate: updatesDate, serverTime: Int32(serverTime)) + return finalStateWithUpdatesAndServerTime(accountPeerId: accountPeerId, postbox: postbox, network: network, state: state, updates: updates, shouldPoll: shouldPoll, missingUpdates: missingUpdates, shouldResetChannels: shouldResetChannels, updatesDate: updatesDate, serverTime: Int32(serverTime)) } } -private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Network, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool, shouldResetChannels: Bool, updatesDate: Int32?, serverTime: Int32) -> Signal { +private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox: Postbox, network: Network, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool, shouldResetChannels: Bool, updatesDate: Int32?, serverTime: Int32) -> Signal { var updatedState = state var channelsToPoll = Set() @@ -1585,7 +1585,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo } } if !channelPeers.isEmpty { - let resetSignal = resetChannels(postbox: postbox, network: network, peers: channelPeers, state: updatedState) + let resetSignal = resetChannels(accountPeerId: accountPeerId, postbox: postbox, network: network, peers: channelPeers, state: updatedState) |> map { resultState -> (AccountMutableState, Bool, Int32?) in return (resultState, true, nil) } @@ -1596,7 +1596,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo } else { for peerId in channelsToPoll.union(missingUpdatesFromChannels) { if let peer = updatedState.peers[peerId] { - pollChannelSignals.append(pollChannel(postbox: postbox, network: network, peer: peer, state: updatedState.branch())) + pollChannelSignals.append(pollChannel(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer, state: updatedState.branch())) } else { Logger.shared.log("State", "can't poll channel \(peerId): no peer found") } @@ -2220,7 +2220,7 @@ private func resolveMissingPeerChatInfos(network: Network, state: AccountMutable } } -func pollChannelOnce(postbox: Postbox, network: Network, peerId: PeerId, stateManager: AccountStateManager, delayCompletion: Bool) -> Signal { +func pollChannelOnce(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, stateManager: AccountStateManager, delayCompletion: Bool) -> Signal { return postbox.transaction { transaction -> Signal in guard let accountState = (transaction.getState() as? AuthorizedAccountState)?.state, let peer = transaction.getPeer(peerId) else { if delayCompletion { @@ -2251,7 +2251,7 @@ func pollChannelOnce(postbox: Postbox, network: Network, peerId: PeerId, stateMa } } let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:]) - return pollChannel(postbox: postbox, network: network, peer: peer, state: initialState) + return pollChannel(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer, state: initialState) |> mapToSignal { (finalState, _, timeout) -> Signal in return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState) |> mapToSignal { resultingState -> Signal in @@ -2279,7 +2279,7 @@ func pollChannelOnce(postbox: Postbox, network: Network, peerId: PeerId, stateMa |> switchToLatest } -public func standalonePollChannelOnce(postbox: Postbox, network: Network, peerId: PeerId, stateManager: AccountStateManager) -> Signal { +public func standalonePollChannelOnce(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, stateManager: AccountStateManager) -> Signal { return postbox.transaction { transaction -> Signal in guard let accountState = (transaction.getState() as? AuthorizedAccountState)?.state, let peer = transaction.getPeer(peerId) else { return .complete() @@ -2305,7 +2305,7 @@ public func standalonePollChannelOnce(postbox: Postbox, network: Network, peerId } } let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:]) - return pollChannel(postbox: postbox, network: network, peer: peer, state: initialState) + return pollChannel(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer, state: initialState) |> mapToSignal { (finalState, _, timeout) -> Signal in return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState) |> mapToSignal { resultingState -> Signal in @@ -2322,13 +2322,13 @@ public func standalonePollChannelOnce(postbox: Postbox, network: Network, peerId |> switchToLatest } -func keepPollingChannel(postbox: Postbox, network: Network, peerId: PeerId, stateManager: AccountStateManager) -> Signal { - return pollChannelOnce(postbox: postbox, network: network, peerId: peerId, stateManager: stateManager, delayCompletion: true) +func keepPollingChannel(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, stateManager: AccountStateManager) -> Signal { + return pollChannelOnce(accountPeerId: accountPeerId, postbox: postbox, network: network, peerId: peerId, stateManager: stateManager, delayCompletion: true) |> restart |> delay(1.0, queue: .concurrentDefaultQueue()) } -private func resetChannels(postbox: Postbox, network: Network, peers: [Peer], state: AccountMutableState) -> Signal { +private func resetChannels(accountPeerId: PeerId, postbox: Postbox, network: Network, peers: [Peer], state: AccountMutableState) -> Signal { var inputPeers: [Api.InputDialogPeer] = [] for peer in peers { if let inputPeer = apiInputPeer(peer) { @@ -2358,6 +2358,8 @@ private func resetChannels(postbox: Postbox, network: Network, peers: [Peer], st var channelSynchronizedUntilMessage: [PeerId: MessageId.Id] = [:] var notificationSettings: [PeerId: TelegramPeerNotificationSettings] = [:] + var resetForumTopics = Set() + if let result = result { switch result { case let .peerDialogs(dialogs, messages, chats, users, _): @@ -2415,7 +2417,7 @@ private func resetChannels(postbox: Postbox, network: Network, peers: [Peer], st updatedState.updatePeerChatInclusion(peerId: peerId, groupId: groupId, changedGroup: false) - updatedState.resetForumTopicLists[peerId] = [] + resetForumTopics.insert(peerId) } for message in messages { @@ -2480,16 +2482,39 @@ private func resetChannels(postbox: Postbox, network: Network, peers: [Peer], st updatedState.updateNotificationSettings(.peer(peerId: peerId, threadId: nil), notificationSettings: settings) } - // TODO: delete messages later than top - - return resolveAssociatedMessages(postbox: postbox, network: network, state: updatedState) - |> mapToSignal { resultingState -> Signal in - return .single(resultingState) + var resetTopicsSignals: [Signal] = [] + for resetForumTopicPeerId in resetForumTopics { + resetTopicsSignals.append(_internal_requestMessageHistoryThreads(accountPeerId: accountPeerId, postbox: postbox, network: network, peerId: resetForumTopicPeerId, offsetIndex: nil, limit: 20) + |> map(StateResetForumTopics.result) + |> `catch` { _ -> Signal in + return .single(.error(resetForumTopicPeerId)) + }) + } + return combineLatest(resetTopicsSignals) + |> mapToSignal { results -> Signal in + var updatedState = updatedState + + for result in results { + let peerId: PeerId + switch result { + case let .result(item): + peerId = item.peerId + case let .error(peerIdValue): + peerId = peerIdValue + } + updatedState.resetForumTopicLists[peerId] = result + } + + // TODO: delete messages later than top + return resolveAssociatedMessages(postbox: postbox, network: network, state: updatedState) + |> mapToSignal { resultingState -> Signal in + return .single(resultingState) + } } } } -private func pollChannel(postbox: Postbox, network: Network, peer: Peer, state: AccountMutableState) -> Signal<(AccountMutableState, Bool, Int32?), NoError> { +private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Network, peer: Peer, state: AccountMutableState) -> Signal<(AccountMutableState, Bool, Int32?), NoError> { if let inputChannel = apiInputChannel(peer) { let limit: Int32 #if DEBUG @@ -2659,6 +2684,8 @@ private func pollChannel(postbox: Postbox, network: Network, peer: Peer, state: break } + var resetForumTopics = Set() + if let (peer, pts, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount) = parameters { updatedState.updateChannelState(peer.peerId, pts: pts) updatedState.updateChannelInvalidationPts(peer.peerId, invalidationPts: pts) @@ -2667,7 +2694,7 @@ private func pollChannel(postbox: Postbox, network: Network, peer: Peer, state: updatedState.mergeUsers(users) updatedState.setNeedsHoleFromPreviousState(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, validateChannelPts: pts) - updatedState.resetForumTopicLists[peer.peerId] = [] + resetForumTopics.insert(peer.peerId) for apiMessage in messages { if var message = StoreMessage(apiMessage: apiMessage) { @@ -2700,7 +2727,31 @@ private func pollChannel(postbox: Postbox, network: Network, peer: Peer, state: assertionFailure() } - return .single((updatedState, true, apiTimeout)) + var resetTopicsSignals: [Signal] = [] + for resetForumTopicPeerId in resetForumTopics { + resetTopicsSignals.append(_internal_requestMessageHistoryThreads(accountPeerId: accountPeerId, postbox: postbox, network: network, peerId: resetForumTopicPeerId, offsetIndex: nil, limit: 20) + |> map(StateResetForumTopics.result) + |> `catch` { _ -> Signal in + return .single(.error(resetForumTopicPeerId)) + }) + } + return combineLatest(resetTopicsSignals) + |> mapToSignal { results -> Signal<(AccountMutableState, Bool, Int32?), NoError> in + var updatedState = updatedState + + for result in results { + let peerId: PeerId + switch result { + case let .result(item): + peerId = item.peerId + case let .error(peerIdValue): + peerId = peerIdValue + } + updatedState.resetForumTopicLists[peerId] = result + } + + return .single((updatedState, true, apiTimeout)) + } } } } else { @@ -4039,7 +4090,8 @@ func replayFinalState( } } - for (peerId, _) in finalState.state.resetForumTopicLists { + var resetForumTopicResults: [LoadMessageHistoryThreadsResult] = [] + for (peerId, result) in finalState.state.resetForumTopicLists { for item in transaction.getMessageHistoryThreadIndex(peerId: peerId, limit: 10000) { let holeLowerBound = transaction.holeLowerBoundForTopValidRange(peerId: peerId, threadId: item.threadId, namespace: Namespaces.Message.Cloud, space: .everywhere) @@ -4049,7 +4101,15 @@ func replayFinalState( } } - transaction.setPeerThreadCombinedState(peerId: peerId, state: nil) + switch result { + case let .result(value): + resetForumTopicResults.append(value) + case .error: + transaction.setPeerThreadCombinedState(peerId: peerId, state: nil) + } + } + if !resetForumTopicResults.isEmpty { + applyLoadMessageHistoryThreadsResults(accountPeerId: accountPeerId, transaction: transaction, results: resetForumTopicResults) } //TODO Please do not forget fix holes space. diff --git a/submodules/TelegramCore/Sources/State/AccountStateManager.swift b/submodules/TelegramCore/Sources/State/AccountStateManager.swift index 44894d7877..a735ec0d9c 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManager.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManager.swift @@ -468,7 +468,7 @@ public final class AccountStateManager { Logger.shared.log("State", "pollDifference initial state \(authorizedState) != current state \(state.initialState.state)") return .single((nil, nil, false)) } else { - return finalStateWithDifference(postbox: postbox, network: network, state: state, difference: difference) + return finalStateWithDifference(accountPeerId: accountPeerId, postbox: postbox, network: network, state: state, difference: difference) |> deliverOn(queue) |> mapToSignal { finalState -> Signal<(difference: Api.updates.Difference?, finalStatte: AccountReplayedFinalState?, skipBecauseOfError: Bool), NoError> in if !finalState.state.preCachedResources.isEmpty { @@ -581,7 +581,7 @@ public final class AccountStateManager { let queue = self.queue let signal = initialStateWithUpdateGroups(postbox: postbox, groups: groups) |> mapToSignal { [weak self] state -> Signal<(AccountReplayedFinalState?, AccountFinalState), NoError> in - return finalStateWithUpdateGroups(postbox: postbox, network: network, state: state, groups: groups) + return finalStateWithUpdateGroups(accountPeerId: accountPeerId, postbox: postbox, network: network, state: state, groups: groups) |> deliverOn(queue) |> mapToSignal { finalState in if !finalState.discard && !finalState.state.preCachedResources.isEmpty { @@ -958,7 +958,7 @@ public final class AccountStateManager { Logger.shared.log("State", "pollDifference initial state \(authorizedState) != current state \(state.initialState.state)") return .single((nil, nil, false)) } else { - return finalStateWithDifference(postbox: postbox, network: network, state: state, difference: difference) + return finalStateWithDifference(accountPeerId: accountPeerId, postbox: postbox, network: network, state: state, difference: difference) |> deliverOn(queue) |> mapToSignal { finalState -> Signal<(difference: Api.updates.Difference?, finalStatte: AccountReplayedFinalState?, skipBecauseOfError: Bool), NoError> in if !finalState.state.preCachedResources.isEmpty { diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index 97a42fef14..3f6babaeae 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -1477,7 +1477,7 @@ public final class AccountViewTracker { if context.subscribers.isEmpty { if let account = self.account { let queue = self.queue - context.disposable.set(keepPollingChannel(postbox: account.postbox, network: account.network, peerId: peerId, stateManager: account.stateManager).start(next: { [weak context] isValidForTimeout in + context.disposable.set(keepPollingChannel(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, peerId: peerId, stateManager: account.stateManager).start(next: { [weak context] isValidForTimeout in queue.async { guard let context = context else { return diff --git a/submodules/TelegramCore/Sources/State/ManagedChatListHoles.swift b/submodules/TelegramCore/Sources/State/ManagedChatListHoles.swift index d452e38546..8f115d7816 100644 --- a/submodules/TelegramCore/Sources/State/ManagedChatListHoles.swift +++ b/submodules/TelegramCore/Sources/State/ManagedChatListHoles.swift @@ -143,7 +143,14 @@ func managedForumTopicListHoles(network: Network, postbox: Postbox, accountPeerI } for (entry, disposable) in added { - disposable.set(_internal_loadMessageHistoryThreads(accountPeerId: accountPeerId, postbox: postbox, network: network, peerId: entry.peerId, offsetIndex: entry.index, limit: 100).start()) + disposable.set((_internal_requestMessageHistoryThreads(accountPeerId: accountPeerId, postbox: postbox, network: network, peerId: entry.peerId, offsetIndex: entry.index, limit: 100) + |> mapToSignal { result -> Signal in + return postbox.transaction { transaction in + return applyLoadMessageHistoryThreadsResults(accountPeerId: accountPeerId, transaction: transaction, results: [result]) + } + |> castError(LoadMessageHistoryThreadsError.self) + |> ignoreValues + }).start()) } }) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/ReplyThreadHistory.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ReplyThreadHistory.swift index ee6ed31c6f..2c914dc948 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/ReplyThreadHistory.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ReplyThreadHistory.swift @@ -344,6 +344,16 @@ private class ReplyThreadHistoryContextImpl { data.maxIncomingReadId = messageIndex.id.id } + if let topMessageIndex = transaction.getMessageHistoryThreadTopMessage(peerId: messageId.peerId, threadId: Int64(messageId.id), namespaces: Set([Namespaces.Message.Cloud])) { + if messageIndex.id.id >= topMessageIndex.id.id { + let containingHole = transaction.getThreadIndexHole(peerId: messageId.peerId, threadId: Int64(messageId.id), namespace: topMessageIndex.id.namespace, containing: topMessageIndex.id.id) + if let _ = containingHole[.everywhere] { + } else { + data.incomingUnreadCount = 0 + } + } + } + data.maxKnownMessageId = max(data.maxKnownMessageId, messageIndex.id.id) if let entry = StoredMessageHistoryThreadInfo(data) { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index 08698d3aeb..4b1d5b6328 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -775,8 +775,11 @@ public extension TelegramEngine { return _internal_deleteNotificationSound(account: self.account, fileId: fileId) } - public func ensurePeerIsLocallyAvailable(peer: EnginePeer) -> Signal { + public func ensurePeerIsLocallyAvailable(peer: EnginePeer) -> Signal { return _internal_storedMessageFromSearchPeer(account: self.account, peer: peer._asPeer()) + |> map { result -> EnginePeer in + return EnginePeer(result) + } } public func ensurePeersAreLocallyAvailable(peers: [EnginePeer]) -> Signal { diff --git a/submodules/TelegramCore/Sources/Utils/StoredMessageFromSearchPeer.swift b/submodules/TelegramCore/Sources/Utils/StoredMessageFromSearchPeer.swift index a4d155e0a3..81aa77a175 100644 --- a/submodules/TelegramCore/Sources/Utils/StoredMessageFromSearchPeer.swift +++ b/submodules/TelegramCore/Sources/Utils/StoredMessageFromSearchPeer.swift @@ -2,17 +2,21 @@ import Foundation import Postbox import SwiftSignalKit -func _internal_storedMessageFromSearchPeer(account: Account, peer: Peer) -> Signal { - return account.postbox.transaction { transaction -> PeerId in +func _internal_storedMessageFromSearchPeer(account: Account, peer: Peer) -> Signal { + return account.postbox.transaction { transaction -> Peer in if transaction.getPeer(peer.id) == nil { updatePeers(transaction: transaction, peers: [peer], update: { previousPeer, updatedPeer in return updatedPeer }) } if let group = transaction.getPeer(peer.id) as? TelegramGroup, let migrationReference = group.migrationReference { - return migrationReference.peerId + if let migrationPeer = transaction.getPeer(migrationReference.peerId) { + return migrationPeer + } else { + return peer + } } - return peer.id + return peer } } diff --git a/submodules/TelegramUI/Sources/ApplicationContext.swift b/submodules/TelegramUI/Sources/ApplicationContext.swift index 6e22927650..0049e43537 100644 --- a/submodules/TelegramUI/Sources/ApplicationContext.swift +++ b/submodules/TelegramUI/Sources/ApplicationContext.swift @@ -313,13 +313,16 @@ final class AuthorizedApplicationContext { if let strongSelf = self, let (messages, _, notify, threadData) = messageList.last, let firstMessage = messages.first { if UIApplication.shared.applicationState == .active { - let chatLocation: ChatLocation + let chatLocation: NavigateToChatControllerParams.Location if let _ = threadData, let threadId = firstMessage.threadId { - chatLocation = .replyThread(message: ChatReplyThreadMessage( + chatLocation = .replyThread(ChatReplyThreadMessage( messageId: MessageId(peerId: firstMessage.id.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false )) } else { - chatLocation = .peer(id: firstMessage.id.peerId) + guard let peer = firstMessage.peers[firstMessage.id.peerId] else { + return + } + chatLocation = .peer(EnginePeer(peer)) } var chatIsVisible = false @@ -445,7 +448,7 @@ final class AuthorizedApplicationContext { return false }, expandAction: { expandData in if let strongSelf = self { - let chatController = ChatControllerImpl(context: strongSelf.context, chatLocation: chatLocation, mode: .overlay(strongSelf.rootController)) + let chatController = ChatControllerImpl(context: strongSelf.context, chatLocation: chatLocation.asChatLocation, mode: .overlay(strongSelf.rootController)) chatController.presentationArguments = ChatControllerOverlayPresentationData(expandData: expandData()) (strongSelf.rootController.viewControllers.last as? ViewController)?.present(chatController, in: .window(.root), with: ChatControllerOverlayPresentationData(expandData: expandData())) } @@ -781,7 +784,14 @@ final class AuthorizedApplicationContext { } let navigateToMessage = { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: strongSelf.rootController, context: strongSelf.context, chatLocation: .peer(id: messageId.peerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil))) + let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: messageId.peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: strongSelf.rootController, context: strongSelf.context, chatLocation: .peer(peer), subject: .message(id: .id(messageId), highlight: true, timecode: nil))) + }) } if chatIsVisible { @@ -860,16 +870,23 @@ final class AuthorizedApplicationContext { if visiblePeerId != peerId || messageId != nil { if self.rootController.rootTabController != nil { - let chatLocation: ChatLocation - if let threadId = threadId { - chatLocation = .replyThread(message: ChatReplyThreadMessage( - messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false - )) - } else { - chatLocation = .peer(id: peerId) - } - - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: self.rootController, context: self.context, chatLocation: chatLocation, subject: messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) }, activateInput: activateInput ? .text : nil)) + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + + let chatLocation: NavigateToChatControllerParams.Location + if let threadId = threadId { + chatLocation = .replyThread(ChatReplyThreadMessage( + messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false + )) + } else { + chatLocation = .peer(peer) + } + + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: self.rootController, context: self.context, chatLocation: chatLocation, subject: messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) }, activateInput: activateInput ? .text : nil)) + }) } else { self.scheduledOpenChatWithPeerId = (peerId, messageId, activateInput) } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index f775a01ac9..afbbb25934 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -6232,7 +6232,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let data = view.info?.data.get(MessageHistoryThreadData.self) else { return nil } - return ChatPresentationInterfaceState.ThreadData(title: data.info.title, icon: data.info.icon, iconColor: data.info.iconColor, isOwn: data.isOwnedByMe, isClosed: data.isClosed) + return ChatPresentationInterfaceState.ThreadData(title: data.info.title, icon: data.info.icon, iconColor: data.info.iconColor, isOwnedByMe: data.isOwnedByMe, isClosed: data.isClosed) } |> distinctUntilChanged } else { @@ -7931,9 +7931,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self else { return } - if let navigationController = strongSelf.effectiveNavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId), subject: nil, keepStack: .always)) - } + let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + guard let strongSelf = self else { + return + } + + if let navigationController = strongSelf.effectiveNavigationController { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), subject: nil, keepStack: .always)) + } + }) }, navigateToProfile: { [weak self] peerId in guard let strongSelf = self else { return @@ -9145,7 +9155,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let navigationController = strongSelf.effectiveNavigationController { let subject: ChatControllerSubject? = sourceMessageId.flatMap { ChatControllerSubject.message(id: .id($0), highlight: true, timecode: nil) } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .replyThread(message: replyThreadResult), subject: subject, keepStack: .always)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .replyThread(replyThreadResult), subject: subject, keepStack: .always)) } }, activatePinnedListPreview: { [weak self] node, gesture in guard let strongSelf = self else { @@ -9761,7 +9771,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G updatedChatNavigationStack.insert(peerId, at: 0) } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), animated: false, chatListFilter: nextFolderId, chatNavigationStack: updatedChatNavigationStack, completion: { nextController in + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), animated: false, chatListFilter: nextFolderId, chatNavigationStack: updatedChatNavigationStack, completion: { nextController in (nextController as! ChatControllerImpl).animateFromPreviousController(snapshotState: snapshotState) })) } @@ -9881,7 +9891,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G updatedChatNavigationStack.removeSubrange(0 ..< (index + 1)) } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), useBackAnimation: true, animated: true, chatListFilter: nextFolderId, chatNavigationStack: updatedChatNavigationStack, completion: { nextController in + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), useBackAnimation: true, animated: true, chatListFilter: nextFolderId, chatNavigationStack: updatedChatNavigationStack, completion: { nextController in let _ = nextController })) }))) @@ -14714,7 +14724,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G statusController?.dismiss() } - let chatLocation: ChatLocation = .replyThread(message: result.message) + let chatLocation: NavigateToChatControllerParams.Location = .replyThread(result.message) let subject: ChatControllerSubject? if let atMessageId = atMessageId { @@ -14781,14 +14791,27 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } if isPinnedMessages, let messageId = messageLocation.messageId { - if let navigationController = self.effectiveNavigationController { - self.dismiss() - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: messageId.peerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always)) - } + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: messageId.peerId)) + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let self, let peer = peer else { + return + } + + if let navigationController = self.effectiveNavigationController { + self.dismiss() + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always)) + } + }) } else if case let .peer(peerId) = self.chatLocation, let messageId = messageLocation.messageId, (messageId.peerId != peerId && !forceInCurrentChat) || (isScheduledMessages && messageId.id != 0 && !Namespaces.Message.allScheduled.contains(messageId.namespace)) { - if let navigationController = self.effectiveNavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: messageId.peerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always)) - } + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: messageId.peerId)) + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let self, let peer = peer else { + return + } + if let navigationController = self.effectiveNavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always)) + } + }) } else if forceInCurrentChat { if let _ = fromId, let fromIndex = fromIndex, rememberInStack { self.historyNavigationStack.add(fromIndex) @@ -14967,9 +14990,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: index, animated: animated, scrollPosition: scrollPosition) completion?() } else { - if let navigationController = strongSelf.effectiveNavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: messageLocation.peerId), subject: messageLocation.messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) })) - } + let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: messageLocation.peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let strongSelf = self, let peer = peer else { + return + } + + if let navigationController = strongSelf.effectiveNavigationController { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), subject: messageLocation.messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) })) + } + }) completion?() } } @@ -14979,10 +15009,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } })) } else { - if let navigationController = self.effectiveNavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: messageLocation.peerId), subject: messageLocation.messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) })) - } - completion?() + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: messageLocation.peerId)) + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let self, let peer = peer else { + return + } + if let navigationController = self.effectiveNavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), subject: messageLocation.messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) })) + } + completion?() + }) } } } else { @@ -15173,8 +15209,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else if peerId == strongSelf.context.account.peerId { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: true, text: messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many), elevatedLayout: false, animateInAsReplacement: true, action: { [weak self] value in - if case .info = value, let strongSelf = self, let navigationController = strongSelf.effectiveNavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: context.account.peerId), keepStack: .always, purposefulAction: {}, peekData: nil)) + if case .info = value, let strongSelf = self { + let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: strongSelf.context.account.peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let strongSelf = self, let peer = peer, let navigationController = strongSelf.effectiveNavigationController else { + return + } + + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), keepStack: .always, purposefulAction: {}, peekData: nil)) + }) return true } return false @@ -15349,7 +15392,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) |> deliverOnMainQueue).start(completed: { [weak self] in if let strongSelf = self, let navigationController = strongSelf.effectiveNavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), subject: subject, updateTextInputState: textInputState, peekData: peekData)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), subject: subject, updateTextInputState: textInputState, peekData: peekData)) } }) } else { @@ -15359,7 +15402,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.effectiveNavigationController?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(id: peer.id), botStart: botStart)) case let .withAttachBot(attachBotStart): if let navigationController = self.effectiveNavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: peer.id), attachBotStart: attachBotStart)) + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), attachBotStart: attachBotStart)) } } } @@ -15815,7 +15858,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if case let .channel(channel) = peerId, channel.flags.contains(.isForum) { strongSelf.context.sharedContext.navigateToForumChannel(context: strongSelf.context, peerId: peerId.id, navigationController: navigationController) } else { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId.id), subject: subject, keepStack: .always, peekData: peekData)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: subject, keepStack: .always, peekData: peekData)) } } case .info: @@ -15834,11 +15877,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G $0.updatedBotStartPayload(startPayload.payload) }) } else if let navigationController = strongSelf.effectiveNavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId.id), botStart: startPayload, keepStack: .always)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), botStart: startPayload, keepStack: .always)) } case let .withAttachBot(attachBotStart): if let navigationController = strongSelf.effectiveNavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId.id), attachBotStart: attachBotStart)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), attachBotStart: attachBotStart)) } default: break diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 9608275a83..21dc5eb086 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -992,19 +992,26 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return } - if suggestSavedMessages, let navigationController = controllerInteraction.navigationController() { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams( - navigationController: navigationController, - chatController: nil, - context: context, - chatLocation: .peer(id: context.account.peerId), - subject: nil, - updateTextInputState: nil, - activateInput: .entityInput, - keepStack: .always, - completion: { _ in - }) - ) + if suggestSavedMessages { + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer, let navigationController = controllerInteraction.navigationController() else { + return + } + + context.sharedContext.navigateToChatController(NavigateToChatControllerParams( + navigationController: navigationController, + chatController: nil, + context: context, + chatLocation: .peer(peer), + subject: nil, + updateTextInputState: nil, + activateInput: .entityInput, + keepStack: .always, + completion: { _ in + }) + ) + }) } else { var replaceImpl: ((ViewController) -> Void)? let controller = PremiumDemoScreen(context: context, subject: .animatedEmoji, action: { diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index 4b1b624900..ea8f5b1c54 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -264,9 +264,9 @@ func canReplyInChat(_ chatPresentationInterfaceState: ChatPresentationInterfaceS var canManage = false if channel.flags.contains(.isCreator) { canManage = true - } else if channel.adminRights != nil { + } else if channel.hasPermission(.manageTopics) { canManage = true - } else if threadData.isOwn { + } else if threadData.isOwnedByMe { canManage = true } @@ -1510,7 +1510,10 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState guard let navigationController = controllerInteraction.navigationController() else { return } - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: messages[0].id.peerId), subject: .message(id: .id(messages[0].id), highlight: true, timecode: nil), useExisting: true)) + guard let peer = messages[0].peers[messages[0].id.peerId] else { + return + } + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(EnginePeer(peer)), subject: .message(id: .id(messages[0].id), highlight: true, timecode: nil), useExisting: true)) }) }))) } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift index 40806f2152..c3fe327cdc 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift @@ -164,9 +164,9 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState var canManage = false if channel.flags.contains(.isCreator) { canManage = true - } else if channel.adminRights != nil { + } else if channel.hasPermission(.manageTopics) { canManage = true - } else if threadData.isOwn { + } else if threadData.isOwnedByMe { canManage = true } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift b/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift index fd66a5fd07..6a66e43666 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift @@ -63,9 +63,9 @@ func titlePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceStat var canManage = false if channel.flags.contains(.isCreator) { canManage = true - } else if channel.adminRights != nil { + } else if channel.hasPermission(.manageTopics) { canManage = true - } else if threadData.isOwn { + } else if threadData.isOwnedByMe { canManage = true } diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index 29b47974fd..c75190e4b3 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -773,7 +773,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { self.navigationActionDisposable.set((peerSignal |> take(1) |> deliverOnMainQueue).start(next: { [weak self] peer in if let strongSelf = self, let peer = peer { if peer is TelegramChannel, let navigationController = strongSelf.getNavigationController() { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), peekData: peekData, animated: true)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)), peekData: peekData, animated: true)) } else { if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) { strongSelf.pushController(infoController) @@ -895,11 +895,11 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { break case let .channelMessage(peer, messageId, timecode): if let navigationController = strongSelf.getNavigationController() { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), subject: .message(id: .id(messageId), highlight: true, timecode: timecode))) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)), subject: .message(id: .id(messageId), highlight: true, timecode: timecode))) } case let .replyThreadMessage(replyThreadMessage, messageId): if let navigationController = strongSelf.getNavigationController() { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .replyThread(message: replyThreadMessage), subject: .message(id: .id(messageId), highlight: true, timecode: nil))) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .replyThread(replyThreadMessage), subject: .message(id: .id(messageId), highlight: true, timecode: nil))) } case let .replyThread(messageId): if let navigationController = strongSelf.getNavigationController() { diff --git a/submodules/TelegramUI/Sources/ChatReportPeerTitlePanelNode.swift b/submodules/TelegramUI/Sources/ChatReportPeerTitlePanelNode.swift index 5bf860e352..593eff609c 100644 --- a/submodules/TelegramUI/Sources/ChatReportPeerTitlePanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatReportPeerTitlePanelNode.swift @@ -104,9 +104,9 @@ private func peerButtons(_ state: ChatPresentationInterfaceState) -> [ChatReport var canManage = false if channel.flags.contains(.isCreator) { canManage = true - } else if channel.adminRights != nil { + } else if channel.hasPermission(.manageTopics) { canManage = true - } else if threadData.isOwn { + } else if threadData.isOwnedByMe { canManage = true } diff --git a/submodules/TelegramUI/Sources/ComposeController.swift b/submodules/TelegramUI/Sources/ComposeController.swift index daf64b2804..5e1215ecd7 100644 --- a/submodules/TelegramUI/Sources/ComposeController.swift +++ b/submodules/TelegramUI/Sources/ComposeController.swift @@ -207,7 +207,7 @@ public class ComposeControllerImpl: ViewController, ComposeController { if let peer = peer { DispatchQueue.main.async { if let navigationController = strongSelf.navigationController as? NavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id))) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)))) } } } else { diff --git a/submodules/TelegramUI/Sources/NavigateToChatController.swift b/submodules/TelegramUI/Sources/NavigateToChatController.swift index 91c3716724..5c0dab0aa8 100644 --- a/submodules/TelegramUI/Sources/NavigateToChatController.swift +++ b/submodules/TelegramUI/Sources/NavigateToChatController.swift @@ -15,11 +15,25 @@ import AttachmentUI import ForumCreateTopicScreen public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParams) { + if case let .peer(peer) = params.chatLocation, case let .channel(channel) = peer, channel.flags.contains(.isForum) { + for controller in params.navigationController.viewControllers.reversed() { + if let controller = controller as? ChatListControllerImpl, case let .forum(peerId) = controller.location, peer.id == peerId { + let _ = params.navigationController.popToViewController(controller, animated: params.animated) + return + } + } + + let controller = ChatListControllerImpl(context: params.context, location: .forum(peerId: peer.id), controlsHistoryPreload: false, enableDebugActions: false) + params.navigationController.pushViewController(controller) + + return + } + var found = false var isFirst = true if params.useExisting { for controller in params.navigationController.viewControllers.reversed() { - if let controller = controller as? ChatControllerImpl, controller.chatLocation == params.chatLocation && (controller.subject != .scheduledMessages || controller.subject == params.subject) { + if let controller = controller as? ChatControllerImpl, controller.chatLocation == params.chatLocation.asChatLocation && (controller.subject != .scheduledMessages || controller.subject == params.subject) { if let updateTextInputState = params.updateTextInputState { controller.updateTextInputState(updateTextInputState) } @@ -46,7 +60,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam } if popAndComplete { - if let _ = params.navigationController.viewControllers.last as? AttachmentController, let controller = params.navigationController.viewControllers[params.navigationController.viewControllers.count - 2] as? ChatControllerImpl, controller.chatLocation == params.chatLocation { + if let _ = params.navigationController.viewControllers.last as? AttachmentController, let controller = params.navigationController.viewControllers[params.navigationController.viewControllers.count - 2] as? ChatControllerImpl, controller.chatLocation == params.chatLocation.asChatLocation { } else { let _ = params.navigationController.popToViewController(controller, animated: params.animated) @@ -89,7 +103,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam controller.presentAttachmentBot(botId: attachBotStart.botId, payload: attachBotStart.payload, justInstalled: attachBotStart.justInstalled) } } else { - controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, attachBotStart: params.attachBotStart, peekData: params.peekData, peerNearbyData: params.peerNearbyData, chatListFilter: params.chatListFilter, chatNavigationStack: params.chatNavigationStack) + controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation.asChatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, attachBotStart: params.attachBotStart, peekData: params.peekData, peerNearbyData: params.peerNearbyData, chatListFilter: params.chatListFilter, chatNavigationStack: params.chatNavigationStack) } controller.purposefulAction = params.purposefulAction if let search = params.activateMessageSearch { @@ -158,16 +172,14 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam if let item = item as? ChatMessageNotificationItem { for message in item.messages { switch params.chatLocation { - case let .peer(peerId): - if message.id.peerId == peerId { + case let .peer(peer): + if message.id.peerId == peer.id { return true } case let .replyThread(replyThreadMessage): if message.id.peerId == replyThreadMessage.messageId.peerId { return true } - case .feed: - break } } } @@ -244,7 +256,7 @@ public func navigateToForumThreadImpl(context: AccountContext, peerId: EnginePee NavigateToChatControllerParams( navigationController: navigationController, context: context, - chatLocation: .replyThread(message: result.message), + chatLocation: .replyThread(result.message), chatLocationContextHolder: result.contextHolder, subject: messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) }, activateInput: actualActivateInput, diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 520f3623d1..e20fc4de48 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -114,16 +114,22 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur } else { let _ = (context.engine.messages.requestStartBotInGroup(botPeerId: botPeerId, groupPeerId: peerId, payload: payload) |> deliverOnMainQueue).start(next: { result in - if let navigationController = navigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) - } - switch result { + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + if let navigationController = navigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) + } + switch result { case let .channelParticipant(participant): context.peerChannelMemberCategoriesContextsManager.externallyAdded(peerId: peerId, participant: participant) case .none: break - } - controller?.dismiss() + } + controller?.dismiss() + }) }, error: { _ in }) @@ -508,17 +514,23 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur } }) case let .joinVoiceChat(peerId, invite): - dismissInput() - if let navigationController = navigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId), completion: { chatController in - guard let chatController = chatController as? ChatControllerImpl else { - return - } - navigationController.currentWindow?.present(VoiceChatJoinScreen(context: context, peerId: peerId, invite: invite, join: { [weak chatController] call in - chatController?.joinGroupCall(peerId: peerId, invite: invite, activeCall: EngineGroupCallDescription(call)) - }), on: .root, blockInteraction: false, completion: {}) - })) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + dismissInput() + if let navigationController = navigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), completion: { chatController in + guard let chatController = chatController as? ChatControllerImpl else { + return + } + navigationController.currentWindow?.present(VoiceChatJoinScreen(context: context, peerId: peerId, invite: invite, join: { [weak chatController] call in + chatController?.joinGroupCall(peerId: peerId, invite: invite, activeCall: EngineGroupCallDescription(call)) + }), on: .root, blockInteraction: false, completion: {}) + })) + } + }) case .importStickers: dismissInput() if let navigationController = navigationController, let data = UIPasteboard.general.data(forPasteboardType: "org.telegram.third-party.stickerset"), let stickerPack = ImportStickerPack(data: data), !stickerPack.stickers.isEmpty { @@ -582,14 +594,23 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur if let navigationController = navigationController { let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, updatedPresentationData: updatedPresentationData, filter: filters, hasChatListSelector: true, hasContactSelector: false, title: presentationData.strings.WebApp_SelectChat)) - controller.peerSelected = { peer, _ in - let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), attachBotStart: ChatControllerInitialAttachBotStart(botId: bot.peer.id, payload: payload, justInstalled: false), keepStack: .never, useExisting: true)) + controller.peerSelected = { [weak navigationController] peer, _ in + guard let navigationController else { + return + } + let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(EnginePeer(peer)), attachBotStart: ChatControllerInitialAttachBotStart(botId: bot.peer.id, payload: payload, justInstalled: false), keepStack: .never, useExisting: true)) } navigationController.pushViewController(controller) } } else { - if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext { - let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: peerId, payload: payload, justInstalled: false), keepStack: .never, useExisting: true)) + if case let .chat(chatPeerId, _) = urlContext { + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: chatPeerId)) + |> deliverOnMainQueue).start(next: { chatPeer in + guard let navigationController = navigationController, let chatPeer else { + return + } + let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(chatPeer), attachBotStart: ChatControllerInitialAttachBotStart(botId: peerId, payload: payload, justInstalled: false), keepStack: .never, useExisting: true)) + }) } else { presentError(presentationData.strings.WebApp_AddToAttachmentAlreadyAddedError) } @@ -625,14 +646,24 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur if let navigationController = navigationController { let controller = context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: context, updatedPresentationData: updatedPresentationData, filter: filters, hasChatListSelector: true, hasContactSelector: false, title: presentationData.strings.WebApp_SelectChat)) - controller.peerSelected = { peer, _ in - let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), attachBotStart: ChatControllerInitialAttachBotStart(botId: botPeer.id, payload: payload, justInstalled: true), useExisting: true)) + controller.peerSelected = { [weak navigationController] peer, _ in + guard let navigationController else { + return + } + let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(EnginePeer(peer)), attachBotStart: ChatControllerInitialAttachBotStart(botId: botPeer.id, payload: payload, justInstalled: true), useExisting: true)) } navigationController.pushViewController(controller) } } else { - if let navigationController = navigationController, case let .chat(chatPeerId, _) = urlContext { - let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: chatPeerId), attachBotStart: ChatControllerInitialAttachBotStart(botId: botPeer.id, payload: payload, justInstalled: true), useExisting: true)) + if case let .chat(chatPeerId, _) = urlContext { + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: chatPeerId)) + |> deliverOnMainQueue).start(next: { chatPeer in + guard let navigationController = navigationController, let chatPeer else { + return + } + + let _ = context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(chatPeer), attachBotStart: ChatControllerInitialAttachBotStart(botId: botPeer.id, payload: payload, justInstalled: true), useExisting: true)) + }) } } }) diff --git a/submodules/TelegramUI/Sources/OpenUrl.swift b/submodules/TelegramUI/Sources/OpenUrl.swift index 6daefd7dc3..4092b160f3 100644 --- a/submodules/TelegramUI/Sources/OpenUrl.swift +++ b/submodules/TelegramUI/Sources/OpenUrl.swift @@ -200,17 +200,17 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur case let .chat(_, subject, peekData): context.sharedContext.applicationBindings.dismissNativeController() if let navigationController = navigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), subject: subject, peekData: peekData)) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: subject, peekData: peekData)) } case let .withBotStartPayload(payload): context.sharedContext.applicationBindings.dismissNativeController() if let navigationController = navigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), botStart: payload)) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), botStart: payload)) } case let .withAttachBot(attachBotStart): context.sharedContext.applicationBindings.dismissNativeController() if let navigationController = navigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), attachBotStart: attachBotStart)) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), attachBotStart: attachBotStart)) } default: break diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift index 7db45f607f..08f846138d 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift @@ -1216,7 +1216,7 @@ func peerInfoCanEdit(peer: Peer?, threadData: MessageHistoryThreadData?, cachedD return true } else if let threadData = threadData, threadData.isOwnedByMe { return true - } else if let _ = peer.adminRights { + } else if peer.hasPermission(.manageTopics) { return true } else { return false diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 421f849dae..194285acce 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -2141,9 +2141,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.SharedMedia_ViewInChat, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor) }, action: { c, _ in c.dismiss(completion: { - if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { + if let strongSelf = self, let currentPeer = strongSelf.data?.peer, let navigationController = strongSelf.controller?.navigationController as? NavigationController { let currentPeerId = strongSelf.peerId - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: currentPeerId), subject: .message(id: .id(message.id), highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(currentPeer)), subject: .message(id: .id(message.id), highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: { var viewControllers = navigationController.viewControllers var indexesToRemove = Set() var keptCurrentChatController = false @@ -2292,9 +2292,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate items.append(.action(ContextMenuActionItem(text: strings.SharedMedia_ViewInChat, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor) }, action: { c, f in c.dismiss(completion: { - if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { + if let strongSelf = self, let currentPeer = strongSelf.data?.peer, let navigationController = strongSelf.controller?.navigationController as? NavigationController { let currentPeerId = strongSelf.peerId - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: currentPeerId), subject: .message(id: .id(message.id), highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(currentPeer)), subject: .message(id: .id(message.id), highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: { var viewControllers = navigationController.viewControllers var indexesToRemove = Set() var keptCurrentChatController = false @@ -3758,7 +3758,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } switch navigation { case let .chat(_, subject, peekData): - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), subject: subject, keepStack: .always, peekData: peekData)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), subject: subject, keepStack: .always, peekData: peekData)) case .info: if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil { if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer._asPeer(), mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) { @@ -3766,9 +3766,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } } case let .withBotStartPayload(startPayload): - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), botStart: startPayload)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), botStart: startPayload)) case let .withAttachBot(attachBotStart): - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), attachBotStart: attachBotStart)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), attachBotStart: attachBotStart)) default: break } @@ -3822,34 +3822,37 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } private func openPeer(peerId: PeerId, navigation: ChatControllerInteractionNavigateToPeer) { - switch navigation { - case .default: - if let navigationController = self.controller?.navigationController as? NavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: peerId), keepStack: .always)) + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let self, let peer = peer else { + return } - case let .chat(_, subject, peekData): - if let navigationController = self.controller?.navigationController as? NavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: peerId), subject: subject, keepStack: .always, peekData: peekData)) - } - case .info: - self.resolveUrlDisposable.set((self.context.account.postbox.loadedPeerWithId(peerId) - |> take(1) - |> deliverOnMainQueue).start(next: { [weak self] peer in - if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil { - if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) { - (strongSelf.controller?.navigationController as? NavigationController)?.pushViewController(infoController) - } + + switch navigation { + case .default: + if let navigationController = self.controller?.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), keepStack: .always)) + } + case let .chat(_, subject, peekData): + if let navigationController = self.controller?.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), subject: subject, keepStack: .always, peekData: peekData)) + } + case .info: + if peer.restrictionText(platform: "ios", contentSettings: self.context.currentContentSettings.with { $0 }) == nil { + if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: nil, peer: peer._asPeer(), mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) { + (self.controller?.navigationController as? NavigationController)?.pushViewController(infoController) } - })) - case let .withBotStartPayload(startPayload): - if let navigationController = self.controller?.navigationController as? NavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: peerId), botStart: startPayload)) + } + case let .withBotStartPayload(startPayload): + if let navigationController = self.controller?.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), botStart: startPayload)) + } + case let .withAttachBot(attachBotStart): + if let navigationController = self.controller?.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), attachBotStart: attachBotStart)) + } } - case let .withAttachBot(attachBotStart): - if let navigationController = self.controller?.navigationController as? NavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: peerId), attachBotStart: attachBotStart)) - } - } + }) } private func openPeerMention(_ name: String, navigation: ChatControllerInteractionNavigateToPeer = .default) { @@ -3965,8 +3968,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } switch key { case .message: - if let navigationController = controller.navigationController as? NavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: self.peerId), keepStack: self.nearbyPeerDistance != nil ? .always : .default, peerNearbyData: self.nearbyPeerDistance.flatMap({ ChatPeerNearbyData(distance: $0) }), completion: { [weak self] _ in + if let navigationController = controller.navigationController as? NavigationController, let peer = self.data?.peer { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(EnginePeer(peer)), keepStack: self.nearbyPeerDistance != nil ? .always : .default, peerNearbyData: self.nearbyPeerDistance.flatMap({ ChatPeerNearbyData(distance: $0) }), completion: { [weak self] _ in if let strongSelf = self, strongSelf.nearbyPeerDistance != nil { var viewControllers = navigationController.viewControllers viewControllers = viewControllers.filter { controller in @@ -3981,9 +3984,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } case .discussion: if let cachedData = self.data?.cachedData as? CachedChannelData, case let .known(maybeLinkedDiscussionPeerId) = cachedData.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId { - if let navigationController = controller.navigationController as? NavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: linkedDiscussionPeerId))) - } + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: linkedDiscussionPeerId)) + |> deliverOnMainQueue).start(next: { [weak self] linkedDiscussionPeer in + guard let self, let linkedDiscussionPeer else { + return + } + if let navigationController = controller.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(linkedDiscussionPeer))) + } + }) } case .call: self.requestCall(isVideo: false) @@ -4909,8 +4918,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } navigationController.setViewControllers(viewControllers, animated: true) current.activateSearch() - } else { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: self.peerId), keepStack: self.nearbyPeerDistance != nil ? .always : .default, activateMessageSearch: (.everything, ""), peerNearbyData: self.nearbyPeerDistance.flatMap({ ChatPeerNearbyData(distance: $0) }), completion: { [weak self] _ in + } else if let peer = self.data?.peer { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(EnginePeer(peer)), keepStack: self.nearbyPeerDistance != nil ? .always : .default, activateMessageSearch: (.everything, ""), peerNearbyData: self.nearbyPeerDistance.flatMap({ ChatPeerNearbyData(distance: $0) }), completion: { [weak self] _ in if let strongSelf = self, strongSelf.nearbyPeerDistance != nil { var viewControllers = navigationController.viewControllers viewControllers = viewControllers.filter { controller in @@ -4927,15 +4936,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } private func openChatForReporting(_ reason: ReportReason) { - if let navigationController = (self.controller?.navigationController as? NavigationController) { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: self.peerId), keepStack: .default, reportReason: reason, completion: { _ in + if let peer = self.data?.peer, let navigationController = (self.controller?.navigationController as? NavigationController) { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(EnginePeer(peer)), keepStack: .default, reportReason: reason, completion: { _ in })) } } private func openChatForThemeChange() { - if let navigationController = (self.controller?.navigationController as? NavigationController) { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: self.peerId), keepStack: .default, changeColors: true, completion: { _ in + if let peer = self.data?.peer, let navigationController = (self.controller?.navigationController as? NavigationController) { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(EnginePeer(peer)), keepStack: .default, changeColors: true, completion: { _ in })) } } @@ -5064,9 +5073,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate guard let strongSelf = self else { return } - if let navigationController = (strongSelf.controller?.navigationController as? NavigationController) { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peerId))) - } + let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> deliverOnMainQueue).start(next: { peer in + guard let strongSelf = self, let peer = peer else { + return + } + if let navigationController = (strongSelf.controller?.navigationController as? NavigationController) { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer))) + } + }) }, error: { error in guard let strongSelf = self else { return @@ -5543,8 +5558,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } private func openChat() { - if let navigationController = self.controller?.navigationController as? NavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: self.peerId), keepStack: self.nearbyPeerDistance != nil ? .always : .default, peerNearbyData: self.nearbyPeerDistance.flatMap({ ChatPeerNearbyData(distance: $0) }), completion: { [weak self] _ in + if let peer = self.data?.peer, let navigationController = self.controller?.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(EnginePeer(peer)), keepStack: self.nearbyPeerDistance != nil ? .always : .default, peerNearbyData: self.nearbyPeerDistance.flatMap({ ChatPeerNearbyData(distance: $0) }), completion: { [weak self] _ in if let strongSelf = self, strongSelf.nearbyPeerDistance != nil { var viewControllers = navigationController.viewControllers viewControllers = viewControllers.filter { controller in @@ -5560,11 +5575,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } private func openChatWithClearedHistory(type: InteractiveHistoryClearingType) { - guard let navigationController = self.controller?.navigationController as? NavigationController else { + guard let peer = self.data?.peer, let navigationController = self.controller?.navigationController as? NavigationController else { return } - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: self.peerId), keepStack: self.nearbyPeerDistance != nil ? .always : .default, peerNearbyData: self.nearbyPeerDistance.flatMap({ ChatPeerNearbyData(distance: $0) }), setupController: { controller in + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(EnginePeer(peer)), keepStack: self.nearbyPeerDistance != nil ? .always : .default, peerNearbyData: self.nearbyPeerDistance.flatMap({ ChatPeerNearbyData(distance: $0) }), setupController: { controller in (controller as? ChatControllerImpl)?.beginClearHistory(type: type) }, completion: { [weak self] _ in if let strongSelf = self, strongSelf.nearbyPeerDistance != nil { @@ -5609,7 +5624,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate if !block { let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start() if let navigationController = strongSelf.controller?.navigationController as? NavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id))) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)))) } } } else { @@ -6034,8 +6049,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start() - if let navigationController = strongSelf.controller?.navigationController as? NavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: strongSelf.peerId))) + if let peer = strongSelf.data?.peer, let navigationController = strongSelf.controller?.navigationController as? NavigationController { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer)))) } }) } @@ -6896,9 +6911,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate case .proxy: self.controller?.push(proxySettingsController(context: self.context)) case .savedMessages: - if let controller = self.controller, let navigationController = controller.navigationController as? NavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(id: self.context.account.peerId))) - } + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId)) + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let self, let peer = peer else { + return + } + if let controller = self.controller, let navigationController = controller.navigationController as? NavigationController { + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer))) + } + }) case .recentCalls: push(CallListController(context: context, mode: .navigation)) case .devices: @@ -7108,7 +7129,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate self.tipsPeerDisposable.set((self.context.engine.peers.resolvePeerByName(name: self.presentationData.strings.Settings_TipsUsername) |> deliverOnMainQueue).start(next: { [weak controller] peer in controller?.dismiss() if let peer = peer, let navigationController = navigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id))) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer))) } })) } @@ -7761,7 +7782,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate f(.dismissWithoutContent) dismissCalendarScreen?() - guard let strongSelf = self, let controller = strongSelf.controller, let navigationController = controller.navigationController as? NavigationController else { + guard let strongSelf = self, let peer = strongSelf.data?.peer, let controller = strongSelf.controller, let navigationController = controller.navigationController as? NavigationController else { return } @@ -7769,7 +7790,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate navigationController: navigationController, chatController: nil, context: strongSelf.context, - chatLocation: .peer(id: strongSelf.peerId), + chatLocation: .peer(EnginePeer(peer)), subject: .message(id: .id(index.id), highlight: false, timecode: nil), botStart: nil, updateTextInputState: nil, @@ -8927,7 +8948,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc return } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), animated: true, completion: { _ in + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), animated: true, completion: { _ in })) }))) } diff --git a/submodules/TelegramUI/Sources/TextLinkHandling.swift b/submodules/TelegramUI/Sources/TextLinkHandling.swift index 1c2293c8b0..4b6ffa4edd 100644 --- a/submodules/TelegramUI/Sources/TextLinkHandling.swift +++ b/submodules/TelegramUI/Sources/TextLinkHandling.swift @@ -30,7 +30,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate switch navigation { case let .chat(_, subject, peekData): if let navigationController = controller?.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), subject: subject, keepStack: .always, peekData: peekData)) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer), subject: subject, keepStack: .always, peekData: peekData)) } case .info: let peerSignal: Signal @@ -62,7 +62,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate openResolvedPeerImpl(peer.flatMap(EnginePeer.init), navigation) case let .channelMessage(peer, messageId, timecode): if let navigationController = controller.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peer.id), subject: .message(id: .id(messageId), highlight: true, timecode: timecode))) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(EnginePeer(peer)), subject: .message(id: .id(messageId), highlight: true, timecode: timecode))) } case let .replyThreadMessage(replyThreadMessage, messageId): if let navigationController = controller.navigationController as? NavigationController { diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 7777379190..94dc29f0a4 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -1116,10 +1116,22 @@ public final class WebAppController: ViewController, AttachmentContainable { }, action: { [weak self] c, _ in c.dismiss(completion: nil) - if let strongSelf = self, let navigationController = strongSelf.getNavigationController() { - strongSelf.dismiss() - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: strongSelf.botId))) + guard let strongSelf = self else { + return } + + let _ = (context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: strongSelf.botId) + ) + |> deliverOnMainQueue).start(next: { botPeer in + guard let botPeer = botPeer else { + return + } + if let strongSelf = self, let navigationController = strongSelf.getNavigationController() { + strongSelf.dismiss() + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(botPeer))) + } + }) }))) }