From 8dd6ff2f0cdd6340325bfb0dcc5f670e9f077ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bojan=20Stefanovi=C4=87?= <5675392+bojanstef@users.noreply.github.com> Date: Sun, 14 Jun 2026 19:51:23 -0400 Subject: [PATCH] Prevent duplicate Peer Info screens on rapid chat-title taps The chat title bar opens the peer's Info screen via the openChatInfo navigation action, which had no re-entrancy guard. Tapping the title in quick succession ran the full path on every tap and pushed a separate PeerInfoScreen each time, so several identical Info screens ended up stacked on top of each other and the user had to press Back once per tap to return to the chat. Route every Info push in openChatInfo through a helper that skips the push when this peer's Info screen is already on top of the navigation stack. The first tap opens Info as before; the remaining taps in a burst become no-ops. All five Info-push sites in the action go through the guard. Fix #2185 Co-Authored-By: Claude Opus 4.8 (1M context) --- ...ChatControllerNavigationButtonAction.swift | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerNavigationButtonAction.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerNavigationButtonAction.swift index 90e5a23d7e..81eaa89678 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerNavigationButtonAction.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerNavigationButtonAction.swift @@ -437,7 +437,7 @@ extension ChatControllerImpl { if peer.restrictionText(platform: "ios", contentSettings: self.context.currentContentSettings.with { $0 }) == nil && !self.presentationInterfaceState.isNotAccessible { if peer.id == self.context.account.peerId { if let peer = self.presentationInterfaceState.renderedPeer?.chatMainPeer, let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: EnginePeer(peer), mode: .generic, avatarInitiallyExpanded: false, fromChat: true, requestsContext: nil) { - self.effectiveNavigationController?.pushViewController(infoController) + self.pushPeerInfoControllerAvoidingDuplicate(infoController) } } else { var expandAvatar = expandAvatar @@ -457,7 +457,7 @@ extension ChatControllerImpl { mode = .generic } if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: EnginePeer(peer), mode: mode, avatarInitiallyExpanded: expandAvatar, fromChat: true, requestsContext: self.contentData?.inviteRequestsContext) { - self.effectiveNavigationController?.pushViewController(infoController) + self.pushPeerInfoControllerAvoidingDuplicate(infoController) } } @@ -467,7 +467,7 @@ extension ChatControllerImpl { case .replyThread: if let peer = self.presentationInterfaceState.renderedPeer?.peer, case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.peerId == self.context.account.peerId { if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: EnginePeer(peer), mode: .forumTopic(thread: replyThreadMessage), avatarInitiallyExpanded: false, fromChat: true, requestsContext: nil) { - self.effectiveNavigationController?.pushViewController(infoController) + self.pushPeerInfoControllerAvoidingDuplicate(infoController) } } else if let monoforumPeer = self.presentationInterfaceState.renderedPeer?.peer, case let .replyThread(replyThreadMessage) = self.chatLocation, monoforumPeer.isMonoForum { let context = self.context @@ -482,13 +482,13 @@ extension ChatControllerImpl { return } if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: peer, mode: .monoforum(monoforumPeer.id), avatarInitiallyExpanded: false, fromChat: true, requestsContext: nil) { - self.effectiveNavigationController?.pushViewController(infoController) + self.pushPeerInfoControllerAvoidingDuplicate(infoController) } } } } else if let channel = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isForumOrMonoForum, case let .replyThread(message) = self.chatLocation { if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: EnginePeer(channel), mode: .forumTopic(thread: message), avatarInitiallyExpanded: false, fromChat: true, requestsContext: self.contentData?.inviteRequestsContext) { - self.effectiveNavigationController?.pushViewController(infoController) + self.pushPeerInfoControllerAvoidingDuplicate(infoController) } } case .customChatContents: @@ -716,4 +716,20 @@ extension ChatControllerImpl { self.editChat() } } + + // #2185: rapid title-bar taps each pushed a new PeerInfoScreen, so a fast burst + // opened several stacked Info screens. Route every Info push through this guard: + // if this peer's Info is already on top of the navigation stack, treat the extra + // tap as a no-op instead of pushing a duplicate. + private func pushPeerInfoControllerAvoidingDuplicate(_ infoController: ViewController) { + guard let navigationController = self.effectiveNavigationController else { + return + } + if let topController = navigationController.viewControllers.last as? PeerInfoScreenImpl, + let newController = infoController as? PeerInfoScreenImpl, + topController.peerId == newController.peerId { + return + } + navigationController.pushViewController(infoController) + } }