|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { useState, useCallback, useEffect } from 'react'; |
|
|
import { themeManager } from '../themes/theme-manager.js'; |
|
|
import { LoadedSettings, SettingScope } from '../../config/settings.js'; |
|
|
import { type HistoryItem, MessageType } from '../types.js'; |
|
|
import process from 'node:process'; |
|
|
|
|
|
interface UseThemeCommandReturn { |
|
|
isThemeDialogOpen: boolean; |
|
|
openThemeDialog: () => void; |
|
|
handleThemeSelect: ( |
|
|
themeName: string | undefined, |
|
|
scope: SettingScope, |
|
|
) => void; |
|
|
handleThemeHighlight: (themeName: string | undefined) => void; |
|
|
} |
|
|
|
|
|
export const useThemeCommand = ( |
|
|
loadedSettings: LoadedSettings, |
|
|
setThemeError: (error: string | null) => void, |
|
|
addItem: (item: Omit<HistoryItem, 'id'>, timestamp: number) => void, |
|
|
): UseThemeCommandReturn => { |
|
|
|
|
|
const effectiveTheme = loadedSettings.merged.theme; |
|
|
|
|
|
|
|
|
const [isThemeDialogOpen, setIsThemeDialogOpen] = useState( |
|
|
effectiveTheme === undefined && !process.env.NO_COLOR, |
|
|
); |
|
|
|
|
|
const [, setForceRender] = useState(0); |
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
if (effectiveTheme === undefined) { |
|
|
if (process.env.NO_COLOR) { |
|
|
addItem( |
|
|
{ |
|
|
type: MessageType.INFO, |
|
|
text: 'Theme configuration unavailable due to NO_COLOR env variable.', |
|
|
}, |
|
|
Date.now(), |
|
|
); |
|
|
} |
|
|
|
|
|
return; |
|
|
} |
|
|
|
|
|
if (!themeManager.setActiveTheme(effectiveTheme)) { |
|
|
setIsThemeDialogOpen(true); |
|
|
setThemeError(`Theme "${effectiveTheme}" not found.`); |
|
|
} else { |
|
|
setThemeError(null); |
|
|
} |
|
|
}, [effectiveTheme, setThemeError, addItem]); |
|
|
|
|
|
const openThemeDialog = useCallback(() => { |
|
|
if (process.env.NO_COLOR) { |
|
|
addItem( |
|
|
{ |
|
|
type: MessageType.INFO, |
|
|
text: 'Theme configuration unavailable due to NO_COLOR env variable.', |
|
|
}, |
|
|
Date.now(), |
|
|
); |
|
|
return; |
|
|
} |
|
|
setIsThemeDialogOpen(true); |
|
|
}, [addItem]); |
|
|
|
|
|
const applyTheme = useCallback( |
|
|
(themeName: string | undefined) => { |
|
|
if (!themeManager.setActiveTheme(themeName)) { |
|
|
|
|
|
setIsThemeDialogOpen(true); |
|
|
setThemeError(`Theme "${themeName}" not found.`); |
|
|
} else { |
|
|
setForceRender((v) => v + 1); |
|
|
setThemeError(null); |
|
|
} |
|
|
}, |
|
|
[setForceRender, setThemeError], |
|
|
); |
|
|
|
|
|
const handleThemeHighlight = useCallback( |
|
|
(themeName: string | undefined) => { |
|
|
applyTheme(themeName); |
|
|
}, |
|
|
[applyTheme], |
|
|
); |
|
|
|
|
|
const handleThemeSelect = useCallback( |
|
|
(themeName: string | undefined, scope: SettingScope) => { |
|
|
|
|
|
try { |
|
|
loadedSettings.setValue(scope, 'theme', themeName); |
|
|
applyTheme(loadedSettings.merged.theme); |
|
|
} finally { |
|
|
setIsThemeDialogOpen(false); |
|
|
} |
|
|
}, |
|
|
[applyTheme, loadedSettings], |
|
|
); |
|
|
|
|
|
return { |
|
|
isThemeDialogOpen, |
|
|
openThemeDialog, |
|
|
handleThemeSelect, |
|
|
handleThemeHighlight, |
|
|
}; |
|
|
}; |
|
|
|