6 Commits

Author SHA1 Message Date
Purp1e
e29b48b98c [fix] building error due to eslint 2025-03-27 00:59:03 +08:00
Purp1e
21cdc7c32d [feat] tray powerplan items and seperators 2025-03-27 00:58:18 +08:00
Purp1e
27439593b4 [fix] building error 2025-03-26 03:50:47 +08:00
Purp1e
ed040aadf5 remove unused type inference 2025-03-26 03:49:59 +08:00
Purp1e
8f885a5412 [feat] tray items with kill and launch game
todo: launch option selection + seperator
2025-03-26 03:49:03 +08:00
Purp1e
ee03bf0160 [feat] start hidden + hidden on close + basic tray function 2025-03-26 03:00:18 +08:00
24 changed files with 487 additions and 119 deletions

BIN
bun.lockb

Binary file not shown.

View File

@@ -24,6 +24,7 @@
"@supabase/ssr": "0.6.1",
"@tauri-apps/api": "2.4.0",
"@tauri-apps/plugin-autostart": "^2.2.0",
"@tauri-apps/plugin-cli": "~2",
"@tauri-apps/plugin-clipboard-manager": "2.2.2",
"@tauri-apps/plugin-deep-link": "~2.2.0",
"@tauri-apps/plugin-dialog": "~2.2.0",
@@ -55,11 +56,11 @@
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.1",
"@types/jest": "^29.5.14",
"@types/node": "^22.13.11",
"@types/node": "^22.13.13",
"@types/react": "19.0.10",
"@types/react-dom": "19.0.4",
"@typescript-eslint/eslint-plugin": "^8.27.0",
"@typescript-eslint/parser": "^8.27.0",
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"autoprefixer": "^10.4.21",
"clsx": "^2.1.1",
"cross-env": "^7.0.3",

111
src-tauri/Cargo.lock generated
View File

