mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-06 03:03:44 +08:00
fix: resolve lightweight mode recovery failure caused by white screen prevention
This commit is contained in:
parent
abe5cf1b84
commit
d05952e945
@ -222,3 +222,11 @@ pub fn notify_ui_ready() -> CmdResult<()> {
|
|||||||
crate::utils::resolve::mark_ui_ready();
|
crate::utils::resolve::mark_ui_ready();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 重置UI就绪状态
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn reset_ui_ready_state() -> CmdResult<()> {
|
||||||
|
log::info!(target: "app", "重置UI就绪状态");
|
||||||
|
crate::utils::resolve::reset_ui_ready();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -7,3 +7,9 @@ pub async fn entry_lightweight_mode() -> CmdResult {
|
|||||||
lightweight::entry_lightweight_mode();
|
lightweight::entry_lightweight_mode();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn exit_lightweight_mode() -> CmdResult {
|
||||||
|
lightweight::exit_lightweight_mode();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -206,7 +206,14 @@ impl Tray {
|
|||||||
match tray_event.as_str() {
|
match tray_event.as_str() {
|
||||||
"system_proxy" => feat::toggle_system_proxy(),
|
"system_proxy" => feat::toggle_system_proxy(),
|
||||||
"tun_mode" => feat::toggle_tun_mode(None),
|
"tun_mode" => feat::toggle_tun_mode(None),
|
||||||
"main_window" => resolve::create_window(true),
|
"main_window" => {
|
||||||
|
// 如果在轻量模式中,先退出轻量模式
|
||||||
|
if crate::module::lightweight::is_in_lightweight_mode() {
|
||||||
|
crate::module::lightweight::exit_lightweight_mode();
|
||||||
|
}
|
||||||
|
// 然后创建窗口
|
||||||
|
resolve::create_window(true)
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -680,7 +687,14 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) {
|
|||||||
println!("change mode to: {}", mode);
|
println!("change mode to: {}", mode);
|
||||||
feat::change_clash_mode(mode.into());
|
feat::change_clash_mode(mode.into());
|
||||||
}
|
}
|
||||||
"open_window" => resolve::create_window(true),
|
"open_window" => {
|
||||||
|
// 如果在轻量模式中,先退出轻量模式
|
||||||
|
if crate::module::lightweight::is_in_lightweight_mode() {
|
||||||
|
crate::module::lightweight::exit_lightweight_mode();
|
||||||
|
}
|
||||||
|
// 然后创建窗口
|
||||||
|
resolve::create_window(true)
|
||||||
|
}
|
||||||
"system_proxy" => feat::toggle_system_proxy(),
|
"system_proxy" => feat::toggle_system_proxy(),
|
||||||
"tun_mode" => feat::toggle_tun_mode(None),
|
"tun_mode" => feat::toggle_tun_mode(None),
|
||||||
"copy_env" => feat::copy_clash_env(),
|
"copy_env" => feat::copy_clash_env(),
|
||||||
|
@ -160,10 +160,14 @@ pub fn run() {
|
|||||||
cmd::restart_app,
|
cmd::restart_app,
|
||||||
// 添加新的命令
|
// 添加新的命令
|
||||||
cmd::notify_ui_ready,
|
cmd::notify_ui_ready,
|
||||||
|
cmd::reset_ui_ready_state,
|
||||||
cmd::get_running_mode,
|
cmd::get_running_mode,
|
||||||
cmd::get_app_uptime,
|
cmd::get_app_uptime,
|
||||||
cmd::get_auto_launch_status,
|
cmd::get_auto_launch_status,
|
||||||
cmd::is_admin,
|
cmd::is_admin,
|
||||||
|
// 添加轻量模式相关命令
|
||||||
|
cmd::entry_lightweight_mode,
|
||||||
|
cmd::exit_lightweight_mode,
|
||||||
// service 管理
|
// service 管理
|
||||||
cmd::install_service,
|
cmd::install_service,
|
||||||
cmd::uninstall_service,
|
cmd::uninstall_service,
|
||||||
|
@ -9,12 +9,33 @@ use crate::{
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use delay_timer::prelude::TaskBuilder;
|
use delay_timer::prelude::TaskBuilder;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
use std::sync::Arc;
|
||||||
use tauri::{Listener, Manager};
|
use tauri::{Listener, Manager};
|
||||||
|
|
||||||
pub static AUTO_LIGHT_WEIGHT_MODE_INIT: OnceCell<()> = OnceCell::new();
|
pub static AUTO_LIGHT_WEIGHT_MODE_INIT: OnceCell<()> = OnceCell::new();
|
||||||
|
|
||||||
const LIGHT_WEIGHT_TASK_UID: &str = "light_weight_task";
|
const LIGHT_WEIGHT_TASK_UID: &str = "light_weight_task";
|
||||||
|
|
||||||
|
// 轻量模式状态标志
|
||||||
|
static IS_LIGHTWEIGHT_MODE: OnceCell<Arc<RwLock<bool>>> = OnceCell::new();
|
||||||
|
|
||||||
|
fn get_lightweight_mode() -> &'static Arc<RwLock<bool>> {
|
||||||
|
IS_LIGHTWEIGHT_MODE.get_or_init(|| Arc::new(RwLock::new(false)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否处于轻量模式
|
||||||
|
pub fn is_in_lightweight_mode() -> bool {
|
||||||
|
*get_lightweight_mode().read()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置轻量模式状态
|
||||||
|
fn set_lightweight_mode(value: bool) {
|
||||||
|
let mut mode = get_lightweight_mode().write();
|
||||||
|
*mode = value;
|
||||||
|
logging!(info, Type::Lightweight, true, "轻量模式状态: {}", value);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn enable_auto_light_weight_mode() {
|
pub fn enable_auto_light_weight_mode() {
|
||||||
Timer::global().init().unwrap();
|
Timer::global().init().unwrap();
|
||||||
logging!(info, Type::Lightweight, true, "开启自动轻量模式");
|
logging!(info, Type::Lightweight, true, "开启自动轻量模式");
|
||||||
@ -40,9 +61,21 @@ pub fn entry_lightweight_mode() {
|
|||||||
AppHandleManager::global().set_activation_policy_accessory();
|
AppHandleManager::global().set_activation_policy_accessory();
|
||||||
logging!(info, Type::Lightweight, true, "轻量模式已开启");
|
logging!(info, Type::Lightweight, true, "轻量模式已开启");
|
||||||
}
|
}
|
||||||
|
// 标记已进入轻量模式
|
||||||
|
set_lightweight_mode(true);
|
||||||
let _ = cancel_light_weight_timer();
|
let _ = cancel_light_weight_timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从轻量模式恢复
|
||||||
|
pub fn exit_lightweight_mode() {
|
||||||
|
// 标记退出轻量模式
|
||||||
|
set_lightweight_mode(false);
|
||||||
|
logging!(info, Type::Lightweight, true, "正在退出轻量模式");
|
||||||
|
|
||||||
|
// 重置UI就绪状态
|
||||||
|
crate::utils::resolve::reset_ui_ready();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_light_weight_timer() {
|
pub fn add_light_weight_timer() {
|
||||||
logging_error!(Type::Lightweight, setup_light_weight_timer());
|
logging_error!(Type::Lightweight, setup_light_weight_timer());
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use percent_encoding::percent_decode_str;
|
|||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
use std::{net::TcpListener, sync::Arc};
|
use std::{net::TcpListener, sync::Arc};
|
||||||
use tauri::{App, Manager};
|
use tauri::{App, Emitter, Manager};
|
||||||
|
|
||||||
use tauri::Url;
|
use tauri::Url;
|
||||||
//#[cfg(not(target_os = "linux"))]
|
//#[cfg(not(target_os = "linux"))]
|
||||||
@ -41,6 +41,13 @@ pub fn mark_ui_ready() {
|
|||||||
*ready = true;
|
*ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重置UI就绪状态
|
||||||
|
pub fn reset_ui_ready() {
|
||||||
|
let mut ready = get_ui_ready().write();
|
||||||
|
*ready = false;
|
||||||
|
logging!(info, Type::Window, true, "UI就绪状态已重置");
|
||||||
|
}
|
||||||
|
|
||||||
pub fn find_unused_port() -> Result<u16> {
|
pub fn find_unused_port() -> Result<u16> {
|
||||||
match TcpListener::bind("127.0.0.1:0") {
|
match TcpListener::bind("127.0.0.1:0") {
|
||||||
Ok(listener) => {
|
Ok(listener) => {
|
||||||
@ -219,27 +226,31 @@ pub fn create_window(is_showup: bool) {
|
|||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
AppHandleManager::global().set_activation_policy_regular();
|
AppHandleManager::global().set_activation_policy_regular();
|
||||||
|
|
||||||
|
// 检查是否从轻量模式恢复
|
||||||
|
let from_lightweight = crate::module::lightweight::is_in_lightweight_mode();
|
||||||
|
if from_lightweight {
|
||||||
|
logging!(info, Type::Window, true, "从轻量模式恢复窗口");
|
||||||
|
crate::module::lightweight::exit_lightweight_mode();
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(window) = handle::Handle::global().get_window() {
|
if let Some(window) = handle::Handle::global().get_window() {
|
||||||
logging!(
|
logging!(info, Type::Window, true, "Found existing window");
|
||||||
info,
|
|
||||||
Type::Window,
|
|
||||||
true,
|
|
||||||
"Found existing window, attempting to restore visibility"
|
|
||||||
);
|
|
||||||
|
|
||||||
if window.is_minimized().unwrap_or(false) {
|
if window.is_minimized().unwrap_or(false) {
|
||||||
logging!(
|
|
||||||
info,
|
|
||||||
Type::Window,
|
|
||||||
true,
|
|
||||||
"Window is minimized, restoring window state"
|
|
||||||
);
|
|
||||||
let _ = window.unminimize();
|
let _ = window.unminimize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if from_lightweight {
|
||||||
|
// 从轻量模式恢复需要销毁旧窗口以重建
|
||||||
|
logging!(info, Type::Window, true, "销毁旧窗口以重建新窗口");
|
||||||
|
let _ = window.close();
|
||||||
|
} else {
|
||||||
|
// 普通情况直接显示窗口
|
||||||
let _ = window.show();
|
let _ = window.show();
|
||||||
let _ = window.set_focus();
|
let _ = window.set_focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 定义默认窗口大小
|
// 定义默认窗口大小
|
||||||
const DEFAULT_WIDTH: u32 = 900;
|
const DEFAULT_WIDTH: u32 = 900;
|
||||||
@ -346,60 +357,37 @@ pub fn create_window(is_showup: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建异步任务处理UI就绪和显示窗口
|
||||||
|
let was_from_lightweight = from_lightweight;
|
||||||
AsyncHandler::spawn(move || async move {
|
AsyncHandler::spawn(move || async move {
|
||||||
use tauri::Emitter;
|
// 处理启动完成
|
||||||
|
|
||||||
logging!(info, Type::Window, true, "UI gets ready.");
|
|
||||||
handle::Handle::global().mark_startup_completed();
|
handle::Handle::global().mark_startup_completed();
|
||||||
|
|
||||||
if let Some(window) = app_handle_clone.get_webview_window("main") {
|
if let Some(window) = app_handle_clone.get_webview_window("main") {
|
||||||
// 检查窗口大小
|
|
||||||
match window.inner_size() {
|
|
||||||
Ok(size) => {
|
|
||||||
let width = size.width;
|
|
||||||
let height = size.height;
|
|
||||||
|
|
||||||
let state_width = STATE_WIDTH.get().copied().unwrap_or(DEFAULT_WIDTH);
|
|
||||||
let state_height =
|
|
||||||
STATE_HEIGHT.get().copied().unwrap_or(DEFAULT_HEIGHT);
|
|
||||||
|
|
||||||
logging!(
|
|
||||||
info,
|
|
||||||
Type::Window,
|
|
||||||
true,
|
|
||||||
"异步任务中窗口尺寸: {}x{}, 状态文件尺寸: {}x{}",
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
state_width,
|
|
||||||
state_height
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
logging!(
|
|
||||||
error,
|
|
||||||
Type::Window,
|
|
||||||
true,
|
|
||||||
"Failed to get window size: {:?}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送启动完成事件
|
// 发送启动完成事件
|
||||||
let _ = window.emit("verge://startup-completed", ());
|
let _ = window.emit("verge://startup-completed", ());
|
||||||
|
|
||||||
if is_showup {
|
if is_showup {
|
||||||
// 启动一个任务等待UI准备就绪再显示窗口
|
|
||||||
let window_clone = window.clone();
|
let window_clone = window.clone();
|
||||||
AsyncHandler::spawn(move || async move {
|
|
||||||
|
// 从轻量模式恢复时使用较短的超时,避免卡死
|
||||||
|
let timeout_seconds = if was_from_lightweight {
|
||||||
|
// 从轻量模式恢复只等待2秒,确保不会卡死
|
||||||
|
2
|
||||||
|
} else {
|
||||||
|
5
|
||||||
|
};
|
||||||
|
|
||||||
|
// 等待UI就绪
|
||||||
async fn wait_for_ui_ready() {
|
async fn wait_for_ui_ready() {
|
||||||
while !*get_ui_ready().read() {
|
while !*get_ui_ready().read() {
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 使用超时机制等待UI就绪
|
||||||
match tokio::time::timeout(
|
match tokio::time::timeout(
|
||||||
std::time::Duration::from_secs(5),
|
std::time::Duration::from_secs(timeout_seconds),
|
||||||
wait_for_ui_ready(),
|
wait_for_ui_ready(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -412,17 +400,22 @@ pub fn create_window(is_showup: bool) {
|
|||||||
warn,
|
warn,
|
||||||
Type::Window,
|
Type::Window,
|
||||||
true,
|
true,
|
||||||
"等待UI准备就绪超时,强制显示窗口"
|
"等待UI准备就绪超时({}秒),强制显示窗口",
|
||||||
|
timeout_seconds
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 无论是否超时,都显示窗口
|
||||||
let _ = window_clone.show();
|
let _ = window_clone.show();
|
||||||
let _ = window_clone.set_focus();
|
let _ = window_clone.set_focus();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
logging!(error, Type::Window, true, "无法获取主窗口");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
logging!(info, Type::Window, true, "异步任务已创建");
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
logging!(
|
logging!(
|
||||||
|
@ -214,6 +214,8 @@ const Layout = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const notifyUiReady = async () => {
|
const notifyUiReady = async () => {
|
||||||
try {
|
try {
|
||||||
|
await invoke("reset_ui_ready_state");
|
||||||
|
console.log("已重置UI就绪状态");
|
||||||
await new Promise(resolve => setTimeout(resolve, 200));
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
await invoke("notify_ui_ready");
|
await invoke("notify_ui_ready");
|
||||||
console.log("已通知后端UI准备就绪");
|
console.log("已通知后端UI准备就绪");
|
||||||
@ -224,12 +226,19 @@ const Layout = () => {
|
|||||||
|
|
||||||
// 监听后端发送的启动完成事件
|
// 监听后端发送的启动完成事件
|
||||||
const listenStartupCompleted = async () => {
|
const listenStartupCompleted = async () => {
|
||||||
|
try {
|
||||||
const unlisten = await listen("verge://startup-completed", () => {
|
const unlisten = await listen("verge://startup-completed", () => {
|
||||||
console.log("收到启动完成事件");
|
console.log("收到启动完成事件,开始通知UI就绪");
|
||||||
|
notifyUiReady();
|
||||||
});
|
});
|
||||||
return unlisten;
|
return unlisten;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("监听启动完成事件失败:", err);
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log("页面初始加载,通知UI就绪");
|
||||||
notifyUiReady();
|
notifyUiReady();
|
||||||
const unlistenPromise = listenStartupCompleted();
|
const unlistenPromise = listenStartupCompleted();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user