feat: implement osu! updater command and enhance folder validation error messages
This commit is contained in:
parent
d6958dd15d
commit
9182c2c994
56
src-tauri/Cargo.lock
generated
56
src-tauri/Cargo.lock
generated
@ -100,9 +100,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-channel"
|
name = "async-channel"
|
||||||
version = "2.3.1"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
|
checksum = "16c74e56284d2188cabb6ad99603d1ace887a5d7e7b695d01b728155ed9ed427"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"event-listener-strategy",
|
"event-listener-strategy",
|
||||||
@ -1087,6 +1087,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
|
"sysinfo",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
"tauri-plugin-cors-fetch",
|
"tauri-plugin-cors-fetch",
|
||||||
@ -1095,6 +1096,7 @@ dependencies = [
|
|||||||
"tauri-plugin-shell",
|
"tauri-plugin-shell",
|
||||||
"tauri-plugin-single-instance",
|
"tauri-plugin-single-instance",
|
||||||
"tauri-plugin-sql",
|
"tauri-plugin-sql",
|
||||||
|
"winapi",
|
||||||
"winreg 0.55.0",
|
"winreg 0.55.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2008,6 +2010,17 @@ dependencies = [
|
|||||||
"cfb",
|
"cfb",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "io-uring"
|
||||||
|
version = "0.7.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.11.0"
|
version = "2.11.0"
|
||||||
@ -2429,6 +2442,15 @@ version = "0.1.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ntapi"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint-dig"
|
name = "num-bigint-dig"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
@ -2645,6 +2667,16 @@ dependencies = [
|
|||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc2-io-kit"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2-io-surface"
|
name = "objc2-io-surface"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@ -4368,6 +4400,20 @@ dependencies = [
|
|||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sysinfo"
|
||||||
|
version = "0.35.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c3ffa3e4ff2b324a57f7aeb3c349656c7b127c3c189520251a648102a92496e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"memchr",
|
||||||
|
"ntapi",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
"objc2-io-kit",
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-configuration"
|
name = "system-configuration"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
@ -4921,16 +4967,18 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.45.1"
|
version = "1.46.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779"
|
checksum = "1140bb80481756a8cbe10541f37433b459c5aa1e727b4c020fbfebdc25bf3ec4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"io-uring",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
|
"slab",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
@ -29,6 +29,8 @@ tauri-plugin-fs = "2.4.0"
|
|||||||
hardware-id = "0.3.0"
|
hardware-id = "0.3.0"
|
||||||
winreg = "0.55.0"
|
winreg = "0.55.0"
|
||||||
tauri-plugin-cors-fetch = "4.1.0"
|
tauri-plugin-cors-fetch = "4.1.0"
|
||||||
|
sysinfo = "0.35.2"
|
||||||
|
winapi = { version = "0.3", features = ["winuser"] }
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
tauri-plugin-single-instance = "2.3.0"
|
tauri-plugin-single-instance = "2.3.0"
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
use hardware_id::get_id;
|
use hardware_id::get_id;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
use sysinfo::System;
|
||||||
use winreg::RegKey;
|
use winreg::RegKey;
|
||||||
use winreg::enums::*;
|
use winreg::enums::*;
|
||||||
|
|
||||||
|
use crate::utils::get_window_title_by_pid;
|
||||||
use crate::utils::set_osu_user_config_value;
|
use crate::utils::set_osu_user_config_value;
|
||||||
use crate::utils::{check_folder_completeness, get_osu_config, get_osu_user_config};
|
use crate::utils::{check_folder_completeness, get_osu_config, get_osu_user_config};
|
||||||
|
|
||||||
@ -217,3 +222,43 @@ pub fn set_osu_config_value(
|
|||||||
) -> Result<bool, String> {
|
) -> Result<bool, String> {
|
||||||
set_osu_user_config_value(&osu_folder_path, &key, &value)
|
set_osu_user_config_value(&osu_folder_path, &key, &value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn run_osu_updater(osu_path: String) -> Result<(), String> {
|
||||||
|
let mut updater_process = Command::new(osu_path.clone())
|
||||||
|
.arg("-repair")
|
||||||
|
.spawn()
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
thread::sleep(Duration::from_millis(500));
|
||||||
|
|
||||||
|
let mut sys = System::new_all();
|
||||||
|
sys.refresh_processes(sysinfo::ProcessesToUpdate::All, true);
|
||||||
|
|
||||||
|
let mut termination_thread_running = true;
|
||||||
|
|
||||||
|
while termination_thread_running {
|
||||||
|
for (_, process) in sys.processes() {
|
||||||
|
if process.name() == "osu!.exe" {
|
||||||
|
let process_id = process.pid();
|
||||||
|
let window_title = get_window_title_by_pid(process_id);
|
||||||
|
|
||||||
|
if !window_title.is_empty() {
|
||||||
|
if let Ok(_) = process.kill_and_wait() {
|
||||||
|
termination_thread_running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !termination_thread_running {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
thread::sleep(Duration::from_millis(500));
|
||||||
|
}
|
||||||
|
|
||||||
|
updater_process.wait().map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||||
use tauri::Manager;
|
use tauri::Manager;
|
||||||
|
|
||||||
pub mod utils;
|
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
|
pub mod utils;
|
||||||
use crate::commands::{
|
use crate::commands::{
|
||||||
find_osu_installation, get_beatmapsets_count, get_hwid, get_osu_release_stream,
|
find_osu_installation, get_beatmapsets_count, get_hwid, get_osu_release_stream,
|
||||||
get_osu_version, get_skins_count, valid_osu_folder, set_osu_config_value
|
get_osu_version, get_skins_count, run_osu_updater, set_osu_config_value, valid_osu_folder,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
@ -31,7 +31,8 @@ pub fn run() {
|
|||||||
get_skins_count,
|
get_skins_count,
|
||||||
get_osu_version,
|
get_osu_version,
|
||||||
get_osu_release_stream,
|
get_osu_release_stream,
|
||||||
set_osu_config_value
|
set_osu_config_value,
|
||||||
|
run_osu_updater
|
||||||
])
|
])
|
||||||
.plugin(tauri_plugin_fs::init())
|
.plugin(tauri_plugin_fs::init())
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
|
use std::ffi::OsString;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::os::windows::ffi::OsStringExt;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::ptr;
|
||||||
|
use sysinfo::Pid;
|
||||||
|
use winapi::{
|
||||||
|
shared::minwindef::LPARAM,
|
||||||
|
um::winuser::{FindWindowW, GetWindowTextW, GetWindowThreadProcessId},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn check_folder_completeness<P: AsRef<Path>>(folder_path: P, required_files: &[&str]) -> f32 {
|
pub fn check_folder_completeness<P: AsRef<Path>>(folder_path: P, required_files: &[&str]) -> f32 {
|
||||||
let mut found = 0;
|
let mut found = 0;
|
||||||
@ -112,3 +120,28 @@ pub fn get_osu_config<P: AsRef<Path>>(
|
|||||||
|
|
||||||
return Some(config_map);
|
return Some(config_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_window_title_by_pid(pid: Pid) -> String {
|
||||||
|
let mut window_title = String::new();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let hwnd = FindWindowW(ptr::null_mut(), ptr::null_mut());
|
||||||
|
|
||||||
|
if hwnd.is_null() {
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut process_id = 0;
|
||||||
|
GetWindowThreadProcessId(hwnd, &mut process_id);
|
||||||
|
|
||||||
|
if process_id == pid.as_u32() {
|
||||||
|
let mut title = vec![0u16; 512];
|
||||||
|
let length = GetWindowTextW(hwnd, title.as_mut_ptr(), title.len() as i32);
|
||||||
|
|
||||||
|
let title = OsString::from_wide(&title[..length as usize]);
|
||||||
|
window_title = title.to_string_lossy().into_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window_title
|
||||||
|
}
|
||||||
|
@ -95,9 +95,10 @@
|
|||||||
}
|
}
|
||||||
const validFolder: boolean = await invoke('valid_osu_folder', { folder: selectedPath });
|
const validFolder: boolean = await invoke('valid_osu_folder', { folder: selectedPath });
|
||||||
if (!validFolder) {
|
if (!validFolder) {
|
||||||
toast.error(
|
toast.error('Oops...', {
|
||||||
'The selected folder is not a valid osu! installation folder. Please select the correct folder.'
|
description:
|
||||||
);
|
'The selected folder is not a valid osu! installation folder. Please select the correct folder.',
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
osuInstallationPath.set(selectedPath);
|
osuInstallationPath.set(selectedPath);
|
||||||
@ -121,8 +122,18 @@
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
launchInfo = 'Looking for updates...';
|
launchInfo = 'Validating osu! installation...';
|
||||||
launching = true;
|
launching = true;
|
||||||
|
|
||||||
|
const validFolder: boolean = await invoke('valid_osu_folder', { folder: $osuInstallationPath });
|
||||||
|
if (!validFolder) {
|
||||||
|
toast.error('Hmmm...', {
|
||||||
|
description: 'Your selected osu! installation folder is not valid.',
|
||||||
|
});
|
||||||
|
launching = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const streamInfo = await osuapi.latestBuildVersion($osuStream ?? 'stable40');
|
const streamInfo = await osuapi.latestBuildVersion($osuStream ?? 'stable40');
|
||||||
if (!streamInfo) {
|
if (!streamInfo) {
|
||||||
@ -137,6 +148,9 @@
|
|||||||
|
|
||||||
if (versions > 0) {
|
if (versions > 0) {
|
||||||
launchInfo = 'Update found!';
|
launchInfo = 'Update found!';
|
||||||
|
await new Promise((res) => setTimeout(res, 1500));
|
||||||
|
launchInfo = 'Running osu! updater...';
|
||||||
|
await invoke('run_osu_updater', { folder: $osuInstallationPath });
|
||||||
} else {
|
} else {
|
||||||
launchInfo = 'You are up to date!';
|
launchInfo = 'You are up to date!';
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user