Files
TeyvatGuide/src-tauri/src/lib.rs
Copilot 7544fa1489 支持托盘 (#181)
* Initial plan

* Add system tray icon feature with show/quit menu

Co-authored-by: BTMuli <72692909+BTMuli@users.noreply.github.com>

* Apply Rust code formatting

Co-authored-by: BTMuli <72692909+BTMuli@users.noreply.github.com>

* Address code review feedback: improve documentation and reduce duplication

Co-authored-by: BTMuli <72692909+BTMuli@users.noreply.github.com>

* Make tray behavior configurable - add closeToTray setting

- Add closeToTray setting in app store (default: false)
- Add UI toggle in PageConfig.vue for "关闭到托盘" setting
- Modify window close handler to emit event instead of always hiding
- Add hide_main_window and quit_app commands in backend
- Frontend listens for close event and respects user preference
- When closeToTray is enabled, window minimizes to tray on close
- When disabled, application quits on close (original behavior)

Co-authored-by: BTMuli <72692909+BTMuli@users.noreply.github.com>

* Remove duplicate SUB_WINDOW_LABELS constant - use shared constant from lib.rs

Co-authored-by: BTMuli <72692909+BTMuli@users.noreply.github.com>

* Fix tray icon issues: remove duplicate tray, add icon loading, close sub-windows on hide

1. Remove duplicate tray icon: Removed trayIcon config from tauri.conf.json (was creating 2 trays)
2. Add proper icon loading: Use image crate to decode PNG and create RGBA icon data
3. Close sub-windows when hiding: Modified hide_main_window to close all sub-windows before hiding
4. Sync with master branch: Merged latest commit c8fe03c

Co-authored-by: BTMuli <72692909+BTMuli@users.noreply.github.com>

* Address code review: remove anyhow, add separator, improve comments

1. Remove anyhow dependency - Use Tauri's InvalidIcon error instead
2. Add menu separator between "显示窗口" and "退出应用"
3. Add comment explaining image crate necessity (Tauri Image only accepts raw RGBA)
4. Keep HTTPS URLs with note about SSH preference for local development
5. Image crate remains necessary as Tauri doesn't provide PNG decoding

Co-authored-by: BTMuli <72692909+BTMuli@users.noreply.github.com>

* Revert to SSH URLs for plugin dependencies as requested

Changed all tauri-plugin git URLs from HTTPS to SSH format.
Project CI has SSH configuration, so SSH is the preferred method.

Co-authored-by: BTMuli <72692909+BTMuli@users.noreply.github.com>

* Use storeToRefs for closeToTray property

Changed closeToTray access to use storeToRefs in both App.vue and PageConfig.vue
for better reactivity and consistency with other store properties.

Co-authored-by: BTMuli <72692909+BTMuli@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: BTMuli <72692909+BTMuli@users.noreply.github.com>
2025-12-14 14:30:15 +08:00

110 lines
3.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 主模块,用于启动应用
//! @since Beta v0.8.8
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, quit_app,
};
use crate::plugins::{build_log_plugin, build_si_plugin};
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<String> = 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::<u32>() {
ppid = v;
}
}
}
// 等父进程退出后再 runas 启动管理员实例,传入 --elevated 标志
let _ = watchdog::run_watchdog(ppid, "--elevated");
// 看门狗退出
return;
}
}
// 正常应用实例:加载单例插件,防止多实例
let mut builder = tauri::Builder::default();
// 只有在正常/管理员实例下才加载单例插件;看门狗不加载
builder = builder.plugin(build_si_plugin());
builder
.on_window_event(move |app, event| window_event_handler(app, event))
.plugin(tauri_plugin_deep_link::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_shell::init())
.plugin(tauri_plugin_sql::Builder::default().build())
.plugin(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");
#[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,
#[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");
}