mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-05 03:13:44 +08:00
feat: improve core functionality to prevent main process blocking, enhance MihomoManager, and optimize window creation process
This commit is contained in:
parent
d6a79316a6
commit
55cde38562
@ -37,6 +37,7 @@
|
|||||||
- 切换到规则页面时自动刷新规则数据
|
- 切换到规则页面时自动刷新规则数据
|
||||||
- 重构更新失败回退机制,使用后端完成更新失败后回退到使用 Clash 代理再次尝试更新
|
- 重构更新失败回退机制,使用后端完成更新失败后回退到使用 Clash 代理再次尝试更新
|
||||||
- 编辑非激活订阅的时候不在触发当前订阅配置重载
|
- 编辑非激活订阅的时候不在触发当前订阅配置重载
|
||||||
|
- 改进核心功能防止主进程阻塞、改进MihomoManager实现,以及优化窗口创建流程。减少应用程序可能出现的主进程卡死情况
|
||||||
|
|
||||||
## v2.2.3
|
## v2.2.3
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ use tauri::AppHandle;
|
|||||||
use tauri::Manager;
|
use tauri::Manager;
|
||||||
use tauri_plugin_autostart::MacosLauncher;
|
use tauri_plugin_autostart::MacosLauncher;
|
||||||
use tauri_plugin_deep_link::DeepLinkExt;
|
use tauri_plugin_deep_link::DeepLinkExt;
|
||||||
|
use tokio::time::{timeout, Duration};
|
||||||
use utils::logging::Type;
|
use utils::logging::Type;
|
||||||
|
|
||||||
/// A global singleton handle to the application.
|
/// A global singleton handle to the application.
|
||||||
@ -85,13 +86,22 @@ impl AppHandleManager {
|
|||||||
|
|
||||||
#[allow(clippy::panic)]
|
#[allow(clippy::panic)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
// 单例检测
|
// 单例检测 - 使用超时机制防止阻塞
|
||||||
let app_exists: bool = AsyncHandler::block_on(move || async move {
|
let app_exists: bool = AsyncHandler::block_on(move || async move {
|
||||||
if server::check_singleton().await.is_err() {
|
match timeout(Duration::from_secs(3), server::check_singleton()).await {
|
||||||
println!("app exists");
|
Ok(result) => {
|
||||||
true
|
if result.is_err() {
|
||||||
} else {
|
println!("app exists");
|
||||||
false
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// 超时处理
|
||||||
|
println!("singleton check timeout, assuming app doesn't exist");
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if app_exists {
|
if app_exists {
|
||||||
@ -139,8 +149,21 @@ pub fn run() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
AsyncHandler::block_on(move || async move {
|
// 使用 block_on 但增加超时保护
|
||||||
resolve::resolve_setup(app).await;
|
AsyncHandler::block_on(|| async {
|
||||||
|
match timeout(Duration::from_secs(30), resolve::resolve_setup(app)).await {
|
||||||
|
Ok(_) => {
|
||||||
|
logging!(info, Type::Setup, true, "App setup completed successfully");
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
logging!(
|
||||||
|
error,
|
||||||
|
Type::Setup,
|
||||||
|
true,
|
||||||
|
"App setup timed out, proceeding anyway"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,43 +1,92 @@
|
|||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use mihomo_api;
|
use mihomo_api;
|
||||||
use once_cell::sync::{Lazy, OnceCell};
|
use once_cell::sync::Lazy;
|
||||||
use std::sync::Mutex;
|
use parking_lot::{Mutex, RwLock};
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
use tauri::http::{HeaderMap, HeaderValue};
|
use tauri::http::{HeaderMap, HeaderValue};
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use tokio_tungstenite::tungstenite::http;
|
// 缓存的最大有效期(5秒)
|
||||||
|
const CACHE_TTL: Duration = Duration::from_secs(5);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq)]
|
#[derive(Debug, Clone, Default, PartialEq)]
|
||||||
pub struct Rate {
|
pub struct Rate {
|
||||||
pub up: u64,
|
pub up: u64,
|
||||||
pub down: u64,
|
pub down: u64,
|
||||||
}
|
}
|
||||||
|
// 缓存MihomoManager实例
|
||||||
|
struct MihomoCache {
|
||||||
|
manager: mihomo_api::MihomoManager,
|
||||||
|
created_at: Instant,
|
||||||
|
server: String,
|
||||||
|
}
|
||||||
|
// 使用RwLock替代Mutex,允许多个读取操作并发进行
|
||||||
pub struct MihomoManager {
|
pub struct MihomoManager {
|
||||||
mihomo: Mutex<OnceCell<mihomo_api::MihomoManager>>,
|
mihomo_cache: RwLock<Option<MihomoCache>>,
|
||||||
|
create_lock: Mutex<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MihomoManager {
|
impl MihomoManager {
|
||||||
fn __global() -> &'static MihomoManager {
|
fn __global() -> &'static MihomoManager {
|
||||||
static INSTANCE: Lazy<MihomoManager> = Lazy::new(|| MihomoManager {
|
static INSTANCE: Lazy<MihomoManager> = Lazy::new(|| MihomoManager {
|
||||||
mihomo: Mutex::new(OnceCell::new()),
|
mihomo_cache: RwLock::new(None),
|
||||||
|
create_lock: Mutex::new(()),
|
||||||
});
|
});
|
||||||
&INSTANCE
|
&INSTANCE
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global() -> mihomo_api::MihomoManager {
|
pub fn global() -> mihomo_api::MihomoManager {
|
||||||
let instance = MihomoManager::__global();
|
let instance = MihomoManager::__global();
|
||||||
let (current_server, headers) = MihomoManager::get_clash_client_info().unwrap();
|
|
||||||
|
|
||||||
let lock = instance.mihomo.lock().unwrap();
|
// 尝试从缓存读取(只需读锁)
|
||||||
if let Some(mihomo) = lock.get() {
|
{
|
||||||
if mihomo.get_mihomo_server() == current_server {
|
let cache = instance.mihomo_cache.read();
|
||||||
return mihomo.clone();
|
if let Some(cache_entry) = &*cache {
|
||||||
|
let (current_server, _) = MihomoManager::get_clash_client_info()
|
||||||
|
.unwrap_or_else(|| (String::new(), HeaderMap::new()));
|
||||||
|
|
||||||
|
// 检查缓存是否有效
|
||||||
|
if cache_entry.server == current_server
|
||||||
|
&& cache_entry.created_at.elapsed() < CACHE_TTL
|
||||||
|
{
|
||||||
|
return cache_entry.manager.clone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.set(mihomo_api::MihomoManager::new(current_server, headers))
|
// 缓存无效,获取创建锁
|
||||||
.ok();
|
let _create_guard = instance.create_lock.lock();
|
||||||
lock.get().unwrap().clone()
|
|
||||||
|
// 再次检查缓存(双重检查锁定模式)
|
||||||
|
{
|
||||||
|
let cache = instance.mihomo_cache.read();
|
||||||
|
if let Some(cache_entry) = &*cache {
|
||||||
|
let (current_server, _) = MihomoManager::get_clash_client_info()
|
||||||
|
.unwrap_or_else(|| (String::new(), HeaderMap::new()));
|
||||||
|
|
||||||
|
if cache_entry.server == current_server
|
||||||
|
&& cache_entry.created_at.elapsed() < CACHE_TTL
|
||||||
|
{
|
||||||
|
return cache_entry.manager.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建新实例
|
||||||
|
let (current_server, headers) = MihomoManager::get_clash_client_info()
|
||||||
|
.unwrap_or_else(|| (String::new(), HeaderMap::new()));
|
||||||
|
let manager = mihomo_api::MihomoManager::new(current_server.clone(), headers);
|
||||||
|
|
||||||
|
// 更新缓存
|
||||||
|
{
|
||||||
|
let mut cache = instance.mihomo_cache.write();
|
||||||
|
*cache = Some(MihomoCache {
|
||||||
|
manager: manager.clone(),
|
||||||
|
created_at: Instant::now(),
|
||||||
|
server: current_server,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
manager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,17 +103,31 @@ impl MihomoManager {
|
|||||||
|
|
||||||
Some((server, headers))
|
Some((server, headers))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提供默认值的版本,避免在connection_info为None时panic
|
||||||
|
fn get_clash_client_info_or_default() -> (String, HeaderMap) {
|
||||||
|
Self::get_clash_client_info().unwrap_or_else(|| {
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert("Content-Type", "application/json".parse().unwrap());
|
||||||
|
("http://127.0.0.1:9090".to_string(), headers)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub fn get_traffic_ws_url() -> (String, HeaderValue) {
|
pub fn get_traffic_ws_url() -> (String, HeaderValue) {
|
||||||
let (url, headers) = MihomoManager::get_clash_client_info().unwrap();
|
let (url, headers) = MihomoManager::get_clash_client_info_or_default();
|
||||||
let ws_url = url.replace("http://", "ws://") + "/traffic";
|
let ws_url = url.replace("http://", "ws://") + "/traffic";
|
||||||
let auth = headers
|
let auth = headers
|
||||||
.get("Authorization")
|
.get("Authorization")
|
||||||
.unwrap()
|
.map(|val| val.to_str().unwrap_or("").to_string())
|
||||||
.to_str()
|
.unwrap_or_default();
|
||||||
.unwrap()
|
|
||||||
.to_string();
|
// 创建默认的空HeaderValue而不是使用unwrap_or_default
|
||||||
let token = http::header::HeaderValue::from_str(&auth).unwrap();
|
let token = match HeaderValue::from_str(&auth) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => HeaderValue::from_static(""),
|
||||||
|
};
|
||||||
|
|
||||||
(ws_url, token)
|
(ws_url, token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,14 @@ use crate::{
|
|||||||
logging, logging_error,
|
logging, logging_error,
|
||||||
module::lightweight,
|
module::lightweight,
|
||||||
process::AsyncHandler,
|
process::AsyncHandler,
|
||||||
utils::{error, init, logging::Type, server},
|
utils::{dirs, error, init, logging::Type, server},
|
||||||
wrap_err,
|
wrap_err,
|
||||||
};
|
};
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
use percent_encoding::percent_decode_str;
|
use percent_encoding::percent_decode_str;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
use std::{
|
use std::{
|
||||||
@ -32,12 +33,23 @@ pub static VERSION: OnceCell<String> = OnceCell::new();
|
|||||||
static STATE_WIDTH: OnceCell<u32> = OnceCell::new();
|
static STATE_WIDTH: OnceCell<u32> = OnceCell::new();
|
||||||
static STATE_HEIGHT: OnceCell<u32> = OnceCell::new();
|
static STATE_HEIGHT: OnceCell<u32> = OnceCell::new();
|
||||||
|
|
||||||
|
// 定义默认窗口尺寸常量
|
||||||
|
const DEFAULT_WIDTH: u32 = 900;
|
||||||
|
const DEFAULT_HEIGHT: u32 = 700;
|
||||||
|
|
||||||
// 添加全局UI准备就绪标志
|
// 添加全局UI准备就绪标志
|
||||||
static UI_READY: OnceCell<Arc<RwLock<bool>>> = OnceCell::new();
|
static UI_READY: OnceCell<Arc<RwLock<bool>>> = OnceCell::new();
|
||||||
|
|
||||||
// 窗口创建锁,防止并发创建窗口
|
// 窗口创建锁,防止并发创建窗口
|
||||||
static WINDOW_CREATING: OnceCell<Mutex<(bool, Instant)>> = OnceCell::new();
|
static WINDOW_CREATING: OnceCell<Mutex<(bool, Instant)>> = OnceCell::new();
|
||||||
|
|
||||||
|
// 定义窗口状态结构体
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct WindowState {
|
||||||
|
width: Option<u32>,
|
||||||
|
height: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
fn get_window_creating_lock() -> &'static Mutex<(bool, Instant)> {
|
fn get_window_creating_lock() -> &'static Mutex<(bool, Instant)> {
|
||||||
WINDOW_CREATING.get_or_init(|| Mutex::new((false, Instant::now())))
|
WINDOW_CREATING.get_or_init(|| Mutex::new((false, Instant::now())))
|
||||||
}
|
}
|
||||||
@ -195,49 +207,47 @@ pub fn create_window(is_showup: bool) {
|
|||||||
let _guard = WindowCreateGuard;
|
let _guard = WindowCreateGuard;
|
||||||
|
|
||||||
// 打印 .window-state.json 文件路径
|
// 打印 .window-state.json 文件路径
|
||||||
if let Ok(app_dir) = crate::utils::dirs::app_home_dir() {
|
let window_state_file = dirs::app_home_dir()
|
||||||
let window_state_path = app_dir.join(".window-state.json");
|
.ok()
|
||||||
logging!(
|
.map(|dir| dir.join(".window-state.json"));
|
||||||
info,
|
logging!(
|
||||||
Type::Window,
|
info,
|
||||||
true,
|
Type::Window,
|
||||||
"窗口状态文件路径: {:?}",
|
true,
|
||||||
window_state_path
|
"窗口状态文件路径: {:?}",
|
||||||
);
|
window_state_file
|
||||||
|
);
|
||||||
|
|
||||||
// 尝试读取窗口状态文件内容
|
// 从文件加载窗口状态
|
||||||
if window_state_path.exists() {
|
if let Some(window_state_file_path) = window_state_file {
|
||||||
match std::fs::read_to_string(&window_state_path) {
|
if window_state_file_path.exists() {
|
||||||
|
match std::fs::read_to_string(&window_state_file_path) {
|
||||||
Ok(content) => {
|
Ok(content) => {
|
||||||
logging!(info, Type::Window, true, "窗口状态文件内容: {}", content);
|
logging!(
|
||||||
|
debug,
|
||||||
|
Type::Window,
|
||||||
|
true,
|
||||||
|
"读取窗口状态文件内容成功: {} 字节",
|
||||||
|
content.len()
|
||||||
|
);
|
||||||
|
|
||||||
// 解析窗口状态文件
|
match serde_json::from_str::<WindowState>(&content) {
|
||||||
match serde_json::from_str::<serde_json::Value>(&content) {
|
Ok(window_state) => {
|
||||||
Ok(state_json) => {
|
logging!(
|
||||||
if let Some(main_window) = state_json.get("main") {
|
info,
|
||||||
let width = main_window
|
Type::Window,
|
||||||
.get("width")
|
true,
|
||||||
.and_then(|v| v.as_u64())
|
"成功解析窗口状态: width={:?}, height={:?}",
|
||||||
.unwrap_or(0)
|
window_state.width,
|
||||||
as u32;
|
window_state.height
|
||||||
let height = main_window
|
);
|
||||||
.get("height")
|
|
||||||
.and_then(|v| v.as_u64())
|
|
||||||
.unwrap_or(0)
|
|
||||||
as u32;
|
|
||||||
|
|
||||||
logging!(
|
// 存储窗口状态以供后续使用
|
||||||
info,
|
if let Some(width) = window_state.width {
|
||||||
Type::Window,
|
STATE_WIDTH.set(width).ok();
|
||||||
true,
|
}
|
||||||
"窗口状态文件中的尺寸: {}x{}",
|
if let Some(height) = window_state.height {
|
||||||
width,
|
STATE_HEIGHT.set(height).ok();
|
||||||
height
|
|
||||||
);
|
|
||||||
|
|
||||||
// 保存读取到的尺寸,用于后续检查
|
|
||||||
STATE_WIDTH.get_or_init(|| width);
|
|
||||||
STATE_HEIGHT.get_or_init(|| height);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -299,56 +309,59 @@ pub fn create_window(is_showup: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义默认窗口大小
|
let width = STATE_WIDTH.get().copied().unwrap_or(DEFAULT_WIDTH);
|
||||||
const DEFAULT_WIDTH: u32 = 900;
|
let height = STATE_HEIGHT.get().copied().unwrap_or(DEFAULT_HEIGHT);
|
||||||
const DEFAULT_HEIGHT: u32 = 700;
|
|
||||||
const MIN_WIDTH: u32 = 650;
|
|
||||||
const MIN_HEIGHT: u32 = 580;
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
logging!(
|
||||||
let window = tauri::WebviewWindowBuilder::new(
|
info,
|
||||||
&app_handle,
|
Type::Window,
|
||||||
"main".to_string(),
|
true,
|
||||||
tauri::WebviewUrl::App("index.html".into()),
|
"Initializing new window with size: {}x{}",
|
||||||
)
|
width,
|
||||||
.title("Clash Verge")
|
height
|
||||||
.inner_size(DEFAULT_WIDTH as f64, DEFAULT_HEIGHT as f64)
|
);
|
||||||
.min_inner_size(MIN_WIDTH as f64, MIN_HEIGHT as f64)
|
|
||||||
.decorations(false)
|
|
||||||
.maximizable(true)
|
|
||||||
.additional_browser_args("--enable-features=msWebView2EnableDraggableRegions --disable-features=OverscrollHistoryNavigation,msExperimentalScrolling")
|
|
||||||
.transparent(true)
|
|
||||||
.shadow(true)
|
|
||||||
.visible(false) // 初始不可见,等待UI加载完成后再显示
|
|
||||||
.build();
|
|
||||||
|
|
||||||
|
// 根据不同平台创建不同配置的窗口
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
let window = tauri::WebviewWindowBuilder::new(
|
let win_builder = {
|
||||||
&app_handle,
|
// 基本配置
|
||||||
"main".to_string(),
|
let builder = tauri::WebviewWindowBuilder::new(
|
||||||
tauri::WebviewUrl::App("index.html".into()),
|
&app_handle,
|
||||||
)
|
"main",
|
||||||
.decorations(true)
|
tauri::WebviewUrl::App("index.html".into()),
|
||||||
.hidden_title(true)
|
)
|
||||||
.title_bar_style(tauri::TitleBarStyle::Overlay)
|
.title("Clash Verge")
|
||||||
.inner_size(DEFAULT_WIDTH as f64, DEFAULT_HEIGHT as f64)
|
.center()
|
||||||
.min_inner_size(MIN_WIDTH as f64, MIN_HEIGHT as f64)
|
.decorations(true)
|
||||||
.visible(false) // 初始不可见,等待UI加载完成后再显示
|
.hidden_title(true) // 隐藏标题文本
|
||||||
.build();
|
.fullscreen(false)
|
||||||
|
.inner_size(width as f64, height as f64)
|
||||||
|
.min_inner_size(520.0, 520.0)
|
||||||
|
.visible(false);
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
// 尝试设置标题栏样式
|
||||||
let window = tauri::WebviewWindowBuilder::new(
|
// 注意:根据Tauri版本不同,此API可能有变化
|
||||||
|
// 如果编译出错,请注释掉下面这行
|
||||||
|
let builder = builder.title_bar_style(tauri::TitleBarStyle::Overlay);
|
||||||
|
|
||||||
|
builder
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
let win_builder = tauri::WebviewWindowBuilder::new(
|
||||||
&app_handle,
|
&app_handle,
|
||||||
"main".to_string(),
|
"main",
|
||||||
tauri::WebviewUrl::App("index.html".into()),
|
tauri::WebviewUrl::App("index.html".into()),
|
||||||
)
|
)
|
||||||
.title("Clash Verge")
|
.title("Clash Verge")
|
||||||
.decorations(false)
|
.center()
|
||||||
.inner_size(DEFAULT_WIDTH as f64, DEFAULT_HEIGHT as f64)
|
.fullscreen(false)
|
||||||
.min_inner_size(MIN_WIDTH as f64, MIN_HEIGHT as f64)
|
.inner_size(width as f64, height as f64)
|
||||||
.transparent(true)
|
.min_inner_size(520.0, 520.0)
|
||||||
.visible(false) // 初始不可见,等待UI加载完成后再显示
|
.visible(false)
|
||||||
.build();
|
.decorations(false);
|
||||||
|
|
||||||
|
let window = win_builder.build();
|
||||||
|
|
||||||
match window {
|
match window {
|
||||||
Ok(window) => {
|
Ok(window) => {
|
||||||
@ -379,33 +392,43 @@ pub fn create_window(is_showup: bool) {
|
|||||||
DEFAULT_HEIGHT
|
DEFAULT_HEIGHT
|
||||||
);
|
);
|
||||||
|
|
||||||
if state_width < DEFAULT_WIDTH || state_height < DEFAULT_HEIGHT {
|
// 优化窗口大小设置
|
||||||
|
if size.width < state_width || size.height < state_height {
|
||||||
logging!(
|
logging!(
|
||||||
info,
|
info,
|
||||||
Type::Window,
|
Type::Window,
|
||||||
true,
|
true,
|
||||||
"状态文件窗口尺寸小于默认值,将使用默认尺寸: {}x{}",
|
"强制设置窗口尺寸: {}x{}",
|
||||||
DEFAULT_WIDTH,
|
state_width,
|
||||||
DEFAULT_HEIGHT
|
state_height
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ = window.set_size(tauri::LogicalSize::new(
|
// 尝试不同的方式设置窗口大小
|
||||||
DEFAULT_WIDTH as f64,
|
let _ = window.set_size(tauri::PhysicalSize {
|
||||||
DEFAULT_HEIGHT as f64,
|
width: state_width,
|
||||||
));
|
height: state_height,
|
||||||
} else if size.width != state_width || size.height != state_height {
|
});
|
||||||
// 如果API报告的尺寸与状态文件不一致,记录日志
|
|
||||||
logging!(
|
// 关键:等待短暂时间让窗口尺寸生效
|
||||||
warn,
|
std::thread::sleep(std::time::Duration::from_millis(50));
|
||||||
Type::Window,
|
|
||||||
true,
|
// 再次检查窗口尺寸
|
||||||
"API报告的窗口尺寸与状态文件不一致"
|
if let Ok(new_size) = window.inner_size() {
|
||||||
);
|
logging!(
|
||||||
|
info,
|
||||||
|
Type::Window,
|
||||||
|
true,
|
||||||
|
"设置后API报告的窗口尺寸: {}x{}",
|
||||||
|
new_size.width,
|
||||||
|
new_size.height
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建异步任务处理UI就绪和显示窗口
|
// 标记此窗口是否从轻量模式恢复
|
||||||
let was_from_lightweight = from_lightweight;
|
let was_from_lightweight = from_lightweight;
|
||||||
|
|
||||||
AsyncHandler::spawn(move || async move {
|
AsyncHandler::spawn(move || async move {
|
||||||
// 处理启动完成
|
// 处理启动完成
|
||||||
handle::Handle::global().mark_startup_completed();
|
handle::Handle::global().mark_startup_completed();
|
||||||
@ -425,53 +448,44 @@ pub fn create_window(is_showup: bool) {
|
|||||||
5
|
5
|
||||||
};
|
};
|
||||||
|
|
||||||
// 等待UI就绪
|
// 使用普通的等待方式替代事件监听,简化实现
|
||||||
async fn wait_for_ui_ready() {
|
let wait_result =
|
||||||
while !*get_ui_ready().read() {
|
tokio::time::timeout(Duration::from_secs(timeout_seconds), async {
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
while !*get_ui_ready().read() {
|
||||||
}
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
// 使用超时机制等待UI就绪
|
// 根据结果处理
|
||||||
match tokio::time::timeout(
|
match wait_result {
|
||||||
std::time::Duration::from_secs(timeout_seconds),
|
|
||||||
wait_for_ui_ready(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
logging!(info, Type::Window, true, "UI准备就绪,显示窗口");
|
logging!(info, Type::Window, true, "UI就绪,显示窗口");
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
logging!(
|
logging!(
|
||||||
warn,
|
warn,
|
||||||
Type::Window,
|
Type::Window,
|
||||||
true,
|
true,
|
||||||
"等待UI准备就绪超时({}秒),强制显示窗口",
|
"等待UI就绪超时({}秒),强制显示窗口",
|
||||||
timeout_seconds
|
timeout_seconds
|
||||||
);
|
);
|
||||||
|
// 强制设置UI就绪状态
|
||||||
|
*get_ui_ready().write() = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 无论是否超时,都显示窗口
|
// 显示窗口
|
||||||
let _ = window_clone.show();
|
let _ = window_clone.show();
|
||||||
let _ = window_clone.set_focus();
|
let _ = window_clone.set_focus();
|
||||||
|
|
||||||
|
logging!(info, Type::Window, true, "窗口创建和显示流程已完成");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
logging!(error, Type::Window, true, "无法获取主窗口");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
logging!(info, Type::Window, true, "异步任务已创建");
|
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
logging!(
|
logging!(error, Type::Window, true, "Failed to create window: {}", e);
|
||||||
error,
|
|
||||||
Type::Window,
|
|
||||||
true,
|
|
||||||
"Failed to create window: {:?}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user