diff --git a/Changelog.md b/Changelog.md index ad1e120f2..c0853940e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,7 +7,6 @@ - 修复设置代理端口时检查端口占用 - 修复 Monaco 编辑器初始化卡 Loading - 修复恢复备份时 `config.yaml` / `profiles.yaml` 文件内字段未正确恢复 -- 修复 Windows 下系统主题同步问题
✨ 新增功能 diff --git a/src-tauri/src/utils/resolve/mod.rs b/src-tauri/src/utils/resolve/mod.rs index 76dd05d07..7da555257 100644 --- a/src-tauri/src/utils/resolve/mod.rs +++ b/src-tauri/src/utils/resolve/mod.rs @@ -22,8 +22,6 @@ use clash_verge_signal; pub mod dns; pub mod scheme; -#[cfg(target_os = "windows")] -pub mod theme; pub mod ui; pub mod window; pub mod window_script; @@ -66,8 +64,6 @@ pub fn resolve_setup_async() { init_verge_config().await; Config::verify_config_initialization().await; init_window().await; - #[cfg(target_os = "windows")] - theme::start_windows_app_theme_watcher(); let core_init = AsyncHandler::spawn(|| async { init_service_manager().await; diff --git a/src-tauri/src/utils/resolve/theme.rs b/src-tauri/src/utils/resolve/theme.rs deleted file mode 100644 index 6046bb3e0..000000000 --- a/src-tauri/src/utils/resolve/theme.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! Windows app theme watcher. -//! -//! NOTE: -//! Tauri's theme API is unreliable on Windows and may miss or delay -//! system theme change events. As a workaround, we poll the system -//! theme via the `dark-light` crate and emit a custom -//! `verge://app-theme-changed` event to keep the frontend in sync. -//! -//! Windows-only, best-effort. - -use std::time::Duration; - -use dark_light::{Mode as SystemTheme, detect as detect_system_theme}; -use tauri::Emitter as _; - -use crate::{core::handle, process::AsyncHandler}; - -const APP_THEME_EVENT: &str = "verge://app-theme-changed"; - -fn resolve_apps_theme_mode() -> Option<&'static str> { - match detect_system_theme().ok()? { - SystemTheme::Dark => Some("dark"), - SystemTheme::Light => Some("light"), - SystemTheme::Unspecified => None, - } -} - -pub fn start_windows_app_theme_watcher() { - AsyncHandler::spawn(|| async move { - let app_handle = handle::Handle::app_handle().clone(); - let mut last_theme = resolve_apps_theme_mode(); - - if let Some(theme) = last_theme { - let _ = app_handle.emit(APP_THEME_EVENT, theme); - } - - loop { - if handle::Handle::global().is_exiting() { - break; - } - - tokio::time::sleep(Duration::from_millis(500)).await; - let Some(theme) = resolve_apps_theme_mode() else { - continue; - }; - - if last_theme.as_ref() == Some(&theme) { - continue; - } - - last_theme = Some(theme); - let _ = app_handle.emit(APP_THEME_EVENT, theme); - } - }); -} diff --git a/src/components/layout/use-custom-theme.ts b/src/components/layout/use-custom-theme.ts index 1376606da..d65fbce00 100644 --- a/src/components/layout/use-custom-theme.ts +++ b/src/components/layout/use-custom-theme.ts @@ -1,6 +1,4 @@ import { alpha, createTheme, Theme as MuiTheme, Shadows } from "@mui/material"; -import { isTauri as isTauriApp } from "@tauri-apps/api/core"; -import { listen } from "@tauri-apps/api/event"; import { getCurrentWebviewWindow, WebviewWindow, @@ -11,7 +9,6 @@ import { useEffect, useMemo } from "react"; import { useVerge } from "@/hooks/use-verge"; import { defaultDarkTheme, defaultTheme } from "@/pages/_theme"; import { useSetThemeMode, useThemeMode } from "@/services/states"; -import getSystem from "@/utils/get-system"; const CSS_INJECTION_SCOPE_ROOT = "[data-css-injection-root]"; const CSS_INJECTION_SCOPE_LIMIT = @@ -29,7 +26,6 @@ const TOP_LEVEL_AT_RULES = [ "@color-profile", ]; let cssScopeSupport: boolean | null = null; -const OS = getSystem(); const canUseCssScope = () => { if (cssScopeSupport !== null) { @@ -80,8 +76,6 @@ export const useCustomTheme = () => { const setMode = useSetThemeMode(); const userBackgroundImage = theme_setting?.background_image || ""; const hasUserBackground = !!userBackgroundImage; - const isTauri = typeof window !== "undefined" && isTauriApp(); - const isWindows = OS === "windows"; useEffect(() => { if (theme_mode === "light" || theme_mode === "dark") { @@ -90,7 +84,17 @@ export const useCustomTheme = () => { }, [theme_mode, setMode]); useEffect(() => { - if (theme_mode !== "system" || !isTauri || isWindows) { + if (theme_mode !== "system") { + return; + } + + const preferBrowserMatchMedia = + typeof window !== "undefined" && + typeof window.matchMedia === "function" && + // Skip Tauri flow when running purely in browser. + !("__TAURI__" in window); + + if (preferBrowserMatchMedia) { return; } @@ -129,40 +133,7 @@ export const useCustomTheme = () => { console.error("Failed to unlisten from theme changes:", err); }); }; - }, [theme_mode, appWindow, setMode, isTauri, isWindows]); - - // Windows-only: Tauri's theme API is unreliable. - // Theme changes are detected in Rust and propagated via a custom event. - useEffect(() => { - if (theme_mode !== "system" || !isTauri || !isWindows) { - return; - } - - let isMounted = true; - let unlisten: (() => void) | null = null; - - listen("verge://app-theme-changed", (event) => { - if (!isMounted) return; - if (event.payload === "dark" || event.payload === "light") { - setMode(event.payload); - } - }) - .then((unlistenFn) => { - if (typeof unlistenFn === "function") { - unlisten = unlistenFn; - } - }) - .catch((err) => { - console.error("Failed to listen to app theme changes:", err); - }); - - return () => { - isMounted = false; - if (typeof unlisten === "function") { - unlisten(); - } - }; - }, [theme_mode, setMode, isTauri, isWindows]); + }, [theme_mode, appWindow, setMode]); useEffect(() => { if (theme_mode !== "system") { @@ -176,10 +147,6 @@ export const useCustomTheme = () => { return; } - if (isTauri && isWindows) { - return; - } - const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); const syncMode = (isDark: boolean) => setMode(isDark ? "dark" : "light"); const handleChange = (event: MediaQueryListEvent) => @@ -223,7 +190,7 @@ export const useCustomTheme = () => { ).removeListener; legacyRemoveListener?.call(legacyQuery, handleChange); }; - }, [theme_mode, setMode, isTauri, isWindows]); + }, [theme_mode, setMode]); useEffect(() => { if (theme_mode === undefined) { @@ -231,16 +198,18 @@ export const useCustomTheme = () => { } if (theme_mode === "system") { - const preferredTheme = isWindows ? (mode as TauriOsTheme) : null; - appWindow.setTheme(preferredTheme).catch((err) => { - console.error("Failed to set window theme for system mode:", err); + appWindow.setTheme(null).catch((err) => { + console.error( + "Failed to set window theme to follow system (setTheme(null)):", + err, + ); }); } else if (mode) { appWindow.setTheme(mode as TauriOsTheme).catch((err) => { console.error(`Failed to set window theme to ${mode}:`, err); }); } - }, [mode, appWindow, theme_mode, isWindows]); + }, [mode, appWindow, theme_mode]); const theme = useMemo(() => { const setting = theme_setting || {};