@@ -16,6 +16,7 @@ dependencies = [
"tauri",
"tauri-build",
"tauri-plugin-autostart",
"tauri-plugin-cli",
"tauri-plugin-clipboard-manager",
"tauri-plugin-deep-link",
"tauri-plugin-dialog",
@@ -90,6 +91,56 @@ dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
dependencies = [
"anstyle",
"once_cell",
"windows-sys 0.59.0",
]
[[package]]
name = "anyhow"
version = "1.0.97"
@@ -691,6 +742,33 @@ dependencies = [
"windows-link",
]
[[package]]
name = "clap"
version = "4.5.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83"
dependencies = [
"clap_builder",
]
[[package]]
name = "clap_builder"
version = "4.5.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_lex"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "clipboard-win"
version = "5.4.0"
@@ -730,6 +808,12 @@ dependencies = [
"objc",
]
[[package]]
name = "colorchoice"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "combine"
version = "4.6.7"
@@ -2441,6 +2525,12 @@ dependencies = [
"once_cell",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itertools"
version = "0.14.0"
@@ -5075,6 +5165,21 @@ dependencies = [
"thiserror 2.0.12",
]
[[package]]
name = "tauri-plugin-cli"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5458ae16eac81bdbe8d9da2a9f3e01e8cdedbc381cc1727c01127542c8a61c5"
dependencies = [
"clap",
"log",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
"thiserror 2.0.12",
]
[[package]]
name = "tauri-plugin-clipboard-manager"
version = "2.2.2"
@@ -6013,6 +6118,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.16.0"

View File

@@ -64,5 +64,6 @@ default = [ "custom-protocol" ]
custom-protocol = [ "tauri/custom-protocol" ]
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-cli = "2"
tauri-plugin-global-shortcut = "2.2.0"
tauri-plugin-single-instance = "2.2.2"

View File

@@ -27,6 +27,7 @@
"deep-link:allow-get-current",
"autostart:default",
"autostart:allow-enable",
"autostart:allow-disable"
"autostart:allow-disable",
"cli:default"
]
}

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"desktop-capability":{"identifier":"desktop-capability","description":"","local":true,"windows":["main"],"permissions":["global-shortcut:default","theme:default","store:default","store:allow-set","store:allow-get-store","store:allow-has","store:allow-delete","store:allow-clear","store:allow-values","store:allow-save","store:allow-load","store:allow-reset","store:allow-entries","deep-link:default","deep-link:allow-register","deep-link:allow-get-current","autostart:default","autostart:allow-enable","autostart:allow-disable"],"platforms":["macOS","windows","linux"]},"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","fs:allow-read-file","fs:allow-write-file","fs:allow-read-dir","fs:allow-copy-file","fs:allow-mkdir","fs:allow-remove","fs:allow-remove","fs:allow-rename","fs:allow-exists","core:window:allow-create","core:window:allow-center","core:window:allow-request-user-attention","core:window:allow-set-resizable","core:window:allow-set-maximizable","core:window:allow-set-minimizable","core:window:allow-set-closable","core:window:allow-set-title","core:window:allow-maximize","core:window:allow-unmaximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-set-decorations","core:window:allow-set-always-on-top","core:window:allow-set-content-protected","core:window:allow-set-size","core:window:allow-set-min-size","core:window:allow-set-max-size","core:window:allow-set-position","core:window:allow-set-fullscreen","core:window:allow-set-focus","core:window:allow-set-icon","core:window:allow-set-skip-taskbar","core:window:allow-set-cursor-grab","core:window:allow-set-cursor-visible","core:window:allow-set-cursor-icon","core:window:allow-set-cursor-position","core:window:allow-set-ignore-cursor-events","core:window:allow-start-dragging","core:webview:allow-print","shell:allow-execute","shell:allow-open","dialog:allow-open","dialog:allow-save","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","http:default","notification:default","global-shortcut:allow-is-registered","global-shortcut:allow-register","global-shortcut:allow-register-all","global-shortcut:allow-unregister","global-shortcut:allow-unregister-all","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","process:allow-restart","process:allow-exit","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","core:app:allow-set-app-theme","process:default","fs:default","dialog:default","os:default","clipboard-manager:default"]},"system-info":{"identifier":"system-info","description":"","local":true,"windows":["*"],"permissions":["system-info:allow-all"]},"valtio":{"identifier":"valtio","description":"","local":true,"windows":["*"],"permissions":["valtio:default","core:event:default"]}}
{"desktop-capability":{"identifier":"desktop-capability","description":"","local":true,"windows":["main"],"permissions":["global-shortcut:default","theme:default","store:default","store:allow-set","store:allow-get-store","store:allow-has","store:allow-delete","store:allow-clear","store:allow-values","store:allow-save","store:allow-load","store:allow-reset","store:allow-entries","deep-link:default","deep-link:allow-register","deep-link:allow-get-current","autostart:default","autostart:allow-enable","autostart:allow-disable","cli:default"],"platforms":["macOS","windows","linux"]},"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:default","fs:allow-read-file","fs:allow-write-file","fs:allow-read-dir","fs:allow-copy-file","fs:allow-mkdir","fs:allow-remove","fs:allow-remove","fs:allow-rename","fs:allow-exists","core:window:allow-create","core:window:allow-center","core:window:allow-request-user-attention","core:window:allow-set-resizable","core:window:allow-set-maximizable","core:window:allow-set-minimizable","core:window:allow-set-closable","core:window:allow-set-title","core:window:allow-maximize","core:window:allow-unmaximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-set-decorations","core:window:allow-set-always-on-top","core:window:allow-set-content-protected","core:window:allow-set-size","core:window:allow-set-min-size","core:window:allow-set-max-size","core:window:allow-set-position","core:window:allow-set-fullscreen","core:window:allow-set-focus","core:window:allow-set-icon","core:window:allow-set-skip-taskbar","core:window:allow-set-cursor-grab","core:window:allow-set-cursor-visible","core:window:allow-set-cursor-icon","core:window:allow-set-cursor-position","core:window:allow-set-ignore-cursor-events","core:window:allow-start-dragging","core:webview:allow-print","shell:allow-execute","shell:allow-open","dialog:allow-open","dialog:allow-save","dialog:allow-message","dialog:allow-ask","dialog:allow-confirm","http:default","notification:default","global-shortcut:allow-is-registered","global-shortcut:allow-register","global-shortcut:allow-register-all","global-shortcut:allow-unregister","global-shortcut:allow-unregister-all","os:allow-platform","os:allow-version","os:allow-os-type","os:allow-family","os:allow-arch","os:allow-exe-extension","os:allow-locale","os:allow-hostname","process:allow-restart","process:allow-exit","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text","core:app:allow-app-show","core:app:allow-app-hide","core:app:allow-set-app-theme","process:default","fs:default","dialog:default","os:default","clipboard-manager:default"]},"system-info":{"identifier":"system-info","description":"","local":true,"windows":["*"],"permissions":["system-info:allow-all"]},"valtio":{"identifier":"valtio","description":"","local":true,"windows":["*"],"permissions":["valtio:default","core:event:default"]}}

