mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-10 22:21:22 -07:00
fix(ui): escaping theme dialog no longer resets theme to default (#11323)
Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
@@ -335,6 +335,7 @@ export const AppContainer = (props: AppContainerProps) => {
|
||||
const {
|
||||
isThemeDialogOpen,
|
||||
openThemeDialog,
|
||||
closeThemeDialog,
|
||||
handleThemeSelect,
|
||||
handleThemeHighlight,
|
||||
} = useThemeCommand(
|
||||
@@ -1266,6 +1267,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
|
||||
const uiActions: UIActions = useMemo(
|
||||
() => ({
|
||||
handleThemeSelect,
|
||||
closeThemeDialog,
|
||||
handleThemeHighlight,
|
||||
handleAuthSelect,
|
||||
setAuthState,
|
||||
@@ -1291,6 +1293,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
|
||||
}),
|
||||
[
|
||||
handleThemeSelect,
|
||||
closeThemeDialog,
|
||||
handleThemeHighlight,
|
||||
handleAuthSelect,
|
||||
setAuthState,
|
||||
|
||||
@@ -115,6 +115,7 @@ export const DialogManager = ({
|
||||
)}
|
||||
<ThemeDialog
|
||||
onSelect={uiActions.handleThemeSelect}
|
||||
onCancel={uiActions.closeThemeDialog}
|
||||
onHighlight={uiActions.handleThemeHighlight}
|
||||
settings={settings}
|
||||
availableTerminalHeight={
|
||||
|
||||
@@ -12,6 +12,7 @@ import { KeypressProvider } from '../contexts/KeypressContext.js';
|
||||
import { SettingsContext } from '../contexts/SettingsContext.js';
|
||||
import { DEFAULT_THEME, themeManager } from '../themes/theme-manager.js';
|
||||
import { act } from 'react';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
|
||||
const createMockSettings = (
|
||||
userSettings = {},
|
||||
@@ -58,6 +59,7 @@ const createMockSettings = (
|
||||
describe('ThemeDialog Snapshots', () => {
|
||||
const baseProps = {
|
||||
onSelect: vi.fn(),
|
||||
onCancel: vi.fn(),
|
||||
onHighlight: vi.fn(),
|
||||
availableTerminalHeight: 40,
|
||||
terminalWidth: 120,
|
||||
@@ -105,4 +107,28 @@ describe('ThemeDialog Snapshots', () => {
|
||||
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should call onCancel when ESC is pressed', async () => {
|
||||
const mockOnCancel = vi.fn();
|
||||
const settings = createMockSettings();
|
||||
const { stdin } = render(
|
||||
<SettingsContext.Provider value={settings}>
|
||||
<KeypressProvider kittyProtocolEnabled={false}>
|
||||
<ThemeDialog
|
||||
{...baseProps}
|
||||
onCancel={mockOnCancel}
|
||||
settings={settings}
|
||||
/>
|
||||
</KeypressProvider>
|
||||
</SettingsContext.Provider>,
|
||||
);
|
||||
|
||||
act(() => {
|
||||
stdin.write('\x1b');
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockOnCancel).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,7 +20,10 @@ import { ScopeSelector } from './shared/ScopeSelector.js';
|
||||
|
||||
interface ThemeDialogProps {
|
||||
/** Callback function when a theme is selected */
|
||||
onSelect: (themeName: string | undefined, scope: SettingScope) => void;
|
||||
onSelect: (themeName: string, scope: SettingScope) => void;
|
||||
|
||||
/** Callback function when the dialog is cancelled */
|
||||
onCancel: () => void;
|
||||
|
||||
/** Callback function when a theme is highlighted */
|
||||
onHighlight: (themeName: string | undefined) => void;
|
||||
@@ -32,6 +35,7 @@ interface ThemeDialogProps {
|
||||
|
||||
export function ThemeDialog({
|
||||
onSelect,
|
||||
onCancel,
|
||||
onHighlight,
|
||||
settings,
|
||||
availableTerminalHeight,
|
||||
@@ -42,9 +46,9 @@ export function ThemeDialog({
|
||||
);
|
||||
|
||||
// Track the currently highlighted theme name
|
||||
const [highlightedThemeName, setHighlightedThemeName] = useState<
|
||||
string | undefined
|
||||
>(settings.merged.ui?.theme || DEFAULT_THEME.name);
|
||||
const [highlightedThemeName, setHighlightedThemeName] = useState<string>(
|
||||
settings.merged.ui?.theme || DEFAULT_THEME.name,
|
||||
);
|
||||
|
||||
// Generate theme items filtered by selected scope
|
||||
const customThemes =
|
||||
@@ -112,7 +116,7 @@ export function ThemeDialog({
|
||||
setMode((prev) => (prev === 'theme' ? 'scope' : 'theme'));
|
||||
}
|
||||
if (key.name === 'escape') {
|
||||
onSelect(undefined, selectedScope);
|
||||
onCancel();
|
||||
}
|
||||
},
|
||||
{ isActive: true },
|
||||
|
||||
@@ -13,10 +13,8 @@ import { type SettingScope } from '../../config/settings.js';
|
||||
import type { AuthState } from '../types.js';
|
||||
|
||||
export interface UIActions {
|
||||
handleThemeSelect: (
|
||||
themeName: string | undefined,
|
||||
scope: SettingScope,
|
||||
) => void;
|
||||
handleThemeSelect: (themeName: string, scope: SettingScope) => void;
|
||||
closeThemeDialog: () => void;
|
||||
handleThemeHighlight: (themeName: string | undefined) => void;
|
||||
handleAuthSelect: (
|
||||
authType: AuthType | undefined,
|
||||
|
||||
@@ -13,10 +13,8 @@ import process from 'node:process';
|
||||
interface UseThemeCommandReturn {
|
||||
isThemeDialogOpen: boolean;
|
||||
openThemeDialog: () => void;
|
||||
handleThemeSelect: (
|
||||
themeName: string | undefined,
|
||||
scope: SettingScope,
|
||||
) => void; // Added scope
|
||||
closeThemeDialog: () => void;
|
||||
handleThemeSelect: (themeName: string, scope: SettingScope) => void;
|
||||
handleThemeHighlight: (themeName: string | undefined) => void;
|
||||
}
|
||||
|
||||
@@ -63,8 +61,14 @@ export const useThemeCommand = (
|
||||
[applyTheme],
|
||||
);
|
||||
|
||||
const closeThemeDialog = useCallback(() => {
|
||||
// Re-apply the saved theme to revert any preview changes from highlighting
|
||||
applyTheme(loadedSettings.merged.ui?.theme);
|
||||
setIsThemeDialogOpen(false);
|
||||
}, [applyTheme, loadedSettings]);
|
||||
|
||||
const handleThemeSelect = useCallback(
|
||||
(themeName: string | undefined, scope: SettingScope) => {
|
||||
(themeName: string, scope: SettingScope) => {
|
||||
try {
|
||||
// Merge user and workspace custom themes (workspace takes precedence)
|
||||
const mergedCustomThemes = {
|
||||
@@ -95,6 +99,7 @@ export const useThemeCommand = (
|
||||
return {
|
||||
isThemeDialogOpen,
|
||||
openThemeDialog,
|
||||
closeThemeDialog,
|
||||
handleThemeSelect,
|
||||
handleThemeHighlight,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user