perf: optimize layout initialization and enhance backend notification mechanism

This commit is contained in:
wonfen
2025-06-15 19:35:12 +08:00
parent dd0e9d4e1b
commit dd505e4d58
4 changed files with 236 additions and 198 deletions

View File

@@ -188,78 +188,30 @@ async fn clean_async() -> bool {
}
pub fn clean() -> bool {
use tokio::time::{timeout, Duration};
use crate::process::AsyncHandler;
// 使用异步处理
let rt = tokio::runtime::Runtime::new().unwrap();
let cleanup_result = rt.block_on(async {
let (tx, rx) = std::sync::mpsc::channel();
AsyncHandler::spawn(move || async move {
log::info!(target: "app", "开始执行清理操作...");
// 1. 处理TUN模式 - 并行执行,减少等待时间
let tun_task = async {
if Config::verge().data().enable_tun_mode.unwrap_or(false) {
let disable_tun = serde_json::json!({
"tun": {
"enable": false
}
});
timeout(
Duration::from_secs(2),
MihomoManager::global().patch_configs(disable_tun),
)
.await
.is_ok()
} else {
true
}
};
// 使用已有的异步清理函数
let cleanup_result = clean_async().await;
// 2. 系统代理重置
let proxy_task = async {
timeout(
Duration::from_secs(2),
sysopt::Sysopt::global().reset_sysproxy(),
)
.await
.is_ok()
};
// 3. 核心服务停止
let core_task = async {
timeout(Duration::from_secs(2), CoreManager::global().stop_core())
.await
.is_ok()
};
// 4. DNS恢复仅macOS
#[cfg(target_os = "macos")]
let dns_task = async {
timeout(Duration::from_millis(800), resolve::restore_public_dns())
.await
.is_ok()
};
// 并行执行所有清理任务,提高效率
let (tun_success, proxy_success, core_success) =
tokio::join!(tun_task, proxy_task, core_task);
#[cfg(target_os = "macos")]
let dns_success = dns_task.await;
#[cfg(not(target_os = "macos"))]
let dns_success = true;
let all_success = tun_success && proxy_success && core_success && dns_success;
log::info!(
target: "app",
"清理操作完成 - TUN: {}, 代理: {}, 核心: {}, DNS: {}, 总体: {}",
tun_success, proxy_success, core_success, dns_success, all_success
);
all_success
// 发送结果
let _ = tx.send(cleanup_result);
});
cleanup_result
match rx.recv_timeout(std::time::Duration::from_secs(8)) {
Ok(result) => {
log::info!(target: "app", "清理操作完成,结果: {}", result);
result
}
Err(_) => {
log::warn!(target: "app", "清理操作超时,返回成功状态避免阻塞");
true
}
}
}
#[cfg(target_os = "macos")]

View File

@@ -172,19 +172,20 @@ fn cancel_window_close_listener() {
fn setup_light_weight_timer() -> Result<()> {
Timer::global().init()?;
let mut timer_map = Timer::global().timer_map.write();
let delay_timer = Timer::global().delay_timer.write();
let mut timer_count = Timer::global().timer_count.lock();
let task_id = *timer_count;
*timer_count += 1;
let once_by_minutes = Config::verge()
.latest()
.auto_light_weight_minutes
.unwrap_or(10);
// 获取task_id
let task_id = {
let mut timer_count = Timer::global().timer_count.lock();
let id = *timer_count;
*timer_count += 1;
id
};
// 创建任务
let task = TaskBuilder::default()
.set_task_id(task_id)
.set_maximum_parallel_runnable_num(1)
@@ -195,17 +196,24 @@ fn setup_light_weight_timer() -> Result<()> {
})
.context("failed to create timer task")?;
delay_timer
.add_task(task)
.context("failed to add timer task")?;
// 添加任务到定时器
{
let delay_timer = Timer::global().delay_timer.write();
delay_timer
.add_task(task)
.context("failed to add timer task")?;
}
let timer_task = crate::core::timer::TimerTask {
task_id,
interval_minutes: once_by_minutes,
last_run: chrono::Local::now().timestamp(),
};
timer_map.insert(LIGHT_WEIGHT_TASK_UID.to_string(), timer_task);
// 更新任务映射
{
let mut timer_map = Timer::global().timer_map.write();
let timer_task = crate::core::timer::TimerTask {
task_id,
interval_minutes: once_by_minutes,
last_run: chrono::Local::now().timestamp(),
};
timer_map.insert(LIGHT_WEIGHT_TASK_UID.to_string(), timer_task);
}
logging!(
info,

View File

@@ -344,49 +344,72 @@ pub fn create_window(is_show: bool) -> bool {
.fullscreen(false)
.inner_size(DEFAULT_WIDTH as f64, DEFAULT_HEIGHT as f64)
.min_inner_size(520.0, 520.0)
.visible(true) // 立即显示窗口,避免用户等待
.initialization_script(r#"
// 添加非侵入式的加载指示器
document.addEventListener('DOMContentLoaded', function() {
// 只有在React应用还没有挂载时才显示加载指示器
if (!document.getElementById('root') || !document.getElementById('root').hasChildNodes()) {
// 创建加载指示器但不覆盖整个body
const loadingDiv = document.createElement('div');
loadingDiv.id = 'initial-loading-overlay';
loadingDiv.innerHTML = `
<div style="
position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background: var(--bg-color, #f5f5f5); color: var(--text-color, #333);
display: flex; flex-direction: column; align-items: center;
justify-content: center; z-index: 9998; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
">
<div style="margin-bottom: 20px;">
<div style="width: 40px; height: 40px; border: 3px solid #e3e3e3; border-top: 3px solid #3498db; border-radius: 50%; animation: spin 1s linear infinite;"></div>
</div>
<div style="font-size: 14px; opacity: 0.7;">正在加载 Clash Verge...</div>
</div>
<style>
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@media (prefers-color-scheme: dark) {
:root { --bg-color: #1a1a1a; --text-color: #ffffff; }
}
</style>
`;
document.body.appendChild(loadingDiv);
// 设置定时器如果React应用在5秒内没有挂载移除加载指示器
setTimeout(() => {
const overlay = document.getElementById('initial-loading-overlay');
if (overlay) {
overlay.remove();
}
}, 5000);
.visible(true) // 立即显示窗口,避免用户等待
.initialization_script(
r#"
console.log('[Tauri] 窗口初始化脚本开始执行');
function createLoadingOverlay() {
if (document.getElementById('initial-loading-overlay')) {
console.log('[Tauri] 加载指示器已存在');
return;
}
});
"#)
console.log('[Tauri] 创建加载指示器');
const loadingDiv = document.createElement('div');
loadingDiv.id = 'initial-loading-overlay';
loadingDiv.innerHTML = `
<div style="
position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background: var(--bg-color, #f5f5f5); color: var(--text-color, #333);
display: flex; flex-direction: column; align-items: center;
justify-content: center; z-index: 9999;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
transition: opacity 0.3s ease;
">
<div style="margin-bottom: 20px;">
<div style="
width: 40px; height: 40px; border: 3px solid #e3e3e3;
border-top: 3px solid #3498db; border-radius: 50%;
animation: spin 1s linear infinite;
"></div>
</div>
<div style="font-size: 14px; opacity: 0.7;">Loading Clash Verge...</div>
</div>
<style>
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@media (prefers-color-scheme: dark) {
:root { --bg-color: #1a1a1a; --text-color: #ffffff; }
}
</style>
`;
if (document.body) {
document.body.appendChild(loadingDiv);
} else {
document.addEventListener('DOMContentLoaded', () => {
if (document.body && !document.getElementById('initial-loading-overlay')) {
document.body.appendChild(loadingDiv);
}
});
}
}
createLoadingOverlay();
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', createLoadingOverlay);
} else {
createLoadingOverlay();
}
console.log('[Tauri] 窗口初始化脚本执行完成');
"#,
)
.build()
{
Ok(newly_created_window) => {