fix: prevent dashboard and TUI startup theme flash - #34248
Open
sgtworkman wants to merge 8 commits into
Open
sgtworkman wants to merge 8 commits into
sgtworkman wants to merge 8 commits into
Conversation
…up flicker The /chat tab spawned the full-screen TUI behind a PTY at the default 80x24, then let the browser's startup burst of RESIZE escapes (onopen, post-layout refit, ResizeObserver) drive it to the real size. Because the TUI clears and repaints on every resize, users saw it flash through several full repaints before settling. Hold the spawn until the browser reports its size, coalescing the rapid follow-up resizes within a short settle window, then boot the child once at the final size. Clients that never send a RESIZE fall back to 80x24 after a bounded wait; non-resize bytes that arrive first are buffered and replayed so no keystrokes are lost. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Ink TUI renders with its built-in DEFAULT_THEME until it receives the configured skin, which previously rode only on gateway.ready. That event is emitted after discover_mcp_tools() in the gateway entry point. For users with MCP servers configured, discovery connects to (often remote) servers and can take seconds, leaving the TUI in the default theme the whole time before it visibly snapped to the user's theme. Emit a cheap, side-effect-free skin.changed event up front, before MCP discovery, so the theme applies on the first event the TUI processes. gateway.ready still carries the skin (applySkin is idempotent), so nothing is lost for old clients or a stale stdout pipe. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
entry.tsx clears the screen and renders App immediately, so the first frame painted in DEFAULT_THEME and visibly snapped to the user's theme once the skin event was read off the gateway stdio. Add a $skinReady atom that App waits on before its first paint: it renders nothing (the screen is already cleared) until the first skin.changed/gateway.ready applies the theme, then paints once in the user's colors. A 1.5s timeout fallback releases the gate so an old gateway that never emits a skin can't strand the UI on a blank screen. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The dashboard restored the active theme NAME from localStorage but userThemeDefs started empty, so resolveTheme() fell back to defaultTheme for custom (user-YAML) themes like GUNNY-COMMAND until /api/dashboard/themes responded — a visible default-palette flash on every load. Built-ins ship in the bundle; user themes only exist server-side, so the name alone can't repaint them. Cache the full user-theme definitions map in localStorage after the API returns, seed userThemeDefs from that cache so the first render resolves the real definition, and pre-apply the cached theme's CSS vars at module load (before React mounts/paints). The apply effect also moves to useLayoutEffect so later theme switches commit before paint too. First render of a known/cached custom theme is now flash-free; only a first-ever load with no cache still falls back to default. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This was referenced May 31, 2026
…resize-flash # Conflicts: # tui_gateway/entry.py # web/src/themes/context.tsx
teknium1
reviewed
Jul 13, 2026
teknium1
left a comment
Collaborator
There was a problem hiding this comment.
Thanks for covering the dashboard, Ink TUI, and embedded-chat startup paths. The dashboard and TUI premises remain present on current main: web/src/themes/context.tsx:435-496 initializes custom definitions only after the API response, while ui-tui/src/app.tsx:9-24 renders before gateway skin events are applied.
Problems
- The PTY sizing hunk is based on a superseded lifecycle. Current main creates attach-token sessions through
PTY_REGISTRY.attach_or_spawninhermes_cli/web_server.py:15545-15596, rather than the direct bridge pump the PR modifies. This needs a registry-aware reimplementation. - PR
hermes_cli/web_server.py:8839passes raw browser dimensions toPtyBridge.spawn; later resize handling clamps those values inhermes_cli/pty_bridge.py:218-239.
Suggested changes
- Salvage the dashboard/TUI theme work, then move initial-size negotiation to the current registry spawn boundary and clamp the initial dimensions. Cover both fresh and attach-token PTY paths.
Automated hermes-sweeper review.
…-fixes # Conflicts: # hermes_cli/web_server.py # ui-tui/src/app/createGatewayEventHandler.ts
Contributor
Author
|
Addressed on current main in 91b804c.
Proof: PTY startup/resize tests pass 3/3; bridge suites pass 23 with 19 platform skips; TUI typecheck passes and the full TUI suite passes 1125 with 1 skip; dashboard typecheck passes and dashboard tests pass 72/72. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
useLayoutEffectto prevent default-palette flashes on reload/theme hydration.Validation
env -u NODE_ENV npm --prefix web ci --include=dev— passedenv -u NODE_ENV npm --prefix web run build— passednpm --prefix ui-tui run build— passedvenv/bin/python -m py_compile hermes_cli/web_server.py tui_gateway/entry.py tui_gateway/server.py— passedenv -u NODE_ENV npx --prefix ui-tui vitest run --root ui-tui src/__tests__/createGatewayEventHandler.test.ts— passed (45 tests)scripts/run_tests.sh tests/hermes_cli/test_web_server.py tests/test_tui_gateway_server.py tests/hermes_cli/test_tui_bundled.py— 338 passed, 1 unrelated existing browser-launch assertion failed intests/test_tui_gateway_server.py::test_browser_manage_connect_default_local_reports_launch_hintManual QA
/api/statusreports v0.15.1 and served root HTML includes__HERMES_THEME_BOOTSTRAP__plus embedded chat bootstrap.Safety