2024-09-20 10:14:36 +08:00
|
|
|
use tauri::{
|
2025-11-06 03:07:38 +08:00
|
|
|
menu::{CheckMenuItem, Menu, MenuItem, PredefinedMenuItem, Submenu},
|
2024-09-20 10:14:36 +08:00
|
|
|
tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},
|
2025-03-27 00:58:18 +08:00
|
|
|
Emitter, Listener, Manager, Runtime,
|
2024-09-20 10:14:36 +08:00
|
|
|
};
|
2025-11-06 03:07:38 +08:00
|
|
|
use serde::{Deserialize, Serialize};
|
2024-09-20 10:14:36 +08:00
|
|
|
|
2025-03-27 00:58:18 +08:00
|
|
|
use crate::tool::powerplan::PowerPlanMode;
|
|
|
|
|
|
2025-11-06 03:07:38 +08:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
|
struct LaunchOption {
|
|
|
|
|
option: String,
|
|
|
|
|
name: String,
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-20 10:14:36 +08:00
|
|
|
pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
|
2025-03-26 03:00:18 +08:00
|
|
|
// 托盘菜单项目
|
2025-03-27 00:58:18 +08:00
|
|
|
let separator = &PredefinedMenuItem::separator(app).unwrap();
|
|
|
|
|
|
|
|
|
|
let show_i = &MenuItem::with_id(app, "show", "显示主界面", true, None::<&str>)?;
|
|
|
|
|
let quit_i = &MenuItem::with_id(app, "quit", "退出", true, None::<&str>)?;
|
|
|
|
|
|
|
|
|
|
let kill_game_i = &MenuItem::with_id(app, "kill_game", "关闭CS2", true, None::<&str>)?;
|
|
|
|
|
let kill_steam_i = &MenuItem::with_id(app, "kill_steam", "关闭Steam", true, None::<&str>)?;
|
|
|
|
|
|
|
|
|
|
let launch_ww_i = &MenuItem::with_id(app, "launch_ww", "启动国际服", true, None::<&str>)?;
|
|
|
|
|
let launch_pw_i = &MenuItem::with_id(app, "launch_pw", "启动国服", true, None::<&str>)?;
|
|
|
|
|
|
|
|
|
|
let power_plan_extreme = CheckMenuItem::with_id(
|
|
|
|
|
app,
|
|
|
|
|
"power_plan_extreme",
|
|
|
|
|
"卓越性能",
|
|
|
|
|
true,
|
|
|
|
|
false,
|
|
|
|
|
None::<&str>,
|
|
|
|
|
)?;
|
|
|
|
|
let power_plan_high =
|
|
|
|
|
CheckMenuItem::with_id(app, "power_plan_high", "高性能", true, false, None::<&str>)?;
|
|
|
|
|
let power_plan_balanced = CheckMenuItem::with_id(
|
|
|
|
|
app,
|
|
|
|
|
"power_plan_balanced",
|
|
|
|
|
"平衡",
|
|
|
|
|
true,
|
|
|
|
|
false,
|
|
|
|
|
None::<&str>,
|
|
|
|
|
)?;
|
|
|
|
|
let power_plan_powersave = CheckMenuItem::with_id(
|
|
|
|
|
app,
|
|
|
|
|
"power_plan_powersave",
|
|
|
|
|
"节能",
|
|
|
|
|
true,
|
|
|
|
|
false,
|
|
|
|
|
None::<&str>,
|
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
|
2025-11-06 03:07:38 +08:00
|
|
|
// 创建启动项子菜单(初始为空,后续会动态更新)
|
|
|
|
|
let launch_option_submenu = Submenu::with_id(app, "launch_option_submenu", "启动项: 游戏", true)?;
|
2025-03-26 03:00:18 +08:00
|
|
|
|
|
|
|
|
// 创建托盘菜单
|
2025-03-26 03:49:03 +08:00
|
|
|
let menu = Menu::with_items(
|
|
|
|
|
app,
|
|
|
|
|
&[
|
2025-03-27 00:58:18 +08:00
|
|
|
&power_plan_extreme,
|
|
|
|
|
&power_plan_high,
|
|
|
|
|
&power_plan_balanced,
|
|
|
|
|
&power_plan_powersave,
|
|
|
|
|
separator,
|
2025-11-06 03:07:38 +08:00
|
|
|
&launch_option_submenu,
|
2025-03-27 00:58:18 +08:00
|
|
|
launch_ww_i,
|
|
|
|
|
launch_pw_i,
|
|
|
|
|
separator,
|
|
|
|
|
kill_game_i,
|
|
|
|
|
kill_steam_i,
|
|
|
|
|
separator,
|
|
|
|
|
show_i,
|
|
|
|
|
quit_i,
|
2025-03-26 03:49:03 +08:00
|
|
|
],
|
|
|
|
|
)?;
|
2024-09-20 10:14:36 +08:00
|
|
|
|
2025-03-27 00:58:18 +08:00
|
|
|
let _ = app.listen("tray://get_powerplan", move |event| {
|
|
|
|
|
if let Ok(payload) = event.payload().parse::<i32>() {
|
|
|
|
|
match payload {
|
|
|
|
|
x if x == PowerPlanMode::Other as i32 => {
|
|
|
|
|
let _ = power_plan_powersave.set_checked(false);
|
|
|
|
|
let _ = power_plan_balanced.set_checked(false);
|
|
|
|
|
let _ = power_plan_high.set_checked(false);
|
|
|
|
|
let _ = power_plan_extreme.set_checked(false);
|
|
|
|
|
}
|
|
|
|
|
x if x == PowerPlanMode::PowerSaving as i32 => {
|
|
|
|
|
let _ = power_plan_powersave.set_checked(true);
|
|
|
|
|
let _ = power_plan_balanced.set_checked(false);
|
|
|
|
|
let _ = power_plan_high.set_checked(false);
|
|
|
|
|
let _ = power_plan_extreme.set_checked(false);
|
|
|
|
|
}
|
|
|
|
|
x if x == PowerPlanMode::Balanced as i32 => {
|
|
|
|
|
let _ = power_plan_powersave.set_checked(false);
|
|
|
|
|
let _ = power_plan_balanced.set_checked(true);
|
|
|
|
|
let _ = power_plan_high.set_checked(false);
|
|
|
|
|
let _ = power_plan_extreme.set_checked(false);
|
|
|
|
|
}
|
|
|
|
|
x if x == PowerPlanMode::HighPerformance as i32 => {
|
|
|
|
|
let _ = power_plan_powersave.set_checked(false);
|
|
|
|
|
let _ = power_plan_balanced.set_checked(false);
|
|
|
|
|
let _ = power_plan_high.set_checked(true);
|
|
|
|
|
let _ = power_plan_extreme.set_checked(false);
|
|
|
|
|
}
|
|
|
|
|
x if x == PowerPlanMode::Extreme as i32 => {
|
|
|
|
|
let _ = power_plan_powersave.set_checked(false);
|
|
|
|
|
let _ = power_plan_balanced.set_checked(false);
|
|
|
|
|
let _ = power_plan_high.set_checked(false);
|
|
|
|
|
let _ = power_plan_extreme.set_checked(true);
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2025-11-06 03:07:38 +08:00
|
|
|
// 监听启动项列表更新事件
|
|
|
|
|
let launch_option_submenu_clone = launch_option_submenu.clone();
|
|
|
|
|
let _ = app.listen("tray://update_launch_options", move |event| {
|
|
|
|
|
if let Ok(data) = serde_json::from_str::<serde_json::Value>(event.payload()) {
|
|
|
|
|
if let (Some(options), Some(current_index)) = (
|
|
|
|
|
data.get("options").and_then(|v| v.as_array()),
|
|
|
|
|
data.get("currentIndex").and_then(|v| v.as_u64()),
|
|
|
|
|
) {
|
|
|
|
|
let current_index = current_index as usize;
|
|
|
|
|
// 获取当前启动项名称
|
|
|
|
|
let current_name = options
|
|
|
|
|
.get(current_index)
|
|
|
|
|
.and_then(|opt| opt.get("name"))
|
|
|
|
|
.and_then(|n| n.as_str())
|
|
|
|
|
.map(|s| s.to_string())
|
|
|
|
|
.unwrap_or_else(|| format!("{}", current_index + 1));
|
|
|
|
|
|
|
|
|
|
// 更新子菜单标题
|
|
|
|
|
let _ = launch_option_submenu_clone.set_text(format!("启动项: {}", current_name));
|
|
|
|
|
|
|
|
|
|
// 清空现有子菜单项 - 先收集所有项目,然后移除
|
|
|
|
|
if let Ok(items) = launch_option_submenu_clone.items() {
|
|
|
|
|
let items_to_remove: Vec<_> = items.iter().collect();
|
|
|
|
|
for item in items_to_remove {
|
|
|
|
|
let _ = launch_option_submenu_clone.remove(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 创建新的子菜单项
|
|
|
|
|
for (index, option) in options.iter().enumerate() {
|
|
|
|
|
if let Some(name) = option.get("name").and_then(|n| n.as_str()) {
|
|
|
|
|
let display_name = if name.is_empty() {
|
|
|
|
|
format!("{}", index + 1)
|
|
|
|
|
} else {
|
|
|
|
|
name.to_string()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let item_id = format!("launch_option_{}", index);
|
|
|
|
|
let app_handle = launch_option_submenu_clone.app_handle();
|
|
|
|
|
if let Ok(item) = CheckMenuItem::with_id(
|
|
|
|
|
app_handle,
|
|
|
|
|
&item_id,
|
|
|
|
|
&display_name,
|
|
|
|
|
true,
|
|
|
|
|
index == current_index,
|
|
|
|
|
None::<&str>,
|
|
|
|
|
) {
|
|
|
|
|
let _ = launch_option_submenu_clone.append(&item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-03-27 00:58:18 +08:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2024-09-20 10:14:36 +08:00
|
|
|
let _ = TrayIconBuilder::with_id("tray")
|
|
|
|
|
.icon(app.default_window_icon().unwrap().clone())
|
|
|
|
|
.menu(&menu)
|
2025-03-13 02:34:59 +08:00
|
|
|
.show_menu_on_left_click(false)
|
2024-09-20 10:14:36 +08:00
|
|
|
.on_menu_event(move |app, event| match event.id.as_ref() {
|
|
|
|
|
"quit" => {
|
|
|
|
|
app.exit(0);
|
|
|
|
|
}
|
2025-03-26 03:00:18 +08:00
|
|
|
"show" => {
|
2025-03-26 03:49:03 +08:00
|
|
|
if let Some(window) = app.get_webview_window("main") {
|
|
|
|
|
let _ = window.show();
|
|
|
|
|
let _ = window.set_focus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"launch_ww" => {
|
|
|
|
|
let _ = app.emit("tray://launch_game", "worldwide");
|
|
|
|
|
}
|
|
|
|
|
"launch_pw" => {
|
|
|
|
|
let _ = app.emit("tray://launch_game", "perfectworld");
|
|
|
|
|
}
|
|
|
|
|
"kill_game" => {
|
|
|
|
|
let _ = app.emit("tray://kill_game", None::<()>);
|
|
|
|
|
}
|
|
|
|
|
"kill_steam" => {
|
|
|
|
|
let _ = app.emit("tray://kill_steam", None::<()>);
|
2025-03-26 03:00:18 +08:00
|
|
|
}
|
2025-03-27 00:58:18 +08:00
|
|
|
"power_plan_extreme" => {
|
|
|
|
|
let _ = app.emit("tray://set_powerplan", PowerPlanMode::Extreme as i32);
|
|
|
|
|
// let _ = power_plan_extreme.set_checked(true);
|
|
|
|
|
}
|
|
|
|
|
"power_plan_high" => {
|
|
|
|
|
let _ = app.emit(
|
|
|
|
|
"tray://set_powerplan",
|
|
|
|
|
PowerPlanMode::HighPerformance as i32,
|
|
|
|
|
);
|
|
|
|
|
// let _ = power_plan_high.set_checked(true);
|
|
|
|
|
}
|
|
|
|
|
"power_plan_balanced" => {
|
|
|
|
|
let _ = app.emit("tray://set_powerplan", PowerPlanMode::Balanced as i32);
|
|
|
|
|
// let _ = power_plan_balanced.set_checked(true);
|
|
|
|
|
}
|
|
|
|
|
"power_plan_powersave" => {
|
|
|
|
|
let _ = app.emit("tray://set_powerplan", PowerPlanMode::PowerSaving as i32);
|
|
|
|
|
// let _ = power_plan_powersave.set_checked(true);
|
|
|
|
|
}
|
2025-11-06 03:07:38 +08:00
|
|
|
id if id.starts_with("launch_option_") => {
|
|
|
|
|
// 提取索引
|
|
|
|
|
if let Ok(index) = id.replace("launch_option_", "").parse::<usize>() {
|
|
|
|
|
let _ = app.emit("tray://set_launch_index", index);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-20 10:14:36 +08:00
|
|
|
_ => {}
|
|
|
|
|
})
|
|
|
|
|
.on_tray_icon_event(|tray, event| {
|
|
|
|
|
if let TrayIconEvent::Click {
|
|
|
|
|
button: MouseButton::Left,
|
|
|
|
|
button_state: MouseButtonState::Up,
|
|
|
|
|
..
|
|
|
|
|
} = event
|
|
|
|
|
{
|
|
|
|
|
let app = tray.app_handle();
|
|
|
|
|
if let Some(window) = app.get_webview_window("main") {
|
|
|
|
|
let _ = window.show();
|
|
|
|
|
let _ = window.set_focus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.build(app);
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|