From df46097605b324f8d880230d960aa5604f916e93 Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Tue, 3 Nov 2026 22:02:25 +0530 Subject: [PATCH 01/12] feat(local): draw the dashboard's frame while startup loads Replaces the logo loader. Once onboarding has been seen done on this database, startup draws the dashboard's columns, headings and composer box with the dashboard's own components, then fades the contents in. First launches, onboarding and Docker keep the plain background. --- docs/architecture/chat.md | 2 +- docs/architecture/overview.md | 1 + surfsense_local/electron/src/main/index.ts | 6 + .../startup-frame/database-identity.test.ts | 42 ++++ .../main/startup-frame/database-identity.ts | 20 ++ .../main/startup-frame/startup-frame-ipc.ts | 16 ++ surfsense_local/electron/src/preload/index.ts | 3 + .../src/app/app-bootstrap-startup.test.tsx | 222 ++++++++++++++++++ .../frontend/src/app/app-bootstrap.test.tsx | 18 -- .../frontend/src/app/app-bootstrap.tsx | 126 ++++++---- .../frontend/src/app/logo-fill-loader.tsx | 55 ----- .../src/features/chat/chat-composer.tsx | 32 +-- .../src/features/chat/chat-viewport-layout.ts | 19 ++ .../src/features/chat/chat-viewport.tsx | 19 +- .../src/features/chat/composer-layout.ts | 33 +++ .../src/features/chat/composer-outline.tsx | 36 +++ .../src/features/chat/conversation-column.tsx | 39 +++ .../frontend/src/features/chat/last-thread.ts | 27 +++ .../src/features/chat/messages-skeleton.tsx | 17 ++ .../src/features/chat/thread-panel.tsx | 73 ++---- .../src/features/chat/thread-welcome.tsx | 13 + .../src/features/chat/use-chat-runtime.ts | 31 +-- .../features/dashboard/dashboard-columns.tsx | 9 +- .../src/features/dashboard/dashboard-page.tsx | 15 +- .../features/dashboard/dashboard-shell.tsx | 22 ++ .../src/features/dashboard/left-sidebar.tsx | 31 ++- .../src/features/dashboard/right-panel.tsx | 12 +- .../src/features/dashboard/sidebar-frame.tsx | 29 +++ .../features/startup/dashboard-hint.test.ts | 56 +++++ .../src/features/startup/dashboard-hint.ts | 45 ++++ .../src/features/startup/startup-frame.tsx | 77 ++++++ .../features/startup/startup-layout.test.ts | 32 +++ .../src/features/startup/startup-layout.ts | 24 ++ .../startup/startup-reveal-context.ts | 4 + .../startup/startup-reveal-provider.tsx | 28 +++ .../features/startup/startup-reveal.test.tsx | 73 ++++++ .../startup/startup-screen-imports.test.ts | 77 ++++++ .../src/features/startup/startup-screen.tsx | 25 ++ .../features/startup/use-startup-reveal.ts | 21 ++ .../src/features/updates/stub-bridge.ts | 1 + .../src/features/workspaces/last-workspace.ts | 19 ++ .../src/features/workspaces/use-workspaces.ts | 21 +- .../features/workspaces/workspace-rail.tsx | 7 +- surfsense_local/frontend/src/index.css | 49 +--- surfsense_local/frontend/src/lib/api.ts | 2 + 45 files changed, 1232 insertions(+), 297 deletions(-) create mode 100644 surfsense_local/electron/src/main/startup-frame/database-identity.test.ts create mode 100644 surfsense_local/electron/src/main/startup-frame/database-identity.ts create mode 100644 surfsense_local/electron/src/main/startup-frame/startup-frame-ipc.ts create mode 100644 surfsense_local/frontend/src/app/app-bootstrap-startup.test.tsx delete mode 100644 surfsense_local/frontend/src/app/logo-fill-loader.tsx create mode 100644 surfsense_local/frontend/src/features/chat/chat-viewport-layout.ts create mode 100644 surfsense_local/frontend/src/features/chat/composer-layout.ts create mode 100644 surfsense_local/frontend/src/features/chat/composer-outline.tsx create mode 100644 surfsense_local/frontend/src/features/chat/conversation-column.tsx create mode 100644 surfsense_local/frontend/src/features/chat/last-thread.ts create mode 100644 surfsense_local/frontend/src/features/chat/messages-skeleton.tsx create mode 100644 surfsense_local/frontend/src/features/chat/thread-welcome.tsx create mode 100644 surfsense_local/frontend/src/features/dashboard/dashboard-shell.tsx create mode 100644 surfsense_local/frontend/src/features/dashboard/sidebar-frame.tsx create mode 100644 surfsense_local/frontend/src/features/startup/dashboard-hint.test.ts create mode 100644 surfsense_local/frontend/src/features/startup/dashboard-hint.ts create mode 100644 surfsense_local/frontend/src/features/startup/startup-frame.tsx create mode 100644 surfsense_local/frontend/src/features/startup/startup-layout.test.ts create mode 100644 surfsense_local/frontend/src/features/startup/startup-layout.ts create mode 100644 surfsense_local/frontend/src/features/startup/startup-reveal-context.ts create mode 100644 surfsense_local/frontend/src/features/startup/startup-reveal-provider.tsx create mode 100644 surfsense_local/frontend/src/features/startup/startup-reveal.test.tsx create mode 100644 surfsense_local/frontend/src/features/startup/startup-screen-imports.test.ts create mode 100644 surfsense_local/frontend/src/features/startup/startup-screen.tsx create mode 100644 surfsense_local/frontend/src/features/startup/use-startup-reveal.ts create mode 100644 surfsense_local/frontend/src/features/workspaces/last-workspace.ts diff --git a/docs/architecture/chat.md b/docs/architecture/chat.md index b55f54ca1e..4a22bdc0f4 100644 --- a/docs/architecture/chat.md +++ b/docs/architecture/chat.md @@ -262,7 +262,7 @@ Interface strings are `dictation__`, and a server code is `dic - The composer follows assistant-ui's keyboard behaviour. - While the turn waits, the thinking header's `role="status"` region says "Thinking" or the reading quarter. A second region (`reply-announcer.tsx`) stays silent until it says "Reply finished" once, for a reply it watched run to completion. It is keyed by message, because messages render by index and an instance would otherwise watch one thread's reply and announce another's. Tokens are never fed to it, since a polite region read on every delta would interrupt without pause; a reply loaded from history, a turn that ended with no answer, and one that failed or was stopped after text arrived say nothing; its alert, or the stop, already does. A stopped reply is marked `incomplete` with reason `cancelled` by the runtime ([`use-chat-runtime.ts`](../../surfsense_local/frontend/src/features/chat/use-chat-runtime.ts)), since assistant-ui would otherwise call it complete once the run ends. A queued reply's header region says "Waiting for another reply" with its place. The Chats button's count is in its accessible name ("Chats, 2 replies being written"), and an unread row carries "New reply" as screen-reader text. - The conversation has a heading, the thread's title, hidden visually because the visible title is the rename button. Focus does not move to it: on every thread switch the composer keeps the focus assistant-ui gives it, so someone can switch and type, and the composer is described by the heading (`aria-describedby`), so a screen reader names the conversation it writes into. A new chat has no heading until it is a thread. -- The startup loader and the typed-in thread title respect `prefers-reduced-motion`. +- The startup fade and the typed-in thread title respect `prefers-reduced-motion`. - The mic carries `aria-pressed` and a name that follows its state: "Start voice input", "Stop voice input", or "Set up voice input"; its tooltip is visual only. While voice input runs, a `role="status"` line in the strip says "Starting the microphone…", "Listening", "Loading the speech recognition model…", "Transcribing…" or the 30-second warning; a problem is a `role="alert"`, the two limits a `role="status"`. Under `prefers-reduced-motion` the level bars give way to the still dot beside them. ## Agent threads diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index 14ae231806..dd984af390 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -110,6 +110,7 @@ The rules that keep the processes out of each other's way: - API calls go through `request()` in [`lib/api.ts`](../../surfsense_local/frontend/src/lib/api.ts), except the Studio viewers, which fetch an artifact's file bytes directly; an ``, `