Files
readest/apps/readest-app/src/store/themeStore.ts
T

86 lines
2.7 KiB
TypeScript

import { create } from 'zustand';
import { getThemeCode, ThemeCode } from '@/utils/style';
import { Palette, ThemeMode } from '@/styles/themes';
import { isWebAppPlatform } from '@/services/environment';
interface ThemeState {
themeMode: ThemeMode;
themeColor: string;
systemIsDarkMode: boolean;
themeCode: ThemeCode;
isDarkMode: boolean;
setThemeMode: (mode: ThemeMode) => void;
setThemeColor: (color: string) => void;
updateAppTheme: (color: keyof Palette) => void;
}
const getInitialThemeMode = (): ThemeMode => {
if (typeof window !== 'undefined' && localStorage) {
return (localStorage.getItem('themeMode') as ThemeMode) || 'auto';
}
return 'auto';
};
const getInitialThemeColor = (): string => {
if (typeof window !== 'undefined' && localStorage) {
return localStorage.getItem('themeColor') || 'default';
}
return 'default';
};
export const useThemeStore = create<ThemeState>((set, get) => {
const initialThemeMode = getInitialThemeMode();
const initialThemeColor = getInitialThemeColor();
const systemIsDarkMode =
typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches;
const isDarkMode =
initialThemeMode === 'dark' || (initialThemeMode === 'auto' && systemIsDarkMode);
const themeCode = getThemeCode();
if (typeof window !== 'undefined') {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleSystemThemeChange = () => {
set({ systemIsDarkMode: mediaQuery.matches });
};
mediaQuery.addEventListener('change', handleSystemThemeChange);
}
return {
themeMode: initialThemeMode,
themeColor: initialThemeColor,
systemIsDarkMode,
isDarkMode,
themeCode,
setThemeMode: (mode) => {
if (typeof window !== 'undefined' && localStorage) {
localStorage.setItem('themeMode', mode);
}
const isDarkMode = mode === 'dark' || (mode === 'auto' && get().systemIsDarkMode);
document.documentElement.setAttribute(
'data-theme',
`${get().themeColor}-${isDarkMode ? 'dark' : 'light'}`,
);
set({ themeMode: mode, isDarkMode });
set({ themeCode: getThemeCode() });
},
setThemeColor: (color) => {
if (typeof window !== 'undefined' && localStorage) {
localStorage.setItem('themeColor', color);
}
document.documentElement.setAttribute(
'data-theme',
`${color}-${get().isDarkMode ? 'dark' : 'light'}`,
);
set({ themeColor: color });
set({ themeCode: getThemeCode() });
},
updateAppTheme: (color) => {
if (isWebAppPlatform()) {
const { palette } = get().themeCode;
document.querySelector('meta[name="theme-color"]')?.setAttribute('content', palette[color]);
}
},
};
});