//! 主模块,用于启动应用 //! @since Beta v0.9.1 mod client; mod commands; mod plugins; mod tray; mod utils; #[cfg(target_os = "windows")] mod watchdog; #[cfg(target_os = "windows")] mod yae; use crate::client::create_mhy_client; use crate::commands::{ create_window, execute_js, get_dir_size, hide_main_window, init_app, is_in_admin, launch_game, quit_app, read_text_scale, }; use tauri::{generate_context, generate_handler, Emitter, Manager, Window, WindowEvent}; // 子窗口 label 的数组 pub const SUB_WINDOW_LABELS: [&str; 3] = ["Sub_window", "Dev_JSON", "mhy_client"]; // 窗口事件处理 fn window_event_handler(app: &Window, event: &WindowEvent) { match event { WindowEvent::CloseRequested { api, .. } => { api.prevent_close(); if app.label() == "TeyvatGuide" { // 主窗口:发送事件让前端根据配置决定是隐藏还是退出 let _ = app.emit("main-window-close-requested", ()); } else { // 子窗口:直接销毁 app.destroy().unwrap(); } } _ => {} } } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { #[cfg(target_os = "windows")] { let args: Vec = std::env::args().collect(); let is_watchdog = args.iter().any(|a| a == "--watchdog"); // 看门狗模式:不初始化 Tauri,不加载单例,纯等待 + 提权启动 if is_watchdog { // 解析父进程 PID let mut ppid: u32 = 0; for a in &args { if let Some(rest) = a.strip_prefix("--ppid=") { if let Ok(v) = rest.parse::() { ppid = v; } } } // 等父进程退出后再 runas 启动管理员实例,传入 --elevated 标志 let _ = watchdog::run_watchdog(ppid, "--elevated"); // 看门狗退出 return; } } // 正常应用实例:加载单例插件,防止多实例 let mut builder = tauri::Builder::default(); // 只有在正常/管理员实例下才加载单例插件;看门狗不加载 builder = builder.plugin(tauri_plugin_single_instance::init(move |app, argv, _cwd| { if let Err(e) = app.emit("active_deep_link", argv) { eprintln!("emit active_deep_link failed: {}", e); } })); builder .on_window_event(move |app, event| window_event_handler(app, event)) .plugin(tauri_plugin_notification::init()) .plugin(tauri_plugin_deep_link::init()) .plugin(tauri_plugin_cli::init()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_process::init()) .plugin(tauri_plugin_sql::Builder::default().build()) .plugin(tauri_plugin_machine_uid::init()) .plugin(plugins::custom_log::build_log_plugin()) .setup(|_app| { // 创建系统托盘图标 tray::create_tray(_app.handle()) .expect("Failed to initialize system tray icon. Please check if the tray icon file exists and the system supports tray icons."); let _window = _app.get_webview_window("TeyvatGuide"); plugins::text_scale::init(_app.handle().clone()); #[cfg(debug_assertions)] if _window.is_some() { _window.unwrap().open_devtools(); } Ok(()) }) .invoke_handler(generate_handler![ init_app, create_window, execute_js, get_dir_size, create_mhy_client, is_in_admin, hide_main_window, quit_app, read_text_scale, launch_game, #[cfg(target_os = "windows")] yae::call_yae_dll, #[cfg(target_os = "windows")] watchdog::run_with_admin ]) .run(generate_context!()) .expect("error while running tauri application"); }