View File

@@ -2039,6 +2039,21 @@
"type": "string",
"const": "autostart:deny-is-enabled"
},
{
"description": "Allows reading the CLI matches",
"type": "string",
"const": "cli:default"
},
{
"description": "Enables the cli_matches command without any pre-configured scope.",
"type": "string",
"const": "cli:allow-cli-matches"
},
{
"description": "Denies the cli_matches command without any pre-configured scope.",
"type": "string",
"const": "cli:deny-cli-matches"
},
{
"description": "No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
"type": "string",

View File

@@ -2039,6 +2039,21 @@
"type": "string",
"const": "autostart:deny-is-enabled"
},
{
"description": "Allows reading the CLI matches",
"type": "string",
"const": "cli:default"
},
{
"description": "Enables the cli_matches command without any pre-configured scope.",
"type": "string",
"const": "cli:allow-cli-matches"
},
{
"description": "Denies the cli_matches command without any pre-configured scope.",
"type": "string",
"const": "cli:deny-cli-matches"
},
{
"description": "No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
"type": "string",

View File

@@ -54,7 +54,7 @@ pub fn get_powerplan() -> Result<i32, String> {
#[cfg(target_os = "windows")]
let powerplan = powerplan::get_powerplan()?;
#[cfg(not(target_os = "windows"))]
#[cfg(not(target_os = "windows"))]
let powerplan = powerplan::PowerPlanMode::Other.into();
Ok(powerplan)
@@ -70,7 +70,7 @@ pub fn set_powerplan(plan: i32) -> Result<(), String> {
#[tauri::command]
pub fn get_steam_users(steam_dir: &str) -> Result<Vec<preset::User>, String> {
wrap_err!(preset::get_users(steam_dir))
wrap_err!(preset::get_users(steam_dir))
}
#[tauri::command]

View File

@@ -4,12 +4,14 @@
)]
use tauri::Manager;
use tauri_plugin_deep_link::DeepLinkExt;
use tauri_plugin_autostart::MacosLauncher;
use tauri_plugin_cli::CliExt;
use tauri_plugin_deep_link::DeepLinkExt;
use tauri_plugin_store::StoreExt;
// Window Vibrancy
#[cfg(target_os = "windows")]
use window_vibrancy::apply_mica;
use window_vibrancy::apply_acrylic;
#[cfg(target_os = "macos")]
use window_vibrancy::{apply_vibrancy, NSVisualEffectMaterial};
@@ -50,7 +52,10 @@ fn main() {
.plugin(tauri_plugin_store::Builder::new().build())
.plugin(tauri_plugin_theme::init(ctx.config_mut()))
.plugin(tauri_plugin_notification::init())
.plugin(tauri_plugin_autostart::init(MacosLauncher::LaunchAgent, Some(vec![]) /* arbitrary number of args to pass to your app */))
.plugin(tauri_plugin_autostart::init(
MacosLauncher::LaunchAgent,
Some(vec!["hidden"]), /* arbitrary number of args to pass to your app */
))
.plugin(tauri_plugin_http::init())
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
@@ -60,9 +65,29 @@ fn main() {
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_system_info::init())
.plugin(tauri_plugin_cli::init())
// .plugin(tauri_plugin_store::Builder::default().build())
// .plugin(tauri_plugin_updater::Builder::new().build())
.setup(|app| {
// Get Window
let window = app.get_webview_window("main").unwrap();
let store = app.store("cstb.json")?;
// 获取boolean类型的hidden值Err时设置为False
let hidden: bool = store.get("hidden").and_then(|v| v.as_bool()).unwrap_or(false);
// Vibrant Window
#[cfg(target_os = "macos")]
apply_vibrancy(&window, NSVisualEffectMaterial::HudWindow, None, Some(10.0))
.expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS");
#[cfg(target_os = "windows")]
apply_acrylic(&window, None)
.expect("Unsupported platform! 'apply_acrylic' is only supported on Windows");
// apply_blur(&window, Some((18, 18, 18, 0)))
// .expect("Unsupported platform! 'apply_blur' is only supported on Windows");
// Deep Link
#[cfg(desktop)]
app.deep_link().register("cstb")?;
@@ -74,20 +99,22 @@ fn main() {
tray::create_tray(handle)?;
}
// Get Window
let window = app.get_webview_window("main").unwrap();
// CLI
match app.cli().matches() {
// `matches` here is a Struct with { args, subcommand }.
// `args` is `HashMap<String, ArgData>` where `ArgData` is a struct with { value, occurrences }.
// `subcommand` is `Option<Box<SubcommandMatches>>` where `SubcommandMatches` is a struct with { name, matches }.
Ok(matches) => {
println!("{:?}", matches);
if matches.args.contains_key("hidden") && matches.args["hidden"].value == true && hidden {
window.hide().unwrap();
} else {
window.show().unwrap();
}
}
Err(_) => {}
}
// Vibrant Window
#[cfg(target_os = "macos")]
apply_vibrancy(&window, NSVisualEffectMaterial::HudWindow, None, Some(10.0))
.expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS");
#[cfg(target_os = "windows")]
apply_mica(&window, Some(false))
.expect("Unsupported platform! 'apply_mica' is only supported on Windows");
// apply_blur(&window, Some((18, 18, 18, 0)))
// .expect("Unsupported platform! 'apply_blur' is only supported on Windows");
Ok(())
})
.invoke_handler(tauri::generate_handler![
@@ -100,7 +127,7 @@ fn main() {
cmds::open_path,
cmds::get_powerplan,
cmds::set_powerplan,
cmds::get_steam_users,
cmds::get_steam_users,
cmds::set_auto_login_user,
cmds::check_path,
on_button_clicked

View File

@@ -21,7 +21,6 @@ pub fn run_steam() -> std::io::Result<std::process::Output> {
.output()
}
pub fn get_exe_path(name: &str) -> Result<String, std::io::Error> {
// [原理]
// Powershell 运行 Get-Process name | Select-Object path

View File

@@ -42,4 +42,4 @@ macro_rules! wrap_err {
}
}
};
}
}

View File

@@ -1,3 +1,3 @@
pub mod common;
pub mod macros;
pub mod powerplan;
pub mod powerplan;

View File

@@ -1,12 +1,125 @@
use tauri::{
menu::{Menu, MenuItem},
menu::{CheckMenuItem, Menu, MenuItem, PredefinedMenuItem},
tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},
Manager, Runtime,
Emitter, Listener, Manager, Runtime,
};
use crate::tool::powerplan::PowerPlanMode;
pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
let quit_i = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?;
let menu = Menu::with_items(app, &[&quit_i])?;
// 托盘菜单项目
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>,
)?;
let current_launch_option = MenuItem::with_id(
app,
"current_launch_option",
"启动项档位",
true,
None::<&str>,
)?;
// 创建托盘菜单
let menu = Menu::with_items(
app,
&[
&power_plan_extreme,
&power_plan_high,
&power_plan_balanced,
&power_plan_powersave,
separator,
&current_launch_option,
launch_ww_i,
launch_pw_i,
separator,
kill_game_i,
kill_steam_i,
separator,
show_i,
quit_i,
],
)?;
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);
}
_ => {}
}
}
});
let _ = app.listen("tray://get_current_launch_option", move |event| {
let payload = event.payload();
if payload != "" {
let _ = current_launch_option.set_text("启动项档位 ".to_string() + payload);
}
});
let _ = TrayIconBuilder::with_id("tray")
.icon(app.default_window_icon().unwrap().clone())
@@ -16,7 +129,43 @@ pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
"quit" => {
app.exit(0);
}
// Add more events here
"show" => {
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::<()>);
}
"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);
}
_ => {}
})
.on_tray_icon_event(|tray, event| {
@@ -37,68 +186,3 @@ pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
Ok(())
}
// Tray Menu
// let quit = CustomMenuItem::new("quit".to_string(), "Quit");
// let hide = CustomMenuItem::new("hide".to_string(), "Hide");
// let tray_menu = SystemTrayMenu::new() // insert the menu items here
// .add_item(hide)
// .add_item(quit);
// .add_native_item(SystemTrayMenuItem::Separator)
// let toggle = MenuItemBuilder::with_id("toggle", "Toggle").build(app)?;
// let menu = MenuBuilder::new(app).items(&[&toggle]).build()?;
// Setup Tray
// let tray = tauri::tray::TrayIconBuilder::with_id("my-tray").build(app)?;
// let _ = TrayIconBuilder::new()
// .menu(&menu)
// .on_menu_event(move |_, event| {
// match event.id().as_ref() {
// "toggle" => {
// println!("toggle clicked");
// }
// _ => (),
// }
// // match event {
// // SystemTrayEvent::LeftClick { position: _, size: _, .. } => {
// // let window = app.get_window("main").unwrap();
// // window.show().unwrap();
// // window.set_focus().unwrap();
// // // thread::sleep(Duration::from_millis(100));
// // // window.set_always_on_top(false).unwrap();
// // println!("system tray received a left click");
// // }
// // SystemTrayEvent::RightClick { position: _, size: _, .. } => {
// // // let window = app.get_window("main").unwrap();
// // // window.hide().unwrap();
// // println!("system tray received a right click");
// // }
// // SystemTrayEvent::DoubleClick { position: _, size: _, .. } => {
// // println!("system tray received a double click");
// // }
// // SystemTrayEvent::MenuItemClick { id, .. } =>
// // match id.as_str() {
// // "quit" => {
// // std::process::exit(0);
// // }
// // "hide" => {
// // let window = app.get_window("main").unwrap();
// // window.hide().unwrap();
// // }
// // _ => {}
// // }
// // _ => {}
// // }
// })
// .on_tray_icon_event(|tray, event| {
// if event.click_type == ClickType::Left {
// let app = tray.app_handle();
// if let Some(webview_window) = app.get_webview_window("main") {
// let _ = webview_window.show();
// let _ = webview_window.set_focus();
// }
// }
// })
// .build(app)
// .unwrap();

View File

@@ -1,2 +1,2 @@
pub mod parse;
pub mod preset;
pub mod preset;

View File

@@ -42,7 +42,7 @@
},
"productName": "CS工具箱",
"mainBinaryName": "cstb",
"version": "0.0.5-beta.2",
"version": "0.0.5-beta.4",
"identifier": "upup.cool",
"plugins": {
"deep-link": {
@@ -51,6 +51,15 @@
"cstb"
]
}
},
"cli": {
"description": "CS Toolbox CLI",
"args": [
{
"name": "hidden",
"description": "hidden on start"
}
]
}
},
"app": {
@@ -70,7 +79,8 @@
"transparent": true,
"theme": null,
"hiddenTitle": true,
"titleBarStyle": "Transparent"
"titleBarStyle": "Transparent",
"visible": false
}
],
"security": {

View File

@@ -17,6 +17,21 @@ export default function Page() {
>
{app.state.autoStart ? "开" : "关"}
</Switch>
<Switch
isSelected={app.state.startHidden}
size="sm"
onChange={(e) => app.setStartHidden(e.target.checked)}
>
{app.state.startHidden ? "开" : "关"}
</Switch>
{/* hiddenOnClose */}
<Switch
isSelected={app.state.hiddenOnClose}
size="sm"
onChange={(e) => app.setHiddenOnClose(e.target.checked)}
>
{app.state.hiddenOnClose ? "开" : "关"}
</Switch>
</div>
)
}

