Repository navigation
perf(settings): apply and mirror the theme only when a theme input changes (#784) - #1400
Conversation
…anges (#784) useThemeSync selected the whole settings object and the slice re-applied inside chrome-only toggles, so unrelated preferences rewrote the palette, fired THEME_CHANGED_EVENT for every xterm/Monaco, and sent the full settings over IPC. Measured on main: 2 applications per toggle, 1 per dispatch flag. Now 0; theme edits still apply immediately and mirror once, with only the theme keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, hydration and same-frame paint (#1400 review a) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review disposition (head Fixed (a, round 1: all three were test gaps; the code was already correct)
All six of a's surviving mutations are killed. Declined (b, minor)
🤖 Generated with Claude Code |
|
Disposition addendum: reviewer c MERGE-READY. c traced six journeys end to end (theme change, saved-theme edit, extension theme, unrelated toggle, hydration, phone reconnect) with no regressions. Declined (c, minor): the slice's 🤖 Generated with Claude Code |
Fixes #784.
Plan:
docs/plans/2026-09-27-theme-sync-projection.md.Problem
useThemeSyncselected the whole settings object, and the settings slice re-applied the theme inside chrome-only toggles. So an unrelated preference or a dispatch colour flag rewrote the inline palette, fonts and radii, firedTHEME_CHANGED_EVENT(which every xterm and Monaco re-reads), and sent the full settings object to main for the phone.Measured on origin/main (the new test's counts): each of these costs 2 theme applications:
A dispatch flag costs 1. Every mirror carries 40 keys.
What merges
THEME_SETTING_KEYSintheme.ts: exactly the settingsapplyTheme/resolveThemePayloadread (mode,contrast,accent,fontFamily,cornerStyle,savedThemes,customAppearanceJson). The WHY comment says a new fieldapplyThemereads must be added here.useThemeSyncselects only those keys (useShallow) plus the installed extensions. It applies and mirrors only when one of them changes, and the mirror now carries only the theme keys. The phone merges the snapshot into its defaults and runsapplyTheme, nothing else (applyRemoteThemeSettings).setSettingsstill applies synchronously, so the change is visible in the same frame, but only when the patch touches a theme key;Preserved:
Tests
useThemeSync.renderer.test.tsxcounts theme applications (THEME_CHANGED_EVENT) and mirror calls per change:After review a:
THEME_SETTING_KEYSapplies and mirrors its new value;mode: 'custom'with its resolved palette;setSettingsstill paints;Fail-first: 6 of the original 8 fail on origin/main.
Mutations, each killed:
setSettingsalways applying;mode,fontFamilyorcustomAppearanceJsonfrom the list;Gates:
npx tsc -b+src/renderer/src/features/settings+src/renderer/src/app-state/{settings,uiShell}+src/remote-clienton3831fc31(36 files, 244 tests).🤖 Generated with Claude Code