fix: theme switching always defaults to dark mode

Root causes:
1. ThemeProvider was imported but never used in App.tsx and showSetupDialog
2. setThemeConfigCallbacks was never called to inject persistence callbacks
3. Preview/save/cancel theme lifecycle had no provider to coordinate

Changes:
- Export setThemeConfigCallbacks from @anthropic/ink
- Wrap App.tsx children with ThemeProvider (initialState from config, onThemeSave persists)
- Wrap showSetupDialog with ThemeProvider for onboarding/trust dialogs
- Call setThemeConfigCallbacks in init.ts to register load/save callbacks
- Update SnapshotUpdateDialog test to account for new ThemeProvider wrapper

Fixes #theme-switching
This commit is contained in:
Bonerush
2026-04-30 16:15:27 +08:00
parent 632f3e199e
commit 71c89e9de4
5 changed files with 168 additions and 202 deletions

View File

@@ -1,38 +1,36 @@
import React from 'react'
import { FpsMetricsProvider } from '../context/fpsMetrics.js'
import { StatsProvider, type StatsStore } from '../context/stats.js'
import { type AppState, AppStateProvider } from '../state/AppState.js'
import { onChangeAppState } from '../state/onChangeAppState.js'
import type { FpsMetrics } from '../utils/fpsTracker.js'
import { ThemeProvider } from '@anthropic/ink'
import React from 'react';
import { FpsMetricsProvider } from '../context/fpsMetrics.js';
import { StatsProvider, type StatsStore } from '../context/stats.js';
import { type AppState, AppStateProvider } from '../state/AppState.js';
import { onChangeAppState } from '../state/onChangeAppState.js';
import type { FpsMetrics } from '../utils/fpsTracker.js';
import { ThemeProvider } from '@anthropic/ink';
import { getGlobalConfig, saveGlobalConfig } from '../utils/config.js';
type Props = {
getFpsMetrics: () => FpsMetrics | undefined
stats?: StatsStore
initialState: AppState
children: React.ReactNode
}
getFpsMetrics: () => FpsMetrics | undefined;
stats?: StatsStore;
initialState: AppState;
children: React.ReactNode;
};
/**
* Top-level wrapper for interactive sessions.
* Provides FPS metrics, stats context, and app state to the component tree.
*/
export function App({
getFpsMetrics,
stats,
initialState,
children,
}: Props): React.ReactNode {
export function App({ getFpsMetrics, stats, initialState, children }: Props): React.ReactNode {
return (
<FpsMetricsProvider getFpsMetrics={getFpsMetrics}>
<StatsProvider store={stats}>
<AppStateProvider
initialState={initialState}
onChangeAppState={onChangeAppState}
>
{children}
<AppStateProvider initialState={initialState} onChangeAppState={onChangeAppState}>
<ThemeProvider
initialState={getGlobalConfig().theme}
onThemeSave={setting => saveGlobalConfig(current => ({ ...current, theme: setting }))}
>
{children}
</ThemeProvider>
</AppStateProvider>
</StatsProvider>
</FpsMetricsProvider>
)
);
}

View File

@@ -5,7 +5,10 @@ import { buildMergePrompt, SnapshotUpdateDialog } from '../SnapshotUpdateDialog.
import { Select } from '../../CustomSelect/index.js';
function getSnapshotDialogFromRenderedTree(rendered: React.ReactElement) {
const appStateProvider = rendered as React.ReactElement<{
const themeProvider = rendered as React.ReactElement<{
children: React.ReactElement;
}>;
const appStateProvider = themeProvider.props.children as React.ReactElement<{
children: React.ReactElement;
}>;
const keybindingSetup = appStateProvider.props.children as React.ReactElement<{