mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-09-29 16:06:36 +08:00
fix: theme persistence and update version to 2.1.9-beta9
This commit is contained in:
@@ -85,11 +85,22 @@
|
|||||||
shortcutIconLink.removeAttribute('type');
|
shortcutIconLink.removeAttribute('type');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 立即检测系统主题并应用
|
// 立即检测主题并应用(优先读取 localStorage 中的用户偏好)
|
||||||
const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
var savedMode = '';
|
||||||
|
try { savedMode = localStorage.getItem('flvx:theme') || ''; } catch (_) {}
|
||||||
|
|
||||||
|
var useDark;
|
||||||
|
if (savedMode === 'dark') {
|
||||||
|
useDark = true;
|
||||||
|
} else if (savedMode === 'light') {
|
||||||
|
useDark = false;
|
||||||
|
} else {
|
||||||
|
// "system" 或无保存:跟随系统
|
||||||
|
useDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
|
}
|
||||||
|
|
||||||
// 立即设置主题类,避免闪烁
|
// 立即设置主题类,避免闪烁
|
||||||
if (isDarkMode) {
|
if (useDark) {
|
||||||
document.documentElement.classList.add('dark');
|
document.documentElement.classList.add('dark');
|
||||||
document.documentElement.style.colorScheme = 'dark';
|
document.documentElement.style.colorScheme = 'dark';
|
||||||
} else {
|
} else {
|
||||||
@@ -97,9 +108,13 @@
|
|||||||
document.documentElement.style.colorScheme = 'light';
|
document.documentElement.style.colorScheme = 'light';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听系统主题变化
|
// 仅在"跟随系统"模式下监听系统主题变化
|
||||||
if (window.matchMedia) {
|
if ((!savedMode || savedMode === 'system') && window.matchMedia) {
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
|
||||||
|
// 运行时可能已由 React 接管,这里仅做 fallback
|
||||||
|
var currentMode = '';
|
||||||
|
try { currentMode = localStorage.getItem('flvx:theme') || ''; } catch (_) {}
|
||||||
|
if (currentMode && currentMode !== 'system') return; // 用户已手动选择,不干预
|
||||||
if (e.matches) {
|
if (e.matches) {
|
||||||
document.documentElement.classList.add('dark');
|
document.documentElement.classList.add('dark');
|
||||||
document.documentElement.style.colorScheme = 'dark';
|
document.documentElement.style.colorScheme = 'dark';
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ import React from "react";
|
|||||||
import "@/themes/loader";
|
import "@/themes/loader";
|
||||||
|
|
||||||
import { ThemeProvider as ThemeContextProvider } from "@/themes/context";
|
import { ThemeProvider as ThemeContextProvider } from "@/themes/context";
|
||||||
|
import { initThemeSystem } from "@/themes/registry";
|
||||||
|
|
||||||
|
// Restore saved theme SYNCHRONOUSLY at module load time — before first render.
|
||||||
|
// This ensures the CSS tokens are injected before any component renders,
|
||||||
|
// preventing a flash of the default theme.
|
||||||
|
initThemeSystem();
|
||||||
|
|
||||||
interface ThemeProviderProps {
|
interface ThemeProviderProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
type AnnouncementData,
|
type AnnouncementData,
|
||||||
} from "@/api";
|
} from "@/api";
|
||||||
import { BackIcon, SettingsIcon } from "@/components/icons";
|
import { BackIcon, SettingsIcon } from "@/components/icons";
|
||||||
|
import { ThemeSettings } from "@/components/theme-settings";
|
||||||
import { isAdmin } from "@/utils/auth";
|
import { isAdmin } from "@/utils/auth";
|
||||||
import { getCachedConfigs, configCache, updateSiteConfig } from "@/config/site";
|
import { getCachedConfigs, configCache, updateSiteConfig } from "@/config/site";
|
||||||
import {
|
import {
|
||||||
@@ -979,6 +980,11 @@ export default function ConfigPage() {
|
|||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/* 主题设置 */}
|
||||||
|
<div className="mt-6">
|
||||||
|
<ThemeSettings />
|
||||||
|
</div>
|
||||||
|
|
||||||
{hasChanges && (
|
{hasChanges && (
|
||||||
<Card className="mt-4 bg-warning-50 dark:bg-warning-900/20 border-warning-200 dark:border-warning-800 shadow-sm overflow-hidden">
|
<Card className="mt-4 bg-warning-50 dark:bg-warning-900/20 border-warning-200 dark:border-warning-800 shadow-sm overflow-hidden">
|
||||||
<div className="h-10 flex items-center justify-center gap-2 text-warning-700 dark:text-warning-300">
|
<div className="h-10 flex items-center justify-center gap-2 text-warning-700 dark:text-warning-300">
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { Switch } from "@/shadcn-bridge/heroui/switch";
|
|||||||
import { reinitializeBaseURL } from "@/api/network";
|
import { reinitializeBaseURL } from "@/api/network";
|
||||||
import { getConfigByName, updateConfig } from "@/api";
|
import { getConfigByName, updateConfig } from "@/api";
|
||||||
import { BackIcon } from "@/components/icons";
|
import { BackIcon } from "@/components/icons";
|
||||||
import { ThemeSettings } from "@/components/theme-settings";
|
|
||||||
import {
|
import {
|
||||||
type UpdateReleaseChannel,
|
type UpdateReleaseChannel,
|
||||||
getUpdateReleaseChannel,
|
getUpdateReleaseChannel,
|
||||||
@@ -182,7 +181,6 @@ export const SettingsPage = () => {
|
|||||||
{/* 内容区域 */}
|
{/* 内容区域 */}
|
||||||
<div className="max-w-4xl mx-auto px-4 py-6">
|
<div className="max-w-4xl mx-auto px-4 py-6">
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<ThemeSettings />
|
|
||||||
<Card className="border border-gray-200 dark:border-gray-700">
|
<Card className="border border-gray-200 dark:border-gray-700">
|
||||||
<CardBody className="p-6">
|
<CardBody className="p-6">
|
||||||
<h2 className="text-lg font-medium text-gray-900 dark:text-white mb-4">
|
<h2 className="text-lg font-medium text-gray-900 dark:text-white mb-4">
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import {
|
|||||||
getSavedMode,
|
getSavedMode,
|
||||||
saveMode,
|
saveMode,
|
||||||
getEffectiveMode,
|
getEffectiveMode,
|
||||||
initThemeSystem,
|
|
||||||
registerTheme,
|
registerTheme,
|
||||||
unregisterTheme,
|
unregisterTheme,
|
||||||
type ThemeMode,
|
type ThemeMode,
|
||||||
@@ -95,11 +94,6 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({ children }) => {
|
|||||||
// Re-render whenever register changes
|
// Re-render whenever register changes
|
||||||
useSyncExternalStore(originalSubscribe, getSnapshot);
|
useSyncExternalStore(originalSubscribe, getSnapshot);
|
||||||
|
|
||||||
// Initialise on mount
|
|
||||||
useEffect(() => {
|
|
||||||
initThemeSystem();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Listen for system mode changes
|
// Listen for system mode changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
|
|||||||
Reference in New Issue
Block a user