fix: prevent share pages from overriding the user's theme preference (#17098)

This commit is contained in:
euvre
2026-07-20 15:46:47 +08:00
committed by GitHub
parent 624b4b03f3
commit 67a2310ea4

View File

@@ -1,5 +1,12 @@
import { ThemeEnum } from '@/constants/common';
import React, { createContext, useContext, useEffect, useState } from 'react';
import React, {
createContext,
useCallback,
useContext,
useEffect,
useRef,
useState,
} from 'react';
type ThemeProviderProps = {
children: React.ReactNode;
@@ -9,7 +16,7 @@ type ThemeProviderProps = {
type ThemeProviderState = {
theme: ThemeEnum;
setTheme: (theme: ThemeEnum) => void;
setTheme: (theme: ThemeEnum, persist?: boolean) => void;
};
const initialState: ThemeProviderState = {
@@ -25,14 +32,22 @@ export function ThemeProvider({
storageKey = 'vite-ui-theme',
...props
}: ThemeProviderProps) {
const [theme, setTheme] = useState<ThemeEnum>(
const [theme, setThemeState] = useState<ThemeEnum>(
() => (localStorage.getItem(storageKey) as ThemeEnum) || defaultTheme,
);
const persistRef = useRef(true);
const setTheme = useCallback((nextTheme: ThemeEnum, persist = true) => {
persistRef.current = persist;
setThemeState(nextTheme);
}, []);
useEffect(() => {
const root = window.document.documentElement;
root.classList.remove(ThemeEnum.Light, ThemeEnum.Dark);
localStorage.setItem(storageKey, theme);
if (persistRef.current) {
localStorage.setItem(storageKey, theme);
}
root.classList.add(theme);
}, [storageKey, theme]);
@@ -73,11 +88,23 @@ export function useSwitchToDarkThemeOnMount() {
}
export function useSyncThemeFromParams(theme: string | null) {
const { setTheme } = useTheme();
const { theme: contextTheme, setTheme } = useTheme();
const originalThemeRef = useRef<ThemeEnum | null>(null);
useEffect(() => {
if (theme && (theme === ThemeEnum.Light || theme === ThemeEnum.Dark)) {
setTheme(theme as ThemeEnum);
if (originalThemeRef.current === null) {
originalThemeRef.current = contextTheme;
}
setTheme(theme as ThemeEnum, false);
}
}, [theme, setTheme]);
}, [theme, contextTheme, setTheme]);
useEffect(() => {
return () => {
if (originalThemeRef.current !== null) {
setTheme(originalThemeRef.current, false);
}
};
}, [setTheme]);
}