fix(cli): restore first-launch theme prompt (#703)

This commit is contained in:
Jacob Richman 2025-06-02 19:09:11 -07:00 committed by GitHub
parent 2ab7e3da71
commit 447826ab40
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 11 deletions

View File

@ -188,7 +188,8 @@ describe('App UI', () => {
} }
mockConfig.getShowMemoryUsage.mockReturnValue(false); // Default for most tests mockConfig.getShowMemoryUsage.mockReturnValue(false); // Default for most tests
mockSettings = createMockSettings(); // Ensure a theme is set so the theme dialog does not appear.
mockSettings = createMockSettings({ theme: 'Default' });
}); });
afterEach(() => { afterEach(() => {
@ -235,7 +236,10 @@ describe('App UI', () => {
}); });
it('should display custom contextFileName in footer when set and count is 1', async () => { it('should display custom contextFileName in footer when set and count is 1', async () => {
mockSettings = createMockSettings({ contextFileName: 'AGENTS.MD' }); mockSettings = createMockSettings({
contextFileName: 'AGENTS.MD',
theme: 'Default',
});
mockConfig.getGeminiMdFileCount.mockReturnValue(1); mockConfig.getGeminiMdFileCount.mockReturnValue(1);
mockConfig.getDebugMode.mockReturnValue(false); mockConfig.getDebugMode.mockReturnValue(false);
mockConfig.getShowMemoryUsage.mockReturnValue(false); mockConfig.getShowMemoryUsage.mockReturnValue(false);
@ -253,7 +257,10 @@ describe('App UI', () => {
}); });
it('should display custom contextFileName with plural when set and count is > 1', async () => { it('should display custom contextFileName with plural when set and count is > 1', async () => {
mockSettings = createMockSettings({ contextFileName: 'MY_NOTES.TXT' }); mockSettings = createMockSettings({
contextFileName: 'MY_NOTES.TXT',
theme: 'Default',
});
mockConfig.getGeminiMdFileCount.mockReturnValue(3); mockConfig.getGeminiMdFileCount.mockReturnValue(3);
mockConfig.getDebugMode.mockReturnValue(false); mockConfig.getDebugMode.mockReturnValue(false);
mockConfig.getShowMemoryUsage.mockReturnValue(false); mockConfig.getShowMemoryUsage.mockReturnValue(false);
@ -271,7 +278,10 @@ describe('App UI', () => {
}); });
it('should not display context file message if count is 0, even if contextFileName is set', async () => { it('should not display context file message if count is 0, even if contextFileName is set', async () => {
mockSettings = createMockSettings({ contextFileName: 'ANY_FILE.MD' }); mockSettings = createMockSettings({
contextFileName: 'ANY_FILE.MD',
theme: 'Default',
});
mockConfig.getGeminiMdFileCount.mockReturnValue(0); mockConfig.getGeminiMdFileCount.mockReturnValue(0);
mockConfig.getDebugMode.mockReturnValue(false); mockConfig.getDebugMode.mockReturnValue(false);
mockConfig.getShowMemoryUsage.mockReturnValue(false); mockConfig.getShowMemoryUsage.mockReturnValue(false);
@ -328,4 +338,21 @@ describe('App UI', () => {
await Promise.resolve(); await Promise.resolve();
expect(lastFrame()).toContain('Using 2 MCP servers'); expect(lastFrame()).toContain('Using 2 MCP servers');
}); });
it('should display theme dialog if no theme is set in settings', async () => {
mockSettings = createMockSettings({});
mockConfig.getDebugMode.mockReturnValue(false);
mockConfig.getShowMemoryUsage.mockReturnValue(false);
const { lastFrame, unmount } = render(
<App
config={mockConfig as unknown as ServerConfig}
settings={mockSettings}
cliVersion="1.0.0"
/>,
);
currentUnmount = unmount;
expect(lastFrame()).toContain('Select Theme');
});
}); });

View File

@ -26,18 +26,23 @@ export const useThemeCommand = (
const effectiveTheme = loadedSettings.merged.theme; const effectiveTheme = loadedSettings.merged.theme;
// Initial state: Open dialog if no theme is set in either user or workspace settings // Initial state: Open dialog if no theme is set in either user or workspace settings
const [isThemeDialogOpen, setIsThemeDialogOpen] = useState(false); const [isThemeDialogOpen, setIsThemeDialogOpen] = useState(
effectiveTheme === undefined, // Open dialog if no theme is set initially
);
// TODO: refactor how theme's are accessed to avoid requiring a forced render. // TODO: refactor how theme's are accessed to avoid requiring a forced render.
const [, setForceRender] = useState(0); const [, setForceRender] = useState(0);
// Apply initial theme on component mount // Apply initial theme on component mount
useEffect(() => { useEffect(() => {
if (!themeManager.setActiveTheme(effectiveTheme)) { // Only try to set a theme if one is actually defined.
// If theme is not found during initial load, open the theme selection dialog and set error message // If effectiveTheme was undefined, the dialog is already open due to useState above.
setIsThemeDialogOpen(true); if (effectiveTheme !== undefined) {
setThemeError(`Theme "${effectiveTheme}" not found.`); if (!themeManager.setActiveTheme(effectiveTheme)) {
} else { setIsThemeDialogOpen(true);
setThemeError(null); // Clear any previous theme error on success setThemeError(`Theme "${effectiveTheme}" not found.`);
} else {
setThemeError(null); // Clear any previous theme error on success
}
} }
}, [effectiveTheme, setThemeError]); // Re-run if effectiveTheme or setThemeError changes }, [effectiveTheme, setThemeError]); // Re-run if effectiveTheme or setThemeError changes