2025-09-13 15:36:43 +08:00
|
|
|
|
import { useState, useEffect } from "react";
|
2025-09-08 15:38:06 +08:00
|
|
|
|
|
|
|
|
|
|
export function useDarkMode() {
|
|
|
|
|
|
// 初始设为 false,挂载后在 useEffect 中加载真实值
|
|
|
|
|
|
const [isDarkMode, setIsDarkMode] = useState<boolean>(false);
|
|
|
|
|
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
|
|
|
|
|
|
|
|
|
|
// 组件挂载后加载初始值(兼容 Tauri 环境)
|
|
|
|
|
|
useEffect(() => {
|
2025-09-13 15:36:43 +08:00
|
|
|
|
if (typeof window === "undefined") return;
|
|
|
|
|
|
|
2025-09-08 15:38:06 +08:00
|
|
|
|
try {
|
|
|
|
|
|
// 尝试读取已保存的偏好
|
2025-09-13 15:36:43 +08:00
|
|
|
|
const saved = localStorage.getItem("darkMode");
|
2025-09-08 15:38:06 +08:00
|
|
|
|
if (saved !== null) {
|
2025-09-13 15:36:43 +08:00
|
|
|
|
const savedBool = saved === "true";
|
2025-09-08 15:38:06 +08:00
|
|
|
|
setIsDarkMode(savedBool);
|
2025-09-13 15:36:43 +08:00
|
|
|
|
console.log("[DarkMode] Loaded from localStorage:", savedBool);
|
2025-09-08 15:38:06 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 回退到系统偏好
|
2025-09-13 15:36:43 +08:00
|
|
|
|
const prefersDark =
|
|
|
|
|
|
window.matchMedia &&
|
|
|
|
|
|
window.matchMedia("(prefers-color-scheme: dark)").matches;
|
2025-09-08 15:38:06 +08:00
|
|
|
|
setIsDarkMode(prefersDark);
|
2025-09-13 15:36:43 +08:00
|
|
|
|
console.log("[DarkMode] Using system preference:", prefersDark);
|
2025-09-08 15:38:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2025-09-13 15:36:43 +08:00
|
|
|
|
console.error("[DarkMode] Error loading preference:", error);
|
2025-09-08 15:38:06 +08:00
|
|
|
|
setIsDarkMode(false);
|
|
|
|
|
|
}
|
2025-09-13 15:36:43 +08:00
|
|
|
|
|
2025-09-08 15:38:06 +08:00
|
|
|
|
setIsInitialized(true);
|
|
|
|
|
|
}, []); // 仅在首次挂载时运行
|
|
|
|
|
|
|
|
|
|
|
|
// 将 dark 类应用到文档根节点
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (!isInitialized) return;
|
2025-09-13 15:36:43 +08:00
|
|
|
|
|
2025-09-08 15:38:06 +08:00
|
|
|
|
// 添加短暂延迟以确保 Tauri 中 DOM 已就绪
|
|
|
|
|
|
const timer = setTimeout(() => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (isDarkMode) {
|
2025-09-13 15:36:43 +08:00
|
|
|
|
document.documentElement.classList.add("dark");
|
|
|
|
|
|
console.log("[DarkMode] Added dark class to document");
|
2025-09-08 15:38:06 +08:00
|
|
|
|
} else {
|
2025-09-13 15:36:43 +08:00
|
|
|
|
document.documentElement.classList.remove("dark");
|
|
|
|
|
|
console.log("[DarkMode] Removed dark class from document");
|
2025-09-08 15:38:06 +08:00
|
|
|
|
}
|
2025-09-13 15:36:43 +08:00
|
|
|
|
|
2025-09-08 15:38:06 +08:00
|
|
|
|
// 检查类名是否已成功应用
|
2025-09-13 15:36:43 +08:00
|
|
|
|
const hasClass = document.documentElement.classList.contains("dark");
|
|
|
|
|
|
console.log("[DarkMode] Document has dark class:", hasClass);
|
2025-09-08 15:38:06 +08:00
|
|
|
|
} catch (error) {
|
2025-09-13 15:36:43 +08:00
|
|
|
|
console.error("[DarkMode] Error applying dark class:", error);
|
2025-09-08 15:38:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
|
|
|
|
return () => clearTimeout(timer);
|
|
|
|
|
|
}, [isDarkMode, isInitialized]);
|
|
|
|
|
|
|
|
|
|
|
|
// 将偏好保存到 localStorage
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
if (!isInitialized) return;
|
2025-09-13 15:36:43 +08:00
|
|
|
|
|
2025-09-08 15:38:06 +08:00
|
|
|
|
try {
|
2025-09-13 15:36:43 +08:00
|
|
|
|
localStorage.setItem("darkMode", isDarkMode.toString());
|
|
|
|
|
|
console.log("[DarkMode] Saved to localStorage:", isDarkMode);
|
2025-09-08 15:38:06 +08:00
|
|
|
|
} catch (error) {
|
2025-09-13 15:36:43 +08:00
|
|
|
|
console.error("[DarkMode] Error saving preference:", error);
|
2025-09-08 15:38:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}, [isDarkMode, isInitialized]);
|
|
|
|
|
|
|
|
|
|
|
|
const toggleDarkMode = () => {
|
2025-09-13 15:36:43 +08:00
|
|
|
|
setIsDarkMode((prev) => {
|
2025-09-08 15:38:06 +08:00
|
|
|
|
const newValue = !prev;
|
2025-09-13 15:36:43 +08:00
|
|
|
|
console.log("[DarkMode] Toggling from", prev, "to", newValue);
|
2025-09-08 15:38:06 +08:00
|
|
|
|
return newValue;
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return { isDarkMode, toggleDarkMode };
|
|
|
|
|
|
}
|