From 1fdfc248937e5e5ee8a010e2e84ec4cb322fecdb Mon Sep 17 00:00:00 2001 From: sword Date: Sat, 18 Jul 2026 09:02:00 +0700 Subject: [PATCH] fix(web): new session button fails on fresh start with no opened projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On a fresh `opencode web` start, the "New Session" button in the titlebar silently does nothing and the home page hides its "New Session" buttons. This happens because: 1. `newSessionProject()` in home.tsx relies solely on `projects()` (persisted opened projects), which is empty. 2. `openNewTab()` in titlebar.tsx has a 5-case fallback chain that all fail when no projects are persisted: home selection is empty, layout.projects.list() is empty, and global.ensureServerCtx(conn).projects.list() returns only persisted projects — never server-registered ones. Fix: - home.tsx: add sync data fallback to `newSessionProject` (registered projects from the server API) - titlebar.tsx: add a final fallback that reads server-registered projects from sync.data.project when all other cases fail --- packages/app/src/components/titlebar.tsx | 16 ++++++++++++++-- packages/app/src/pages/home.tsx | 3 ++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/app/src/components/titlebar.tsx b/packages/app/src/components/titlebar.tsx index 1a2a8a81b6d4..92e82ccd6e1e 100644 --- a/packages/app/src/components/titlebar.tsx +++ b/packages/app/src/components/titlebar.tsx @@ -367,9 +367,21 @@ export function Titlebar(props: { update?: TitlebarUpdate }) { const project = global.ensureServerCtx(conn).projects.list()[0] return project ? [{ server: ServerConnection.key(conn), project }] : [] })[0] - if (!fallback) return + if (fallback) { + tabs.newDraft({ server: fallback.server, directory: fallback.project.worktree }, "") + return + } - tabs.newDraft({ server: fallback.server, directory: fallback.project.worktree }, "") + // Last resort: use server-registered projects from sync data when + // no projects have been opened yet (fresh web start) + const conn = global.servers.list()[0] ?? server.current + if (conn) { + const ctx = global.ensureServerCtx(conn) + const registered = ctx.sync.data.project[0] + if (registered) { + tabs.newDraft({ server: ServerConnection.key(conn), directory: registered.worktree }, "") + } + } } const toggleHome = () => tabs.toggleHome({ home: layout.route().type === "home", current: currentTab() }) diff --git a/packages/app/src/pages/home.tsx b/packages/app/src/pages/home.tsx index 215696d7de62..d596ab1f9b98 100644 --- a/packages/app/src/pages/home.tsx +++ b/packages/app/src/pages/home.tsx @@ -332,7 +332,8 @@ export function NewHome() { () => selectedProject() ?? projects().find((project) => project.worktree === focusedServerCtx()?.projects.last()) ?? - projects()[0], + projects()[0] ?? + focusedSync().data.project[0] as LocalProject | undefined, ) const directories = (project: LocalProject) => [project.worktree, ...(project.sandboxes ?? [])] const projectDirectories = createMemo(() => {