250 lines
9.5 KiB
Rust
250 lines
9.5 KiB
Rust
use tauri::Manager;
|
|
|
|
mod download_engine;
|
|
mod logger;
|
|
mod mihomo_manager;
|
|
mod monitor_kernel;
|
|
mod process_manager;
|
|
|
|
use download_engine::{
|
|
DownloadEngine, ExtensionServer,
|
|
downloader_add_task, downloader_get_extension_info, downloader_get_settings, downloader_get_tasks,
|
|
downloader_open_dir, downloader_open_url, downloader_pause_task, downloader_remove_task,
|
|
downloader_resume_task, downloader_save_settings, downloader_status,
|
|
};
|
|
use logger::{
|
|
clear_logs, get_log_info, get_logs, log_message, LogManager,
|
|
};
|
|
use mihomo_manager::{
|
|
proxy_activate_profile, proxy_check_kernel_update, proxy_clear_system_proxy, proxy_close_connection, proxy_delete_profile,
|
|
proxy_get_connections, proxy_get_proxies, proxy_get_settings, proxy_get_system_proxy,
|
|
proxy_import_profile, proxy_install_kernel, proxy_kernel_info, proxy_patch_configs, proxy_restart, proxy_save_settings,
|
|
proxy_select_proxy, proxy_set_system_proxy, proxy_start, proxy_status, proxy_stop,
|
|
proxy_test_delay, proxy_update_kernel, proxy_update_profile, proxy_version, MihomoManager,
|
|
};
|
|
use monitor_kernel::{
|
|
monitor_get_snapshot, monitor_get_status, monitor_kernel_info, monitor_start, monitor_status,
|
|
monitor_stop, MonitorKernel,
|
|
};
|
|
use process_manager::{
|
|
get_all_process_status, get_process_status, start_monitoring_thread, start_process,
|
|
stop_all_processes, stop_process, ProcessManager,
|
|
};
|
|
|
|
#[tauri::command]
|
|
fn greet(name: &str) -> String {
|
|
format!("Hello, {}! You've been greeted from Rust!", name)
|
|
}
|
|
|
|
#[tauri::command]
|
|
fn quit_app(
|
|
state: tauri::State<'_, ProcessManager>,
|
|
mihomo: tauri::State<'_, MihomoManager>,
|
|
engine: tauri::State<'_, DownloadEngine>,
|
|
app: tauri::AppHandle,
|
|
) {
|
|
// 退出前清理系统代理,避免遗留导致网络问题
|
|
mihomo.cleanup_on_exit();
|
|
// 退出前保存下载引擎状态
|
|
engine.cleanup_on_exit();
|
|
// 停止所有子进程(同步 kill + 带超时的 wait,确保进程真正终止)
|
|
state.stop_all();
|
|
// 通过 app.exit 触发 RunEvent::ExitRequested,统一退出路径
|
|
app.exit(0);
|
|
}
|
|
|
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
|
pub fn run() {
|
|
tauri::Builder::default()
|
|
.plugin(tauri_plugin_autostart::Builder::new().build())
|
|
.plugin(tauri_plugin_opener::init())
|
|
.plugin(tauri_plugin_dialog::init())
|
|
.plugin(
|
|
tauri_plugin_snap_layout::init()
|
|
.button_id("titlebar-maximize")
|
|
.build()
|
|
)
|
|
.manage(ProcessManager::new())
|
|
.invoke_handler(tauri::generate_handler![
|
|
greet,
|
|
quit_app,
|
|
start_process,
|
|
stop_process,
|
|
get_process_status,
|
|
get_all_process_status,
|
|
stop_all_processes,
|
|
log_message,
|
|
get_logs,
|
|
clear_logs,
|
|
get_log_info,
|
|
proxy_get_settings,
|
|
proxy_save_settings,
|
|
proxy_kernel_info,
|
|
proxy_check_kernel_update,
|
|
proxy_update_kernel,
|
|
proxy_install_kernel,
|
|
proxy_status,
|
|
proxy_start,
|
|
proxy_stop,
|
|
proxy_restart,
|
|
proxy_version,
|
|
proxy_get_proxies,
|
|
proxy_select_proxy,
|
|
proxy_test_delay,
|
|
proxy_get_connections,
|
|
proxy_close_connection,
|
|
proxy_patch_configs,
|
|
proxy_import_profile,
|
|
proxy_update_profile,
|
|
proxy_delete_profile,
|
|
proxy_activate_profile,
|
|
proxy_set_system_proxy,
|
|
proxy_clear_system_proxy,
|
|
proxy_get_system_proxy,
|
|
monitor_kernel_info,
|
|
monitor_status,
|
|
monitor_start,
|
|
monitor_stop,
|
|
monitor_get_status,
|
|
monitor_get_snapshot,
|
|
downloader_get_tasks,
|
|
downloader_add_task,
|
|
downloader_pause_task,
|
|
downloader_resume_task,
|
|
downloader_remove_task,
|
|
downloader_get_settings,
|
|
downloader_save_settings,
|
|
downloader_status,
|
|
downloader_get_extension_info,
|
|
downloader_open_dir,
|
|
downloader_open_url
|
|
])
|
|
.setup(|app| {
|
|
// 初始化日志系统,日志目录: {app_data_dir}/logs/
|
|
let log_dir = app
|
|
.path()
|
|
.app_data_dir()
|
|
.unwrap_or_else(|_| std::path::PathBuf::from("."))
|
|
.join("logs");
|
|
app.manage(LogManager::new(log_dir));
|
|
|
|
// 初始化 MihomoManager,数据目录: {app_data_dir}/proxy/
|
|
let app_data_dir = app
|
|
.path()
|
|
.app_data_dir()
|
|
.unwrap_or_else(|_| std::path::PathBuf::from("."));
|
|
|
|
let mihomo = MihomoManager::new(app_data_dir.clone());
|
|
app.manage(mihomo);
|
|
|
|
// 初始化 MonitorKernel,数据目录: {app_data_dir}/monitor/
|
|
let monitor = MonitorKernel::new(app_data_dir.clone());
|
|
app.manage(monitor);
|
|
|
|
// 初始化 DownloadEngine,数据目录: {app_data_dir}/downloader/
|
|
let engine = DownloadEngine::new(
|
|
app_data_dir.join("downloader"),
|
|
app.handle().clone(),
|
|
);
|
|
let settings = engine.get_settings();
|
|
app.manage(engine.clone());
|
|
|
|
// 启动扩展 HTTP API 服务器
|
|
let server_engine = engine.clone();
|
|
let server_port = settings.extension_port;
|
|
let server_secret = settings.extension_secret.clone();
|
|
tauri::async_runtime::spawn(async move {
|
|
ExtensionServer::start(server_engine, server_port, server_secret).await;
|
|
});
|
|
|
|
let open = tauri::menu::MenuItem::with_id(app, "open", "设置", true, None::<&str>)?;
|
|
let quit = tauri::menu::MenuItem::with_id(app, "quit", "退出", true, None::<&str>)?;
|
|
let menu = tauri::menu::Menu::with_items(app, &[&open, &quit])?;
|
|
|
|
let _tray = tauri::tray::TrayIconBuilder::new()
|
|
.icon(app.default_window_icon().unwrap().clone())
|
|
.menu(&menu)
|
|
.show_menu_on_left_click(false)
|
|
.on_menu_event(|app, event| match event.id().as_ref() {
|
|
"open" => {
|
|
if let Some(window) = app.get_webview_window("main") {
|
|
window.show().ok();
|
|
window.set_focus().ok();
|
|
}
|
|
}
|
|
"quit" => {
|
|
if let Some(mihomo) = app.try_state::<MihomoManager>() {
|
|
mihomo.cleanup_on_exit();
|
|
}
|
|
if let Some(engine) = app.try_state::<DownloadEngine>() {
|
|
engine.cleanup_on_exit();
|
|
}
|
|
if let Some(pm) = app.try_state::<ProcessManager>() {
|
|
pm.stop_all();
|
|
}
|
|
app.exit(0);
|
|
}
|
|
_ => {}
|
|
})
|
|
.on_tray_icon_event(|tray, event| {
|
|
if let tauri::tray::TrayIconEvent::Click {
|
|
button: tauri::tray::MouseButton::Left,
|
|
..
|
|
} = event
|
|
{
|
|
let app = tray.app_handle();
|
|
if let Some(window) = app.get_webview_window("main") {
|
|
window.show().ok();
|
|
window.set_focus().ok();
|
|
}
|
|
}
|
|
})
|
|
.build(app)?;
|
|
|
|
// 启动进程监控线程
|
|
start_monitoring_thread(app.handle().clone());
|
|
|
|
// 应用启动时自动启动 mihomo(如果用户在设置中开启了自动启动)
|
|
if let Some(mihomo) = app.try_state::<MihomoManager>() {
|
|
if let Some(pm) = app.try_state::<ProcessManager>() {
|
|
mihomo.auto_start_on_launch(app.handle(), &pm);
|
|
}
|
|
}
|
|
|
|
// 应用启动时自动启动 monitor Kernel(硬件监控默认启用,被动读取无副作用)
|
|
if let Some(monitor) = app.try_state::<MonitorKernel>() {
|
|
let monitor = monitor.inner().clone();
|
|
let app_handle = app.handle().clone();
|
|
tauri::async_runtime::spawn(async move {
|
|
match monitor.start_with_subscription(&app_handle).await {
|
|
Ok(info) => eprintln!("[monitor] 自动启动成功, pid={:?}", info.pid),
|
|
Err(e) => eprintln!("[monitor] 自动启动跳过: {}", e),
|
|
}
|
|
});
|
|
}
|
|
|
|
Ok(())
|
|
})
|
|
.on_window_event(|window, event| {
|
|
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
|
|
window.hide().ok();
|
|
api.prevent_close();
|
|
}
|
|
})
|
|
.build(tauri::generate_context!())
|
|
.expect("error while building tauri application")
|
|
.run(|app, event| {
|
|
if let tauri::RunEvent::ExitRequested { .. } = event {
|
|
if let Some(mihomo) = app.try_state::<MihomoManager>() {
|
|
mihomo.cleanup_on_exit();
|
|
}
|
|
if let Some(engine) = app.try_state::<DownloadEngine>() {
|
|
engine.cleanup_on_exit();
|
|
}
|
|
if let Some(pm) = app.try_state::<ProcessManager>() {
|
|
pm.stop_all();
|
|
}
|
|
}
|
|
});
|
|
}
|