View File

@@ -1,21 +1,71 @@
"use client"
import { init } from "@/store"
import { useSteamStore } from "@/store/steam"
import { useToolStore } from "@/store/tool"
import { addToast } from "@heroui/react"
import { invoke } from "@tauri-apps/api/core"
import { listen } from "@tauri-apps/api/event"
import { useDebounce } from "ahooks"
import { useEffect } from "react"
import "./globals.css"
import Providers from "./providers"
import { init } from "@/store"
import { useDebounce } from "ahooks"
import { PowerPlans } from "@/components/cstb/PowerPlan"
export default function RootLayout({ children }: { children: React.ReactNode }) {
const steam = useSteamStore()
const tool = useToolStore()
useEffect(() => {
void init()
void listen<string>("tray://launch_game", async (event) => {
await invoke("launch_game", {
steamPath: `${steam.state.steamDir}/steam.exe`,
launchOption: tool.state.launchOptions[tool.state.launchIndex].option || "",
server: event.payload || "worldwide",
})
addToast({ title: "启动国服成功" })
})
void listen("tray://kill_steam", async () => {
await invoke("kill_steam")
addToast({ title: "已关闭Steam" })
})
void listen("tray://kill_game", async () => {
await invoke("kill_game")
addToast({ title: "已关闭CS2" })
})
void listen<number>("tray://set_powerplan", async (event) => {
if (typeof(event.payload) === "number" && event.payload <= 0 && event.payload > 4) return
await invoke("set_powerplan", { plan: event.payload })
const current = await invoke<number>("get_powerplan")
tool.setPowerPlan(current)
addToast({ title: `电源计划已切换 → ${PowerPlans[current].title}` })
})
})
// 检测steam路径和游戏路径是否有效
const steam = useSteamStore()
const debounceSteamDir = useDebounce(steam.state.steamDir, {wait: 500, leading: true, trailing: true, maxWait: 2500})
const debounceCs2Dir = useDebounce(steam.state.cs2Dir, {wait: 500, leading: true, trailing: true, maxWait: 2500})
const debounceSteamDirValid = useDebounce(steam.state.steamDirValid, {wait: 500, leading: true, trailing: true, maxWait: 2500})
const debounceSteamDir = useDebounce(steam.state.steamDir, {
wait: 500,
leading: true,
trailing: true,
maxWait: 2500,
})
const debounceCs2Dir = useDebounce(steam.state.cs2Dir, {
wait: 500,
leading: true,
trailing: true,
maxWait: 2500,
})
const debounceSteamDirValid = useDebounce(steam.state.steamDirValid, {
wait: 500,
leading: true,
trailing: true,
maxWait: 2500,
})
useEffect(() => {
void steam.checkSteamDirValid()
}, [debounceSteamDir])

View File

@@ -7,7 +7,7 @@ import { Key } from "@react-types/shared"
import { useToolStore } from "@/store/tool"
import { useEffect } from "react"
const PowerPlans = [
export const PowerPlans = [
{
id: "0",
title: "其他",

View File

@@ -11,8 +11,7 @@ import {
Refresh,
RocketOne,
Square,
SunOne,
SurprisedFaceWithOpenBigMouth,
SunOne
} from "@icon-park/react"
import { type Theme, getCurrentWindow } from "@tauri-apps/api/window"
import { /* relaunch, */ exit } from "@tauri-apps/plugin-process"
@@ -21,6 +20,7 @@ import { usePathname, useRouter } from "next/navigation"
import { saveAllNow } from "@tauri-store/valtio"
import { useSteamStore } from "@/store/steam"
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from "@heroui/react"
import { window } from "@tauri-apps/api"
const Nav = () => {
const { theme, setTheme } = useTheme()
@@ -29,10 +29,12 @@ const Nav = () => {
await setTauriTheme(theme)
}
const app = useAppStore()
const close = async () => {
// (await window.hideOnClose) ? getCurrent().hide() : exit();
await saveAllNow()
await exit()
// await exit()
if (app.state.hiddenOnClose) await window.getCurrentWindow().hide()
else await exit()
}
const minimize = async () => {
@@ -52,8 +54,6 @@ const Nav = () => {
const router = useRouter()
const pathname = usePathname()
const app = useAppStore()
return (
<nav className="absolute top-0 right-0 flex flex-row h-16 gap-0.5 p-4" data-tauri-drag-region>
<Tooltip content="启动页确认设置" showArrow={true} delay={300}>

View File

@@ -55,7 +55,7 @@ const Avatar = () => {
<img
src={
steam.currentUser()?.avatar
? `data:image/png;base64,${steam.currentUser()?.avatar || ''}`
? `data:image/png;base64,${steam.currentUser()?.avatar || ""}`
: "/logo_square.png"
}
alt="avatar"
@@ -72,9 +72,10 @@ const Avatar = () => {
const SideBar = () => {
const app = useAppStore()
void getVersion().then((Value) => {
app.setVersion(Value)
})
if (typeof window !== "undefined")
void getVersion().then((Value) => {
app.setVersion(Value)
})
return (
<div

View File

@@ -1,7 +1,8 @@
import { store } from "@tauri-store/valtio"
import { useSnapshot } from "valtio"
import { DEFAULT_STORE_CONFIG } from "./config"
import { enable, isEnabled, disable } from "@tauri-apps/plugin-autostart"
import { enable, disable } from "@tauri-apps/plugin-autostart"
import { LazyStore } from '@tauri-apps/plugin-store';
const defaultValue = {
version: "0.0.1",
@@ -10,6 +11,8 @@ const defaultValue = {
notice: "",
useMirror: true,
autoStart: false,
startHidden: false,
hiddenOnClose: false,
}
export const appStore = store("app", { ...defaultValue }, DEFAULT_STORE_CONFIG)
@@ -27,10 +30,15 @@ export const useAppStore = () => {
setNotice,
setUseMirror,
setAutoStart,
setStartHidden,
setHiddenOnClose,
resetAppStore,
}
}
const launchStore = new LazyStore('cstb.json', { autoSave: true });
if (typeof window !== 'undefined') void launchStore.save()
const setVersion = (version: string) => {
appStore.state.version = version
}
@@ -56,6 +64,17 @@ const setAutoStart = (autoStart: boolean) => {
appStore.state.autoStart = autoStart
}
// 同步到 launchStore 使 start hidden 生效
const setStartHidden = async (startHidden: boolean) => {
appStore.state.startHidden = startHidden;
await launchStore.set('hidden', startHidden);
await launchStore.save();
}
const setHiddenOnClose = (hiddenOnClose: boolean) => {
appStore.state.hiddenOnClose = hiddenOnClose;
}
const resetAppStore = () => {
setVersion(defaultValue.version)
setHasUpdate(defaultValue.hasUpdate)
@@ -63,4 +82,6 @@ const resetAppStore = () => {
setNotice(defaultValue.notice)
setUseMirror(defaultValue.useMirror)
setAutoStart(defaultValue.autoStart)
void setStartHidden(defaultValue.startHidden)
setHiddenOnClose(defaultValue.hiddenOnClose)
}

View File

@@ -1,6 +1,8 @@
import { store } from "@tauri-store/valtio"
import { useSnapshot } from "valtio"
import { DEFAULT_STORE_CONFIG } from "./config"
import { emit } from "@tauri-apps/api/event"
import { send } from "process"
interface LaunchOption {
option: string
@@ -50,6 +52,13 @@ export const useToolStore = () => {
void toolStore.start
const state = useSnapshot(toolStore.state)
if (typeof window !== 'undefined') {
setTimeout(() => {
sendCurrentLaunchOptionToTray(state.launchIndex)
sendPowerPlanToTray(state.powerPlan)
}, 500)
}
return {
state,
store: toolStore,
@@ -77,10 +86,18 @@ const setLaunchOptions = (options: LaunchOption[]) => {
const setLaunchIndex = (index: number) => {
toolStore.state.launchIndex = index
sendCurrentLaunchOptionToTray(index)
}
const sendCurrentLaunchOptionToTray = (index: number) => {
void emit("tray://get_current_launch_option", toolStore.state.launchOptions[index].name || index + 1)
}
const setPowerPlan = (plan: number) => {
toolStore.state.powerPlan = plan
sendPowerPlanToTray(plan)
}
const sendPowerPlanToTray = (plan: number) => {
void emit("tray://get_powerplan", plan)
}
const setVideoSetting = (setting: VideoSetting) => {