| index 16f27a5..4a6d1e0 100644 |
| --- a/web/static/shell.js |
| +++ b/web/static/shell.js |
| @@ -2855,11 +2855,30 @@ async function openThread(id) { |
| // A personal app-thread (chat or interface view) or a chat-app thread renders |
| // full-pane (no original feed / composer). An app-thread defaults to its chat |
| // view — a DM with its bot — with the header toggle switching to the interface view. |
| - const renderApp = renderAppFor(id); |
| + // Mount the thread's surface. renderAppFor → chatAppFor looks the thread up |
| + // in `threads`, so a thread that isn't loaded yet (opened programmatically |
| + // during onboarding, or right after a Discover/auto join) resolves to |
| + // "no feed". Fetch once and retry rather than falling through — otherwise |
| + // the block below would leave the PREVIOUS thread's pane showing. |
| + let renderApp = renderAppFor(id); |
| + if (!renderApp && !threads.some((t) => t.id === id)) { |
| + await loadThreads(); |
| + if (myOpen !== openSeq) return; // a newer open superseded us |
| + renderThreadList(); |
| + renderApp = renderAppFor(id); |
| + } |
| if (renderApp) { |
| await openAppThreadView(id, myOpen, renderApp, threadApp[id] || null); |
| return; |
| } |
| + // No feed to mount for this thread. Never leave the outgoing thread's feed |
| + // sitting under the new header (the onboarding-then-join bug: Eleven's |
| + // messages showing "in" the just-opened group) — clear the pane. stashAppPane |
| + // above only detaches the old root when it was cached, so an uncached pane |
| + // (e.g. the onboarding conversation) would otherwise linger here. |
| + const pane = document.getElementById("app-pane"); |
| + if (pane) pane.textContent = ""; |
| + setAppThreadMode(false); |
| } |
| |
| // Pin the feed to the bottom, and keep it pinned for a short settle window as |