From c223c274f960a6bc9b61d5d466e9528bdacbee88 Mon Sep 17 00:00:00 2001 From: sneak Date: Tue, 27 Oct 2026 02:18:52 +0000 Subject: [PATCH] Show a joined channel's web tab whichever reply comes first (closes #193) After a join request returned, joinChannel made tab number tabsRef.current.length active. When the user's own JOIN event had already added the tab, or the tab was already open, that index was one past the last tab. The view then fell back to the Server tab and typed lines were dropped. joinChannel now finds the channel's tab by name inside its own tab-list update and makes that tab active there. Preact runs that update at once on the newest tab list, so the position is right even when the JOIN event, or the close of another tab, landed first. Model: opus-5-5 --- web/src/app.jsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/web/src/app.jsx b/web/src/app.jsx index 11607d8..c707e1b 100644 --- a/web/src/app.jsx +++ b/web/src/app.jsx @@ -858,14 +858,23 @@ function App() { method: "POST", body: JSON.stringify({ command: "JOIN", to: name }), }); + // Show the channel's tab. Preact runs this update at once on the + // newest tab list, so the tab is found there by name: the user's + // own JOIN event may already have added it, and other tabs may + // have closed. setTabs((prev) => { - if (prev.find((t) => t.type === "channel" && t.name === name)) + const idx = prev.findIndex( + (t) => t.type === "channel" && t.name === name, + ); + if (idx >= 0) { + setActiveTab(idx); + return prev; + } + setActiveTab(prev.length); return [...prev, { type: "channel", name }]; }); - const newIdx = tabsRef.current.length; - setActiveTab(newIdx); try { const hist = await api( `/history?target=${encodeURIComponent(name)}&limit=50`,