diff --git a/web/helpers/atoms/Setting.atom.ts b/web/helpers/atoms/Setting.atom.ts index 904e85fe5..5f220be46 100644 --- a/web/helpers/atoms/Setting.atom.ts +++ b/web/helpers/atoms/Setting.atom.ts @@ -11,15 +11,30 @@ export const janSettingScreenAtom = atom([]) export const THEME = 'themeAppearance' export const REDUCE_TRANSPARENT = 'reduceTransparent' export const SPELL_CHECKING = 'spellChecking' -export const themesOptionsAtom = atom<{ name: string; value: string }[]>([]) -export const janThemesPathAtom = atom(undefined) +export const THEME_DATA = 'themeData' +export const THEME_OPTIONS = 'themeOptions' +export const THEME_PATH = 'themePath' +export const themesOptionsAtom = atomWithStorage< + { name: string; value: string }[] +>(THEME_OPTIONS, [], undefined, { getOnInit: true }) +export const janThemesPathAtom = atomWithStorage( + THEME_PATH, + undefined, + undefined, + { getOnInit: true } +) export const selectedThemeIdAtom = atomWithStorage( THEME, '', undefined, { getOnInit: true } ) -export const themeDataAtom = atom(undefined) +export const themeDataAtom = atomWithStorage( + THEME_DATA, + undefined, + undefined, + { getOnInit: true } +) export const reduceTransparentAtom = atomWithStorage( REDUCE_TRANSPARENT, false, diff --git a/web/hooks/useLoadTheme.ts b/web/hooks/useLoadTheme.ts index eb9455da8..66915e669 100644 --- a/web/hooks/useLoadTheme.ts +++ b/web/hooks/useLoadTheme.ts @@ -4,7 +4,7 @@ import { useTheme } from 'next-themes' import { fs, joinPath } from '@janhq/core' -import { useAtom, useAtomValue, useSetAtom } from 'jotai' +import { useAtom, useAtomValue } from 'jotai' import cssVars from '@/utils/jsonToCssVariables' @@ -20,8 +20,8 @@ type NativeThemeProps = 'light' | 'dark' export const useLoadTheme = () => { const janDataFolderPath = useAtomValue(janDataFolderPathAtom) - const setThemeOptions = useSetAtom(themesOptionsAtom) - const setThemePath = useSetAtom(janThemesPathAtom) + const [themeOptions, setThemeOptions] = useAtom(themesOptionsAtom) + const [themePath, setThemePath] = useAtom(janThemesPathAtom) const [themeData, setThemeData] = useAtom(themeDataAtom) const [selectedIdTheme, setSelectedIdTheme] = useAtom(selectedThemeIdAtom) const { setTheme } = useTheme() @@ -84,11 +84,23 @@ export const useLoadTheme = () => { setThemePath, ]) - useEffect(() => { - getThemes() + const applyTheme = useCallback(async () => { + if (!themeData || !themeOptions || !themePath) { + await getThemes() + } else { + const variables = cssVars(themeData.variables) + const headTag = document.getElementsByTagName('head')[0] + const styleTag = document.createElement('style') + styleTag.innerHTML = `:root {${variables}}` + headTag.appendChild(styleTag) + } setNativeTheme(themeData?.nativeTheme as NativeThemeProps) + }, [themeData, themeOptions, themePath, getThemes]) + + useEffect(() => { + applyTheme() }, [ - getThemes, + applyTheme, selectedIdTheme, setNativeTheme, setSelectedIdTheme,