diff --git a/src-tauri/src/utils/resolve/window.rs b/src-tauri/src/utils/resolve/window.rs index 5e009bd46..1fa2a43f1 100644 --- a/src-tauri/src/utils/resolve/window.rs +++ b/src-tauri/src/utils/resolve/window.rs @@ -2,11 +2,7 @@ use dark_light::{Mode as SystemTheme, detect as detect_system_theme}; use tauri::utils::config::Color; use tauri::{Theme, WebviewWindow}; -use crate::{ - config::Config, - core::handle, - utils::resolve::window_script::{INITIAL_LOADING_OVERLAY, build_window_initial_script}, -}; +use crate::{config::Config, core::handle, utils::resolve::window_script::build_window_initial_script}; use clash_verge_logging::{Type, logging_error}; const DARK_BACKGROUND_COLOR: Color = Color(46, 48, 61, 255); // #2E303D @@ -82,7 +78,6 @@ pub async fn build_new_window() -> Result { match builder.build() { Ok(window) => { logging_error!(Type::Window, window.set_background_color(Some(background_color))); - logging_error!(Type::Window, window.eval(INITIAL_LOADING_OVERLAY)); Ok(window) } Err(e) => Err(e.to_string()), diff --git a/src-tauri/src/utils/resolve/window_script.rs b/src-tauri/src/utils/resolve/window_script.rs index c8bd8ba00..9d6bf5c98 100644 --- a/src-tauri/src/utils/resolve/window_script.rs +++ b/src-tauri/src/utils/resolve/window_script.rs @@ -91,11 +91,3 @@ pub const WINDOW_INITIAL_SCRIPT: &str = r##" console.log('[Tauri] 窗口初始化脚本执行完成'); "##; - -pub const INITIAL_LOADING_OVERLAY: &str = r" - const overlay = document.getElementById('initial-loading-overlay'); - if (overlay) { - overlay.style.opacity = '0'; - setTimeout(() => overlay.remove(), 300); - } -"; diff --git a/src-tauri/src/utils/window_manager.rs b/src-tauri/src/utils/window_manager.rs index 83b970e42..7b4e5fa77 100644 --- a/src-tauri/src/utils/window_manager.rs +++ b/src-tauri/src/utils/window_manager.rs @@ -285,6 +285,7 @@ impl WindowManager { } /// 创建新窗口,防抖避免重复调用 + /// 窗口创建后保持隐藏,由前端 index.html 在 overlay 渲染后调用 show,避免主题闪烁 pub fn create_window(is_show: bool) -> Pin + Send>> { Box::pin(async move { logging!(info, Type::Window, "开始创建/显示主窗口, is_show={}", is_show); @@ -293,23 +294,22 @@ impl WindowManager { return false; } - let window = match build_new_window().await { - Ok(window) => { - logging!(info, Type::Window, "新窗口创建成功"); - window + match build_new_window().await { + Ok(_) => { + logging!(info, Type::Window, "新窗口创建成功,等待前端渲染后显示"); + + #[cfg(target_os = "macos")] + { + handle::Handle::global().set_activation_policy_regular(); + } + + true } Err(e) => { logging!(error, Type::Window, "新窗口创建失败: {}", e); - return false; + false } - }; - - // 直接激活刚创建的窗口,避免因防抖导致首次显示被跳过 - if WindowOperationResult::Failed == Self::activate_window(&window) { - return false; } - - true }) } diff --git a/src/index.html b/src/index.html index 25dddf465..2a7238e06 100644 --- a/src/index.html +++ b/src/index.html @@ -11,27 +11,15 @@ Clash Verge -
-
-
- Loading Clash Verge... -
-
+
+
diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx index b20f0ad67..2021fcbbf 100644 --- a/src/pages/_layout.tsx +++ b/src/pages/_layout.tsx @@ -44,7 +44,6 @@ import { useThemeMode } from '@/services/states' import getSystem from '@/utils/get-system' import { - useAppInitialization, useCustomTheme, useLayoutEvents, useLoadingOverlay, @@ -217,7 +216,6 @@ const Layout = () => { ) useLoadingOverlay(themeReady) - useAppInitialization() const handleNotice = useCallback( (payload: [string, string]) => { diff --git a/src/pages/_layout/hooks/index.ts b/src/pages/_layout/hooks/index.ts index 08d85b86b..41182136a 100644 --- a/src/pages/_layout/hooks/index.ts +++ b/src/pages/_layout/hooks/index.ts @@ -1,4 +1,3 @@ -export { useAppInitialization } from './use-app-initialization' export { useLayoutEvents } from './use-layout-events' export { useLoadingOverlay } from './use-loading-overlay' export { useNavMenuOrder } from './use-nav-menu-order' diff --git a/src/pages/_layout/hooks/use-app-initialization.ts b/src/pages/_layout/hooks/use-app-initialization.ts deleted file mode 100644 index 14bdfb469..000000000 --- a/src/pages/_layout/hooks/use-app-initialization.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { useEffect, useRef } from 'react' - -import { hideInitialOverlay } from '../utils' - -export const useAppInitialization = () => { - const initRef = useRef(false) - - useEffect(() => { - if (initRef.current) return - initRef.current = true - - let isCancelled = false - const timers = new Set() - - const scheduleTimeout = (handler: () => void, delay: number) => { - if (isCancelled) return -1 - const id = window.setTimeout(() => { - if (!isCancelled) { - handler() - } - timers.delete(id) - }, delay) - timers.add(id) - return id - } - - const removeLoadingOverlay = () => { - hideInitialOverlay({ schedule: scheduleTimeout }) - } - - const performInitialization = () => { - if (isCancelled) return - removeLoadingOverlay() - } - - scheduleTimeout(performInitialization, 100) - scheduleTimeout(performInitialization, 5000) - - return () => { - isCancelled = true - timers.forEach((id) => { - try { - window.clearTimeout(id) - } catch (error) { - console.warn('[Initialization] Failed to clear timer:', error) - } - }) - timers.clear() - } - }, []) -} diff --git a/src/pages/_layout/hooks/use-loading-overlay.ts b/src/pages/_layout/hooks/use-loading-overlay.ts index 946c0f5a7..16af897bc 100644 --- a/src/pages/_layout/hooks/use-loading-overlay.ts +++ b/src/pages/_layout/hooks/use-loading-overlay.ts @@ -3,46 +3,15 @@ import { useEffect, useRef } from 'react' import { hideInitialOverlay } from '../utils' export const useLoadingOverlay = (themeReady: boolean) => { - const overlayRemovedRef = useRef(false) + const doneRef = useRef(false) useEffect(() => { - if (!themeReady || overlayRemovedRef.current) return - - let removalTimer: number | undefined - let retryTimer: number | undefined - let attempts = 0 - const maxAttempts = 50 - let stopped = false - - const tryRemoveOverlay = () => { - if (stopped || overlayRemovedRef.current) return - - const { removed, removalTimer: timerId } = hideInitialOverlay({ - assumeMissingAsRemoved: true, - }) - if (typeof timerId === 'number') { - removalTimer = timerId - } - - if (removed) { - overlayRemovedRef.current = true - return - } - - if (attempts < maxAttempts) { - attempts += 1 - retryTimer = window.setTimeout(tryRemoveOverlay, 100) - } else { - console.warn('[Loading Overlay] Element not found') - } - } - - tryRemoveOverlay() + if (!themeReady || doneRef.current) return + doneRef.current = true + const timer = hideInitialOverlay() return () => { - stopped = true - if (typeof removalTimer === 'number') window.clearTimeout(removalTimer) - if (typeof retryTimer === 'number') window.clearTimeout(retryTimer) + if (timer !== undefined) window.clearTimeout(timer) } }, [themeReady]) } diff --git a/src/pages/_layout/utils/initial-loading-overlay.ts b/src/pages/_layout/utils/initial-loading-overlay.ts index cda9ca2db..08d33f6aa 100644 --- a/src/pages/_layout/utils/initial-loading-overlay.ts +++ b/src/pages/_layout/utils/initial-loading-overlay.ts @@ -1,45 +1,17 @@ -const OVERLAY_ID = 'initial-loading-overlay' -const REMOVE_DELAY = 300 +let removed = false -let overlayRemoved = false +export const hideInitialOverlay = (): number | undefined => { + if (removed) return undefined -type HideOverlayOptions = { - schedule?: (handler: () => void, delay: number) => number - assumeMissingAsRemoved?: boolean -} - -type HideOverlayResult = { - removed: boolean - removalTimer?: number -} - -export const hideInitialOverlay = ( - options: HideOverlayOptions = {}, -): HideOverlayResult => { - if (overlayRemoved) { - return { removed: true } - } - - const overlay = document.getElementById(OVERLAY_ID) + const overlay = document.getElementById('initial-loading-overlay') if (!overlay) { - if (options.assumeMissingAsRemoved) { - overlayRemoved = true - return { removed: true } - } - return { removed: false } + removed = true + return undefined } - overlayRemoved = true + removed = true overlay.dataset.hidden = 'true' - const schedule = options.schedule ?? window.setTimeout - const removalTimer = schedule(() => { - try { - overlay.remove() - } catch (error) { - console.warn('[Loading Overlay] Removal failed:', error) - } - }, REMOVE_DELAY) - - return { removed: true, removalTimer } + const timer = window.setTimeout(() => overlay.remove(), 200) + return timer }