feat: CLI
This commit is contained in:
@ -15,6 +15,7 @@
|
|||||||
"@primevue/themes": "^4.3.1",
|
"@primevue/themes": "^4.3.1",
|
||||||
"@tailwindcss/vite": "^4.0.9",
|
"@tailwindcss/vite": "^4.0.9",
|
||||||
"@tauri-apps/api": "^2.3.0",
|
"@tauri-apps/api": "^2.3.0",
|
||||||
|
"@tauri-apps/plugin-cli": "^2.2.0",
|
||||||
"@tauri-apps/plugin-deep-link": "~2.2.0",
|
"@tauri-apps/plugin-deep-link": "~2.2.0",
|
||||||
"@tauri-apps/plugin-dialog": "~2.2.0",
|
"@tauri-apps/plugin-dialog": "~2.2.0",
|
||||||
"@tauri-apps/plugin-fs": "^2.2.0",
|
"@tauri-apps/plugin-fs": "^2.2.0",
|
||||||
|
45
rust/Cargo.lock
generated
45
rust/Cargo.lock
generated
@ -727,6 +727,33 @@ dependencies = [
|
|||||||
"vec_map",
|
"vec_map",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim 0.11.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "closure"
|
name = "closure"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -4530,6 +4557,7 @@ dependencies = [
|
|||||||
"simple_logger",
|
"simple_logger",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
|
"tauri-plugin-cli",
|
||||||
"tauri-plugin-deep-link",
|
"tauri-plugin-deep-link",
|
||||||
"tauri-plugin-dialog",
|
"tauri-plugin-dialog",
|
||||||
"tauri-plugin-fs",
|
"tauri-plugin-fs",
|
||||||
@ -4590,7 +4618,7 @@ version = "0.3.26"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
|
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap 2.34.0",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"structopt-derive",
|
"structopt-derive",
|
||||||
]
|
]
|
||||||
@ -4888,6 +4916,21 @@ dependencies = [
|
|||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tauri-plugin-cli"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5458ae16eac81bdbe8d9da2a9f3e01e8cdedbc381cc1727c01127542c8a61c5"
|
||||||
|
dependencies = [
|
||||||
|
"clap 4.5.31",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tauri",
|
||||||
|
"tauri-plugin",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-deep-link"
|
name = "tauri-plugin-deep-link"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
@ -42,6 +42,7 @@ junction = "1.2.0"
|
|||||||
tauri-plugin-fs = "2"
|
tauri-plugin-fs = "2"
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
|
tauri-plugin-cli = "2"
|
||||||
tauri-plugin-single-instance = { version = "2", features = ["deep-link"] }
|
tauri-plugin-single-instance = { version = "2", features = ["deep-link"] }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
|
14
rust/capabilities/desktop.json
Normal file
14
rust/capabilities/desktop.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"identifier": "desktop-capability",
|
||||||
|
"platforms": [
|
||||||
|
"macOS",
|
||||||
|
"windows",
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"windows": [
|
||||||
|
"main"
|
||||||
|
],
|
||||||
|
"permissions": [
|
||||||
|
"cli:default"
|
||||||
|
]
|
||||||
|
}
|
@ -15,6 +15,7 @@ pub struct AppData {
|
|||||||
pub profile: Option<Profile>,
|
pub profile: Option<Profile>,
|
||||||
pub pkgs: PackageStore,
|
pub pkgs: PackageStore,
|
||||||
pub cfg: GlobalConfig,
|
pub cfg: GlobalConfig,
|
||||||
|
pub remain_open: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppData {
|
impl AppData {
|
||||||
@ -32,6 +33,7 @@ impl AppData {
|
|||||||
profile,
|
profile,
|
||||||
pkgs: PackageStore::new(apph.clone()),
|
pkgs: PackageStore::new(apph.clone()),
|
||||||
cfg,
|
cfg,
|
||||||
|
remain_open: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,18 +10,20 @@ mod download_handler;
|
|||||||
mod appdata;
|
mod appdata;
|
||||||
mod display;
|
mod display;
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use closure::closure;
|
use closure::closure;
|
||||||
use appdata::AppData;
|
use appdata::AppData;
|
||||||
|
use model::misc::Game;
|
||||||
use pkg::PkgKey;
|
use pkg::PkgKey;
|
||||||
use profile::Profile;
|
use profile::Profile;
|
||||||
use tauri::{Listener, Manager};
|
use tauri::{Listener, Manager};
|
||||||
use tauri_plugin_deep_link::DeepLinkExt;
|
use tauri_plugin_deep_link::DeepLinkExt;
|
||||||
|
use tauri_plugin_cli::CliExt;
|
||||||
use tokio::{sync::Mutex, fs, try_join};
|
use tokio::{sync::Mutex, fs, try_join};
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub async fn run(_args: Vec<String>) {
|
pub async fn run(_args: Vec<String>) {
|
||||||
simple_logger::init_with_env()
|
simple_logger::init_with_env().expect("Unable to initialize the logger");
|
||||||
.expect("Unable to initialize the logger");
|
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"Running from {}",
|
"Running from {}",
|
||||||
@ -62,6 +64,7 @@ pub async fn run(_args: Vec<String>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
.plugin(tauri_plugin_cli::init())
|
||||||
.plugin(tauri_plugin_fs::init())
|
.plugin(tauri_plugin_fs::init())
|
||||||
.plugin(tauri_plugin_deep_link::init())
|
.plugin(tauri_plugin_deep_link::init())
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
@ -72,7 +75,38 @@ pub async fn run(_args: Vec<String>) {
|
|||||||
|
|
||||||
util::init_dirs(&apph);
|
util::init_dirs(&apph);
|
||||||
|
|
||||||
let app_data = AppData::new(app.handle().clone());
|
let mut app_data = AppData::new(app.handle().clone());
|
||||||
|
let start_immediately;
|
||||||
|
|
||||||
|
if let Ok(matches) = app.cli().matches() {
|
||||||
|
let start_arg = matches.args.get("start").expect("Invalid argument configuration");
|
||||||
|
let game_arg = matches.args.get("game").expect("Invalid argument configuration");
|
||||||
|
let name_arg = matches.args.get("name").expect("Invalid argument configuration");
|
||||||
|
log::debug!("{:?} {:?} {:?}", start_arg, game_arg, name_arg);
|
||||||
|
if start_arg.occurrences > 0 {
|
||||||
|
start_immediately = true;
|
||||||
|
app_data.remain_open = false;
|
||||||
|
} else {
|
||||||
|
tauri::WebviewWindowBuilder::new(app, "main", tauri::WebviewUrl::App("index.html".into()))
|
||||||
|
.title("STARTLINER")
|
||||||
|
.inner_size(600f64, 500f64)
|
||||||
|
.min_inner_size(600f64, 500f64)
|
||||||
|
.build()?;
|
||||||
|
start_immediately = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if game_arg.occurrences == 1 && name_arg.occurrences == 1 {
|
||||||
|
let game = game_arg.value.as_str().unwrap();
|
||||||
|
let name = name_arg.value.as_str().unwrap();
|
||||||
|
|
||||||
|
app_data.switch_profile(
|
||||||
|
Game::from_str(game).ok_or_else(|| anyhow!("Invalid game"))?,
|
||||||
|
name.to_owned()
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(anyhow!("Invalid command line arguments").into());
|
||||||
|
}
|
||||||
|
|
||||||
app.manage(Mutex::new(app_data));
|
app.manage(Mutex::new(app_data));
|
||||||
app.deep_link().register_all()?;
|
app.deep_link().register_all()?;
|
||||||
@ -103,6 +137,36 @@ pub async fn run(_args: Vec<String>) {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
app.listen("launch-end", closure!(clone apph, |_| {
|
||||||
|
let apph = apph.clone();
|
||||||
|
tauri::async_runtime::spawn(async move {
|
||||||
|
let mutex = apph.state::<Mutex<AppData>>();
|
||||||
|
let appd = mutex.lock().await;
|
||||||
|
if !appd.remain_open {
|
||||||
|
apph.exit(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
if start_immediately == true {
|
||||||
|
let apph_clone = apph.clone();
|
||||||
|
tauri::async_runtime::spawn(async {
|
||||||
|
let apph_clone_clone = apph_clone.clone();
|
||||||
|
{
|
||||||
|
let mtx = apph_clone.state::<Mutex<AppData>>();
|
||||||
|
let mut appd = mtx.lock().await;
|
||||||
|
if let Err(e) = appd.pkgs.reload_all().await {
|
||||||
|
log::error!("Unable to reload packages: {}", e);
|
||||||
|
apph_clone.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Err(e) = cmd::startline(apph_clone).await {
|
||||||
|
log::error!("Unable to launch: {}", e);
|
||||||
|
apph_clone_clone.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
@ -110,6 +110,8 @@ pub async fn start(p: &Profile, app: AppHandle) -> Result<()> {
|
|||||||
amd_builder.env("OPENSSL_ia32cap", ":~0x20000000");
|
amd_builder.env("OPENSSL_ia32cap", ":~0x20000000");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pkill("amdaemon.exe").await;
|
||||||
|
|
||||||
log::info!("Launching amdaemon: {:?}", amd_builder);
|
log::info!("Launching amdaemon: {:?}", amd_builder);
|
||||||
log::info!("Launching mu3: {:?}", game_builder);
|
log::info!("Launching mu3: {:?}", game_builder);
|
||||||
|
|
||||||
@ -127,7 +129,9 @@ pub async fn start(p: &Profile, app: AppHandle) -> Result<()> {
|
|||||||
(game.wait().await.expect("mu3 failed to run"), "mu3.exe")
|
(game.wait().await.expect("mu3 failed to run"), "mu3.exe")
|
||||||
});
|
});
|
||||||
|
|
||||||
_ = app.emit("launch-start", "");
|
if let Err(e) = app.emit("launch-start", "") {
|
||||||
|
log::warn!("Unable to emit launch-start: {}", e);
|
||||||
|
}
|
||||||
|
|
||||||
let (rc, process_name) = set.join_next().await.expect("No spawn").expect("No result");
|
let (rc, process_name) = set.join_next().await.expect("No spawn").expect("No result");
|
||||||
|
|
||||||
@ -143,7 +147,9 @@ pub async fn start(p: &Profile, app: AppHandle) -> Result<()> {
|
|||||||
|
|
||||||
log::debug!("Fin");
|
log::debug!("Fin");
|
||||||
|
|
||||||
_ = app.emit("launch-end", "");
|
if let Err(e) = app.emit("launch-start", "") {
|
||||||
|
log::warn!("Unable to emit launch-end: {}", e);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
||||||
|
@ -17,18 +17,33 @@
|
|||||||
"desktop": {
|
"desktop": {
|
||||||
"schemes": ["rainycolor"]
|
"schemes": ["rainycolor"]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"cli": {
|
||||||
|
"description": "STARTLINER CLI",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"short": "s",
|
||||||
|
"name": "start",
|
||||||
|
"description": "Just start"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"short": "g",
|
||||||
|
"name": "game",
|
||||||
|
"description": "Game",
|
||||||
|
"takesValue": true,
|
||||||
|
"possibleValues": ["chunithm", "ongeki"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"short": "n",
|
||||||
|
"name": "name",
|
||||||
|
"takesValue": true,
|
||||||
|
"description": "Profile name"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"windows": [
|
"windows": [],
|
||||||
{
|
|
||||||
"title": "STARTLINER",
|
|
||||||
"width": 600,
|
|
||||||
"height": 500,
|
|
||||||
"minWidth": 600,
|
|
||||||
"minHeight": 500
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"security": {
|
"security": {
|
||||||
"csp": {
|
"csp": {
|
||||||
"img-src": "'self' asset: https: http://asset.localhost blob: data:"
|
"img-src": "'self' asset: https: http://asset.localhost blob: data:"
|
||||||
|
Reference in New Issue
Block a user