From 7848d6b1de005d2f394528187509c6a6b39026dc Mon Sep 17 00:00:00 2001 From: Tunglies Date: Thu, 18 Sep 2025 10:22:43 +0800 Subject: [PATCH] refactor: window handle usage (#4788) * refactor: Remove unused UI reset function and streamline window creation logic * refactor: Remove debug print statements and streamline lightweight mode initialization * fix: Ensure tray status refresh during silent startup and lightweight mode entry is independent of window creation * refactor: Simplify window creation process and remove debug print statements --- UPDATELOG.md | 2 + src-tauri/src/cmd/app.rs | 8 - src-tauri/src/lib.rs | 1 - src-tauri/src/module/lightweight.rs | 7 - src-tauri/src/utils/resolve/mod.rs | 17 +- src-tauri/src/utils/resolve/scheme.rs | 1 - src-tauri/src/utils/resolve/ui.rs | 33 ---- src-tauri/src/utils/resolve/window.rs | 266 +------------------------- src-tauri/src/utils/window_manager.rs | 46 ++++- 9 files changed, 66 insertions(+), 315 deletions(-) diff --git a/UPDATELOG.md b/UPDATELOG.md index 818eda2ed..159e8b639 100644 --- a/UPDATELOG.md +++ b/UPDATELOG.md @@ -3,12 +3,14 @@ ### 🚀 性能优化 - 重构并简化服务模式启动检测流程,消除重复检测 +- 重构并简化窗口创建流程 ### 🐞 修复问题 - 优化服务模式重装逻辑,避免不必要的重复检查 - 修复轻量模式退出无响应的问题 - 修复托盘轻量模式支持退出/进入 +- 修复静默启动和自动进入轻量模式时,托盘状态刷新不再依赖窗口创建流程 - macOS Tun/系统代理 模式下图标大小不统一 - 托盘节点切换不再显示隐藏组 diff --git a/src-tauri/src/cmd/app.rs b/src-tauri/src/cmd/app.rs index 44b2cecf1..68de9ec5f 100644 --- a/src-tauri/src/cmd/app.rs +++ b/src-tauri/src/cmd/app.rs @@ -235,11 +235,3 @@ pub fn update_ui_stage(stage: String) -> CmdResult<()> { crate::utils::resolve::ui::update_ui_ready_stage(stage_enum); Ok(()) } - -/// 重置UI就绪状态 -#[tauri::command] -pub fn reset_ui_ready_state() -> CmdResult<()> { - log::info!(target: "app", "重置UI就绪状态"); - crate::utils::resolve::ui::reset_ui_ready(); - Ok(()) -} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 13590e1b4..4889da7e0 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -155,7 +155,6 @@ mod app_init { // Application lifecycle cmd::notify_ui_ready, cmd::update_ui_stage, - cmd::reset_ui_ready_state, cmd::get_running_mode, cmd::get_app_uptime, cmd::get_auto_launch_status, diff --git a/src-tauri/src/module/lightweight.rs b/src-tauri/src/module/lightweight.rs index 8eefe6fe0..ba42963b5 100644 --- a/src-tauri/src/module/lightweight.rs +++ b/src-tauri/src/module/lightweight.rs @@ -107,13 +107,6 @@ pub async fn run_once_auto_lightweight() { return; } - logging!( - info, - Type::Lightweight, - true, - "在静默启动的情况下,创建窗口再添加自动进入轻量模式窗口监听器" - ); - set_lightweight_mode(true).await; enable_auto_light_weight_mode().await; } diff --git a/src-tauri/src/utils/resolve/mod.rs b/src-tauri/src/utils/resolve/mod.rs index 6118b934e..0b6770bc5 100644 --- a/src-tauri/src/utils/resolve/mod.rs +++ b/src-tauri/src/utils/resolve/mod.rs @@ -7,9 +7,9 @@ use crate::{ CoreManager, Timer, handle, hotkey::Hotkey, service::SERVICE_MANAGER, sysopt, tray::Tray, }, logging, logging_error, - module::lightweight::auto_lightweight_mode_init, + module::lightweight::{auto_lightweight_mode_init, run_once_auto_lightweight}, process::AsyncHandler, - utils::{init, logging::Type, resolve::window::create_window, server}, + utils::{init, logging::Type, server, window_manager::WindowManager}, }; pub mod dns; @@ -50,6 +50,7 @@ pub fn resolve_setup_async() { ); init_timer().await; + init_once_auto_lightweight().await; init_auto_lightweight_mode().await; init_verge_config().await; @@ -154,6 +155,16 @@ pub(super) async fn init_hotkey() { logging_error!(Type::Setup, true, Hotkey::global().init().await); } +pub(super) async fn init_once_auto_lightweight() { + logging!( + info, + Type::Lightweight, + true, + "Running auto lightweight mode check..." + ); + run_once_auto_lightweight().await; +} + pub(super) async fn init_auto_lightweight_mode() { logging!( info, @@ -242,5 +253,5 @@ pub(super) async fn init_window() { Handle::global().set_activation_policy_accessory(); } } - create_window(!is_silent_start).await; + WindowManager::create_window(!is_silent_start).await; } diff --git a/src-tauri/src/utils/resolve/scheme.rs b/src-tauri/src/utils/resolve/scheme.rs index 57e0c0015..99e6588ea 100644 --- a/src-tauri/src/utils/resolve/scheme.rs +++ b/src-tauri/src/utils/resolve/scheme.rs @@ -44,7 +44,6 @@ pub(super) async fn resolve_scheme(param: String) -> Result<()> { match url_param { Some(url) => { log::info!(target:"app", "decoded subscription url: {url}"); - // create_window(false).await; match PrfItem::from_url(url.as_ref(), name, None, None).await { Ok(item) => { let uid = match item.uid.clone() { diff --git a/src-tauri/src/utils/resolve/ui.rs b/src-tauri/src/utils/resolve/ui.rs index 727e2fe0d..009e55ab5 100644 --- a/src-tauri/src/utils/resolve/ui.rs +++ b/src-tauri/src/utils/resolve/ui.rs @@ -51,26 +51,6 @@ fn get_ui_ready_notify() -> &'static Arc { UI_READY_NOTIFY.get_or_init(|| Arc::new(Notify::new())) } -/// 等待 UI 就绪的异步函数,使用事件驱动而非轮询 -pub async fn wait_for_ui_ready(timeout_seconds: u64) -> bool { - // 首先检查是否已经就绪 - if get_ui_ready().load(Ordering::Acquire) { - return true; - } - - // 使用 tokio::select! 同时等待通知和超时 - tokio::select! { - _ = get_ui_ready_notify().notified() => { - // 收到通知后再次确认状态(防止虚假通知) - get_ui_ready().load(Ordering::Acquire) - } - _ = tokio::time::sleep(std::time::Duration::from_secs(timeout_seconds)) => { - // 超时,返回当前状态 - get_ui_ready().load(Ordering::Acquire) - } - } -} - // 更新UI准备阶段 pub fn update_ui_ready_stage(stage: UiReadyStage) { let state = get_ui_ready_state(); @@ -91,16 +71,3 @@ pub fn mark_ui_ready() { // 通知所有等待的任务 get_ui_ready_notify().notify_waiters(); } - -// 重置UI就绪状态 -pub fn reset_ui_ready() { - get_ui_ready().store(false, Ordering::Release); - { - let state = get_ui_ready_state(); - let mut stage = state.stage.write(); - *stage = UiReadyStage::NotStarted; - } - logging!(info, Type::Window, true, "UI就绪状态已重置"); - - // 注意:这里不需要通知,因为重置后状态变为 false -} diff --git a/src-tauri/src/utils/resolve/window.rs b/src-tauri/src/utils/resolve/window.rs index 0030d15ff..e99e3307f 100644 --- a/src-tauri/src/utils/resolve/window.rs +++ b/src-tauri/src/utils/resolve/window.rs @@ -1,18 +1,11 @@ -use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; -use std::time::{SystemTime, UNIX_EPOCH}; - -use tauri::{Manager, WebviewWindow}; +use tauri::WebviewWindow; use crate::{ core::handle, - logging, - module::lightweight, + logging, logging_error, utils::{ logging::Type, - resolve::{ - ui::{UiReadyStage, get_ui_ready, update_ui_ready_stage, wait_for_ui_ready}, - window_script::{INITIAL_LOADING_OVERLAY, WINDOW_INITIAL_SCRIPT}, - }, + resolve::window_script::{INITIAL_LOADING_OVERLAY, WINDOW_INITIAL_SCRIPT}, }, }; @@ -23,87 +16,8 @@ const DEFAULT_HEIGHT: f64 = 700.0; const MINIMAL_WIDTH: f64 = 520.0; const MINIMAL_HEIGHT: f64 = 520.0; -// 窗口创建状态,使用原子操作 -static WINDOW_CREATING: AtomicBool = AtomicBool::new(false); -static LAST_CREATION_TIME: AtomicU32 = AtomicU32::new(0); - -/// 获取当前时间戳(秒) -fn get_current_timestamp() -> u32 { - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap_or_default() - .as_secs() as u32 -} - -/// 检查是否已存在窗口,如果存在则显示并返回 true -fn check_existing_window(is_show: bool) -> Option { - if let Some(app_handle) = handle::Handle::global().app_handle() - && let Some(window) = app_handle.get_webview_window("main") - { - logging!(info, Type::Window, true, "主窗口已存在,将显示现有窗口"); - if is_show { - if window.is_minimized().unwrap_or(false) { - logging!(info, Type::Window, true, "窗口已最小化,正在取消最小化"); - let _ = window.unminimize(); - } - let _ = window.show(); - let _ = window.set_focus(); - - #[cfg(target_os = "macos")] - handle::Handle::global().set_activation_policy_regular(); - } - return Some(true); - } - None -} - -/// 获取窗口创建锁,防止并发创建 -fn acquire_window_creation_lock() -> Result<(), bool> { - let current_time = get_current_timestamp(); - let last_time = LAST_CREATION_TIME.load(Ordering::Acquire); - let elapsed_seconds = current_time.saturating_sub(last_time); - - // 检查是否正在创建窗口且时间间隔小于2秒 - if WINDOW_CREATING.load(Ordering::Acquire) && elapsed_seconds < 2 { - logging!( - info, - Type::Window, - true, - "窗口创建请求被忽略,因为最近创建过 ({}秒前)", - elapsed_seconds - ); - return Err(false); - } - - // 尝试获取创建锁 - match WINDOW_CREATING.compare_exchange(false, true, Ordering::AcqRel, Ordering::Acquire) { - Ok(_) => { - // 成功获取锁,更新时间戳 - LAST_CREATION_TIME.store(current_time, Ordering::Release); - Ok(()) - } - Err(_) => { - // 锁已被占用 - logging!( - info, - Type::Window, - true, - "窗口创建请求被忽略,另一个创建过程正在进行" - ); - Err(false) - } - } -} - -/// 重置窗口创建锁 -fn reset_window_creation_lock() { - WINDOW_CREATING.store(false, Ordering::Release); - LAST_CREATION_TIME.store(get_current_timestamp(), Ordering::Release); - logging!(debug, Type::Window, true, "窗口创建状态已重置"); -} - /// 构建新的 WebView 窗口 -fn build_new_window() -> Result { +pub fn build_new_window() -> Result { let app_handle = handle::Handle::global().app_handle().ok_or_else(|| { logging!( error, @@ -114,7 +28,7 @@ fn build_new_window() -> Result { "无法获取app_handle".to_string() })?; - tauri::WebviewWindowBuilder::new( + match tauri::WebviewWindowBuilder::new( &app_handle, "main", /* the unique window label */ tauri::WebviewUrl::App("index.html".into()), @@ -128,171 +42,11 @@ fn build_new_window() -> Result { .visible(true) // 立即显示窗口,避免用户等待 .initialization_script(WINDOW_INITIAL_SCRIPT) .build() - .map_err(|e| { - logging!(error, Type::Window, true, "主窗口构建失败: {}", e); - e.to_string() - }) -} - -/// 窗口创建后的初始设置 -async fn setup_window_post_creation() { - update_ui_ready_stage(UiReadyStage::NotStarted); - handle::Handle::global().mark_startup_completed(); - - logging!( - debug, - Type::Window, - true, - "异步窗口任务开始 (启动已标记完成)" - ); - - // 先运行轻量模式检测 - lightweight::run_once_auto_lightweight().await; -} - -/// 通过窗口标签处理窗口显示逻辑(减少任务大小的优化版本) -async fn handle_window_display_by_label(window_label: String, is_show: bool) { - if !is_show { - logging!( - debug, - Type::Window, - true, - "is_show为false,窗口保持隐藏状态" - ); - return; - } - - // 通过标签重新获取窗口实例 - let app_handle = match handle::Handle::global().app_handle() { - Some(handle) => handle, - None => { - logging!(error, Type::Window, true, "无法获取app handle"); - return; - } - }; - - let window = match app_handle.get_webview_window(&window_label) { - Some(window) => window, - None => { - logging!( - error, - Type::Window, - true, - "无法通过标签获取窗口: {}", - window_label - ); - return; - } - }; - - // 立即显示窗口 - let _ = window.show(); - let _ = window.set_focus(); - logging!(info, Type::Window, true, "窗口已立即显示"); - - #[cfg(target_os = "macos")] - handle::Handle::global().set_activation_policy_regular(); - - let timeout_seconds = 8; - - logging!( - info, - Type::Window, - true, - "开始监控UI加载状态 (最多{}秒)...", - timeout_seconds - ); - - // 异步监控UI状态 - monitor_ui_loading(timeout_seconds).await; - - logging!(info, Type::Window, true, "窗口显示流程完成"); -} - -/// 监控 UI 加载状态 - 优雅的事件驱动版本 -async fn monitor_ui_loading(timeout_seconds: u64) { - logging!( - debug, - Type::Window, - true, - "启动UI状态监控,使用事件驱动方式,超时{}秒", - timeout_seconds - ); - - // 使用事件驱动的方式等待 UI 就绪,完全消除轮询 - let ui_ready = wait_for_ui_ready(timeout_seconds).await; - - if ui_ready { - logging!(info, Type::Window, true, "UI已完全加载就绪(事件驱动)"); - handle::Handle::global() - .get_window() - .map(|window| window.eval(INITIAL_LOADING_OVERLAY)); - } else { - logging!( - warn, - Type::Window, - true, - "UI加载监控超时({}秒),但窗口已正常显示", - timeout_seconds - ); - - // 超时后手动设置 UI 就绪状态(保持向后兼容性) - get_ui_ready().store(true, std::sync::atomic::Ordering::Release); - logging!(info, Type::Window, true, "超时后成功设置UI就绪状态"); - } -} - -pub async fn create_window(is_show: bool) -> bool { - logging!( - info, - Type::Window, - true, - "开始创建/显示主窗口, is_show={}", - is_show - ); - - if !is_show { - return false; - } - - // 检查是否已存在窗口 - if let Some(result) = check_existing_window(is_show) { - return result; - } - - // 检查 app_handle 是否存在 - if handle::Handle::global().app_handle().is_none() { - logging!(error, Type::Window, true, "No window found in app_handle"); - return false; - } - - // 获取窗口创建锁 - if let Err(should_return) = acquire_window_creation_lock() { - return should_return; - } - - // 构建新窗口 - let newly_created_window = match build_new_window() { + { Ok(window) => { - // 窗口创建成功,重置锁状态 - reset_window_creation_lock(); - window + logging_error!(Type::Window, true, window.eval(INITIAL_LOADING_OVERLAY)); + Ok(window) } - Err(_) => { - // 窗口创建失败,重置锁状态 - reset_window_creation_lock(); - return false; - } - }; - - logging!(debug, Type::Window, true, "主窗口实例创建成功"); - - // 获取窗口标签,减少闭包捕获的大小 - let window_label = newly_created_window.label().to_string(); - - // 异步处理窗口后续设置,只捕获必要的小数据 - setup_window_post_creation().await; - handle_window_display_by_label(window_label, is_show).await; - - true + Err(e) => Err(e.to_string()), + } } diff --git a/src-tauri/src/utils/window_manager.rs b/src-tauri/src/utils/window_manager.rs index 0540f784b..d982a8e25 100644 --- a/src-tauri/src/utils/window_manager.rs +++ b/src-tauri/src/utils/window_manager.rs @@ -1,4 +1,10 @@ -use crate::{core::handle, logging, utils::logging::Type}; +use crate::{ + core::handle, + logging, + utils::{logging::Type, resolve::window::build_new_window}, +}; +use std::future::Future; +use std::pin::Pin; use tauri::{Manager, WebviewWindow, Wry}; use once_cell::sync::OnceCell; @@ -140,7 +146,7 @@ impl WindowManager { match current_state { WindowState::NotExist => { logging!(info, Type::Window, true, "窗口不存在,创建新窗口"); - if Self::create_new_window().await { + if Self::create_window(true).await { logging!(info, Type::Window, true, "窗口创建成功"); std::thread::sleep(std::time::Duration::from_millis(100)); WindowOperationResult::Created @@ -200,7 +206,7 @@ impl WindowManager { // 窗口不存在,创建新窗口 logging!(info, Type::Window, true, "窗口不存在,将创建新窗口"); // 由于已经有防抖保护,直接调用内部方法 - if Self::create_new_window().await { + if Self::create_window(true).await { WindowOperationResult::Created } else { WindowOperationResult::Failed @@ -340,10 +346,38 @@ impl WindowManager { } /// 创建新窗口,防抖避免重复调用 - async fn create_new_window() -> bool { - use crate::utils::resolve; + pub fn create_window(is_show: bool) -> Pin + Send>> { + Box::pin(async move { + logging!( + info, + Type::Window, + true, + "开始创建/显示主窗口, is_show={}", + is_show + ); - resolve::window::create_window(true).await + if !is_show { + return false; + } + + match build_new_window() { + Ok(_) => { + logging!(info, Type::Window, true, "新窗口创建成功"); + } + Err(e) => { + logging!(error, Type::Window, true, "新窗口创建失败: {}", e); + return false; + } + } + + if WindowOperationResult::Failed != Self::show_main_window().await { + return false; + } + + handle::Handle::global().mark_startup_completed(); + + true + }) } /// 摧毁窗口