mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-22 19:53:48 +08:00
feat: read local theme on page load (#1114)
Co-authored-by: zqran <uuxnet@gmail.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
Theme,
|
|
||||||
ThemeMode,
|
ThemeMode,
|
||||||
ThemeProviderProps,
|
ThemeProviderProps,
|
||||||
ThemeProviderValue,
|
ThemeProviderValue,
|
||||||
@@ -17,7 +16,15 @@ import {
|
|||||||
ThemeProvider as MuiThemeProvider,
|
ThemeProvider as MuiThemeProvider,
|
||||||
} from '@mui/material/styles';
|
} from '@mui/material/styles';
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
import { createContext, useContext, useEffect, useState } from 'react';
|
import {
|
||||||
|
createContext,
|
||||||
|
useCallback,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
useSyncExternalStore,
|
||||||
|
} from 'react';
|
||||||
|
|
||||||
import useCurrentPageMeta from '@/hooks/use-current-page-meta';
|
import useCurrentPageMeta from '@/hooks/use-current-page-meta';
|
||||||
|
|
||||||
@@ -35,16 +42,31 @@ export const ThemeProvider = ({
|
|||||||
defaultTheme = 'light',
|
defaultTheme = 'light',
|
||||||
children,
|
children,
|
||||||
}: PropsWithChildren<ThemeProviderProps>) => {
|
}: PropsWithChildren<ThemeProviderProps>) => {
|
||||||
const [theme, setTheme] = useState<Theme>(defaultTheme);
|
const localStorageThemeMode = useSyncExternalStore<ThemeMode>(
|
||||||
const [mode, setMode] = useState<ThemeMode>('auto');
|
useCallback(cb => {
|
||||||
|
localStorageThemeHelper.callback.add(cb);
|
||||||
|
return () => {
|
||||||
|
localStorageThemeHelper.callback.delete(cb);
|
||||||
|
};
|
||||||
|
}, []),
|
||||||
|
useCallback(() => localStorageThemeHelper.get() ?? 'light', []),
|
||||||
|
useCallback(() => defaultTheme, [defaultTheme])
|
||||||
|
);
|
||||||
|
const [mode, setMode] = useState<ThemeMode>(defaultTheme);
|
||||||
|
if (localStorageThemeMode !== mode) {
|
||||||
|
setMode(localStorageThemeMode);
|
||||||
|
}
|
||||||
const { mode: editorMode = 'page' } = useCurrentPageMeta() || {};
|
const { mode: editorMode = 'page' } = useCurrentPageMeta() || {};
|
||||||
const themeStyle =
|
const themeStyle =
|
||||||
theme === 'light' ? getLightTheme(editorMode) : getDarkTheme(editorMode);
|
mode === 'light' ? getLightTheme(editorMode) : getDarkTheme(editorMode);
|
||||||
const changeMode = (themeMode: ThemeMode) => {
|
const changeMode = useCallback(
|
||||||
themeMode !== mode && setMode(themeMode);
|
(themeMode: ThemeMode) => {
|
||||||
// Remember the theme mode which user selected for next time
|
themeMode !== mode && setMode(themeMode);
|
||||||
localStorageThemeHelper.set(themeMode);
|
// Remember the theme mode which user selected for next time
|
||||||
};
|
localStorageThemeHelper.set(themeMode);
|
||||||
|
},
|
||||||
|
[mode]
|
||||||
|
);
|
||||||
|
|
||||||
// ===================== A temporary solution, just use system theme and not remember the user selected ====================
|
// ===================== A temporary solution, just use system theme and not remember the user selected ====================
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -57,9 +79,9 @@ export const ThemeProvider = ({
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
setTheme(mode === 'auto' ? theme : mode);
|
// setTheme(mode === 'auto' ? theme : mode);
|
||||||
}, [mode, setTheme, theme]);
|
// }, [mode, setTheme, theme]);
|
||||||
// ===================== ====================
|
// ===================== ====================
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
@@ -93,7 +115,12 @@ export const ThemeProvider = ({
|
|||||||
return (
|
return (
|
||||||
// Use MuiThemeProvider is just because some Transitions in Mui components need it
|
// Use MuiThemeProvider is just because some Transitions in Mui components need it
|
||||||
<MuiThemeProvider theme={muiTheme}>
|
<MuiThemeProvider theme={muiTheme}>
|
||||||
<ThemeContext.Provider value={{ mode, changeMode, theme: themeStyle }}>
|
<ThemeContext.Provider
|
||||||
|
value={useMemo(
|
||||||
|
() => ({ mode, changeMode, theme: themeStyle }),
|
||||||
|
[changeMode, mode, themeStyle]
|
||||||
|
)}
|
||||||
|
>
|
||||||
<Global
|
<Global
|
||||||
styles={css`
|
styles={css`
|
||||||
:root {
|
:root {
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import { ThemeMode } from '../types';
|
|||||||
|
|
||||||
export class LocalStorageThemeHelper {
|
export class LocalStorageThemeHelper {
|
||||||
name = 'Affine-theme-mode';
|
name = 'Affine-theme-mode';
|
||||||
|
callback = new Set<() => void>();
|
||||||
get = (): ThemeMode | null => {
|
get = (): ThemeMode | null => {
|
||||||
return localStorage.getItem(this.name) as ThemeMode | null;
|
return localStorage.getItem(this.name) as ThemeMode | null;
|
||||||
};
|
};
|
||||||
set = (mode: ThemeMode) => {
|
set = (mode: ThemeMode) => {
|
||||||
localStorage.setItem(this.name, mode);
|
localStorage.setItem(this.name, mode);
|
||||||
|
this.callback.forEach(cb => cb());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user