1 Commits
Author SHA1 Message Date
sneak 97e71742ac Show a joined channel's web tab whichever reply comes first (closes #193)
check / check (push) Waiting to run
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 records the joined channel's name. An effect makes that
channel's tab active once the tab list holds it, finding the tab by
name.

Model: opus-5-5
2026-10-27 02:18:52 +00:00
+15 -2
View File
@@ -280,6 +280,8 @@ function App() {
const [connected, setConnected] = useState(true);
const [inputHistory, setInputHistory] = useState([]);
const [historyIndex, setHistoryIndex] = useState(-1);
// A channel this client has just joined, whose tab is to be shown.
const [joinedChannel, setJoinedChannel] = useState(null);
const lastIdRef = useRef(0);
const seenIdsRef = useRef(new Set());
@@ -315,6 +317,18 @@ function App() {
if (tab) setUnread((prev) => ({ ...prev, [tab.name]: 0 }));
}, [activeTab, tabs]);
// Show the tab of a channel this client has just joined. The tab is
// found by name in the updated tab list, because the user's own JOIN
// event may have added it before the join request returned.
useEffect(() => {
if (!joinedChannel) return;
const idx = tabs.findIndex(
(t) => t.type === "channel" && t.name === joinedChannel,
);
if (idx >= 0) setActiveTab(idx);
setJoinedChannel(null);
}, [tabs, joinedChannel]);
const addMessage = useCallback((tabName, msg) => {
if (msg.id && seenIdsRef.current.has(msg.id)) return;
if (msg.id) seenIdsRef.current.add(msg.id);
@@ -864,8 +878,7 @@ function App() {
return [...prev, { type: "channel", name }];
});
const newIdx = tabsRef.current.length;
setActiveTab(newIdx);
setJoinedChannel(name);
try {
const hist = await api(
`/history?target=${encodeURIComponent(name)}&limit=50`,