summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/cli/src/gemini.ts19
-rw-r--r--packages/cli/src/ui/App.tsx20
-rw-r--r--packages/cli/src/ui/hooks/useThemeCommand.ts73
3 files changed, 92 insertions, 20 deletions
diff --git a/packages/cli/src/gemini.ts b/packages/cli/src/gemini.ts
index 420f3242..32e34c20 100644
--- a/packages/cli/src/gemini.ts
+++ b/packages/cli/src/gemini.ts
@@ -24,7 +24,24 @@ async function main() {
const settings = loadSettings(process.cwd());
const config = await loadCliConfig(settings.merged);
if (settings.merged.theme) {
- themeManager.setActiveTheme(settings.merged.theme);
+ try {
+ themeManager.setActiveTheme(settings.merged.theme);
+ } catch (error: unknown) {
+ // If the theme is not found during initial load, log a warning and continue.
+ // The useThemeCommand hook in App.tsx will handle opening the dialog.
+ if (
+ error instanceof Error &&
+ error.message.includes('Theme') &&
+ error.message.includes('not found')
+ ) {
+ console.warn(
+ `Warning: ${error instanceof Error ? error.message : String(error)}`,
+ );
+ } else {
+ // Re-throw other errors to be caught by the main catch block
+ throw error;
+ }
+ }
}
// hop into sandbox if we are outside and sandboxing is enabled
diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx
index 9fe651b5..725a2012 100644
--- a/packages/cli/src/ui/App.tsx
+++ b/packages/cli/src/ui/App.tsx
@@ -39,12 +39,13 @@ export const App = ({ config, settings, cliVersion }: AppProps) => {
const { history, addItem, clearItems } = useHistory();
const [startupWarnings, setStartupWarnings] = useState<string[]>([]);
const [showHelp, setShowHelp] = useState<boolean>(false);
+ const [themeError, setThemeError] = useState<string | null>(null);
const {
isThemeDialogOpen,
openThemeDialog,
handleThemeSelect,
handleThemeHighlight,
- } = useThemeCommand(settings);
+ } = useThemeCommand(settings, setThemeError);
const [staticKey, setStaticKey] = useState(0);
const refreshStatic = useCallback(() => {
@@ -191,11 +192,18 @@ export const App = ({ config, settings, cliVersion }: AppProps) => {
)}
{isThemeDialogOpen ? (
- <ThemeDialog
- onSelect={handleThemeSelect}
- onHighlight={handleThemeHighlight}
- settings={settings}
- />
+ <Box flexDirection="column">
+ {themeError && (
+ <Box marginBottom={1}>
+ <Text color={Colors.AccentRed}>{themeError}</Text>
+ </Box>
+ )}
+ <ThemeDialog
+ onSelect={handleThemeSelect}
+ onHighlight={handleThemeHighlight}
+ settings={settings}
+ />
+ </Box>
) : (
<>
<LoadingIndicator
diff --git a/packages/cli/src/ui/hooks/useThemeCommand.ts b/packages/cli/src/ui/hooks/useThemeCommand.ts
index c32a7c2e..b1ae170f 100644
--- a/packages/cli/src/ui/hooks/useThemeCommand.ts
+++ b/packages/cli/src/ui/hooks/useThemeCommand.ts
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import { useState, useCallback } from 'react';
+import { useState, useCallback, useEffect } from 'react';
import { themeManager } from '../themes/theme-manager.js';
import { LoadedSettings, SettingScope } from '../../config/settings.js'; // Import LoadedSettings, AppSettings, MergedSetting
@@ -20,36 +20,83 @@ interface UseThemeCommandReturn {
export const useThemeCommand = (
loadedSettings: LoadedSettings,
+ setThemeError: (error: string | null) => void,
): UseThemeCommandReturn => {
// Determine the effective theme
const effectiveTheme = loadedSettings.merged.theme;
// Initial state: Open dialog if no theme is set in either user or workspace settings
- const [isThemeDialogOpen, setIsThemeDialogOpen] = useState(
- effectiveTheme === undefined,
- );
+ const [isThemeDialogOpen, setIsThemeDialogOpen] = useState(false);
// TODO: refactor how theme's are accessed to avoid requiring a forced render.
const [, setForceRender] = useState(0);
+ // Apply initial theme on component mount
+ useEffect(() => {
+ try {
+ themeManager.setActiveTheme(effectiveTheme);
+ setThemeError(null); // Clear any previous theme error on success
+ } catch (error: unknown) {
+ // If theme is not found during initial load, open the theme selection dialog and set error message
+ if (
+ error instanceof Error &&
+ error.message.includes('Theme') &&
+ error.message.includes('not found')
+ ) {
+ setIsThemeDialogOpen(true);
+ setThemeError(
+ `Error: ${error instanceof Error ? error.message : String(error)}`,
+ );
+ } else {
+ console.error(
+ `Error setting initial theme: ${error instanceof Error ? error.message : String(error)}`,
+ );
+ setThemeError(
+ `Error setting initial theme: ${error instanceof Error ? error.message : String(error)}`,
+ );
+ }
+ }
+ }, [effectiveTheme, setThemeError]); // Re-run if effectiveTheme or setThemeError changes
+
const openThemeDialog = useCallback(() => {
setIsThemeDialogOpen(true);
}, []);
- const applyTheme = useCallback((themeName: string | undefined) => {
- try {
- themeManager.setActiveTheme(themeName);
- setForceRender((v) => v + 1); // Trigger potential re-render
- } catch (error) {
- console.error(`Error setting theme: ${error}`);
- }
- }, []);
+ const applyTheme = useCallback(
+ (themeName: string | undefined) => {
+ try {
+ themeManager.setActiveTheme(themeName);
+ setForceRender((v) => v + 1); // Trigger potential re-render
+ setThemeError(null); // Clear any previous theme error on success
+ } catch (error: unknown) {
+ // If theme is not found, open the theme selection dialog and set error message
+ if (
+ error instanceof Error &&
+ error.message.includes('Theme') &&
+ error.message.includes('not found')
+ ) {
+ setIsThemeDialogOpen(true);
+ setThemeError(
+ `Error: ${error instanceof Error ? error.message : String(error)}`,
+ );
+ } else {
+ console.error(
+ `Error setting theme: ${error instanceof Error ? error.message : String(error)}`,
+ );
+ setThemeError(
+ `Error setting theme: ${error instanceof Error ? error.message : String(error)}`,
+ );
+ }
+ }
+ },
+ [setForceRender, setThemeError],
+ );
const handleThemeHighlight = useCallback(
(themeName: string | undefined) => {
applyTheme(themeName);
},
[applyTheme],
- ); // Added applyTheme to dependencies
+ );
const handleThemeSelect = useCallback(
(themeName: string | undefined, scope: SettingScope) => {