From 7e8f379dfbd4d70050ce301a42a38ba9c1f052f4 Mon Sep 17 00:00:00 2001 From: Jacob Richman Date: Thu, 1 May 2025 10:34:07 -0700 Subject: Save settings to ~/.gemini/settings.json and optionally /your/workspace/.gemini/settings.json (#237) --- packages/cli/src/ui/components/ThemeDialog.tsx | 98 ++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 13 deletions(-) (limited to 'packages/cli/src/ui/components/ThemeDialog.tsx') diff --git a/packages/cli/src/ui/components/ThemeDialog.tsx b/packages/cli/src/ui/components/ThemeDialog.tsx index 62ede336..7e8c5afd 100644 --- a/packages/cli/src/ui/components/ThemeDialog.tsx +++ b/packages/cli/src/ui/components/ThemeDialog.tsx @@ -4,33 +4,87 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React from 'react'; -import { Box, Text } from 'ink'; +import React, { useState } from 'react'; +import { Box, Text, useInput } from 'ink'; import { Colors } from '../colors.js'; -import { themeManager } from '../themes/theme-manager.js'; +import { themeManager, DEFAULT_THEME } from '../themes/theme-manager.js'; import { RadioButtonSelect } from './shared/RadioButtonSelect.js'; import { DiffRenderer } from './messages/DiffRenderer.js'; import { colorizeCode } from '../utils/CodeColorizer.js'; +import { LoadedSettings, SettingScope } from '../../config/settings.js'; interface ThemeDialogProps { /** Callback function when a theme is selected */ - onSelect: (themeName: string) => void; + onSelect: (themeName: string | undefined, scope: SettingScope) => void; /** Callback function when a theme is highlighted */ - onHighlight: (themeName: string) => void; + onHighlight: (themeName: string | undefined) => void; + /** The settings object */ + settings: LoadedSettings; } export function ThemeDialog({ onSelect, onHighlight, + settings, }: ThemeDialogProps): React.JSX.Element { + const [selectedScope, setSelectedScope] = useState( + SettingScope.User, + ); + const themeItems = themeManager.getAvailableThemes().map((theme) => ({ label: theme.active ? `${theme.name} (Active)` : theme.name, value: theme.name, })); - const initialIndex = themeItems.findIndex( - (item) => item.value === themeManager.getActiveTheme().name, + const [selectInputKey, setSelectInputKey] = useState(Date.now()); + + const initialThemeIndex = themeItems.findIndex( + (item) => + item.value === + (settings.forScope(selectedScope).settings.theme || DEFAULT_THEME.name), + ); + + const scopeItems = [ + { label: 'User Settings', value: SettingScope.User }, + { label: 'Workspace Settings', value: SettingScope.Workspace }, + ]; + + const handleThemeSelect = (themeName: string) => { + onSelect(themeName, selectedScope); + }; + + const handleScopeHighlight = (scope: SettingScope) => { + setSelectedScope(scope); + setSelectInputKey(Date.now()); + }; + + const handleScopeSelect = (scope: SettingScope) => { + handleScopeHighlight(scope); + setFocusedSection('theme'); // Reset focus to theme section + }; + + const [focusedSection, setFocusedSection] = useState<'theme' | 'scope'>( + 'theme', ); + + useInput((input, key) => { + if (key.tab) { + setFocusedSection((prev) => (prev === 'theme' ? 'scope' : 'theme')); + } + }); + + let otherScopeModifiedMessage = ''; + const otherScope = + selectedScope === SettingScope.User + ? SettingScope.Workspace + : SettingScope.User; + if (settings.forScope(otherScope).settings.theme !== undefined) { + otherScopeModifiedMessage = + settings.forScope(selectedScope).settings.theme !== undefined + ? `(Also modified in ${otherScope})` + : `(Modified in ${otherScope})`; + } + return ( - - Select Theme - + + {focusedSection === 'theme' ? '> ' : ' '}Select Theme{' '} + {otherScopeModifiedMessage} + + + {/* Scope Selection */} + + + {focusedSection === 'scope' ? '> ' : ' '}Apply To + + + + - (Use ↑/↓ arrows and Enter to select) + (Use ↑/↓ arrows and Enter to select, Tab to change focus) -- cgit v1.2.3