chore: add file downloading for ezpplauncher files, add ui replacement
This commit is contained in:
parent
41608afae2
commit
7e524debb9
153
src-tauri/Cargo.lock
generated
153
src-tauri/Cargo.lock
generated
@ -622,7 +622,7 @@ dependencies = [
|
|||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"core-foundation 0.10.1",
|
"core-foundation 0.10.1",
|
||||||
"core-graphics-types",
|
"core-graphics-types",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1084,6 +1084,8 @@ name = "ezpplauncher"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hardware-id",
|
"hardware-id",
|
||||||
|
"md5",
|
||||||
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
@ -1096,6 +1098,7 @@ dependencies = [
|
|||||||
"tauri-plugin-shell",
|
"tauri-plugin-shell",
|
||||||
"tauri-plugin-single-instance",
|
"tauri-plugin-single-instance",
|
||||||
"tauri-plugin-sql",
|
"tauri-plugin-sql",
|
||||||
|
"tokio",
|
||||||
"winapi",
|
"winapi",
|
||||||
"winreg 0.55.0",
|
"winreg 0.55.0",
|
||||||
]
|
]
|
||||||
@ -1158,6 +1161,15 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
dependencies = [
|
||||||
|
"foreign-types-shared 0.1.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foreign-types"
|
name = "foreign-types"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@ -1165,7 +1177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
|
checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"foreign-types-macros",
|
"foreign-types-macros",
|
||||||
"foreign-types-shared",
|
"foreign-types-shared 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1179,6 +1191,12 @@ dependencies = [
|
|||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types-shared"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foreign-types-shared"
|
name = "foreign-types-shared"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@ -1806,6 +1824,22 @@ dependencies = [
|
|||||||
"webpki-roots",
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper-tls"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper",
|
||||||
|
"hyper-util",
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-util"
|
||||||
version = "0.1.14"
|
version = "0.1.14"
|
||||||
@ -2324,6 +2358,12 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "md5"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.5"
|
version = "2.7.5"
|
||||||
@ -2387,6 +2427,23 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "native-tls"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"openssl",
|
||||||
|
"openssl-probe",
|
||||||
|
"openssl-sys",
|
||||||
|
"schannel",
|
||||||
|
"security-framework",
|
||||||
|
"security-framework-sys",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -2777,6 +2834,50 @@ dependencies = [
|
|||||||
"pathdiff",
|
"pathdiff",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.10.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"cfg-if",
|
||||||
|
"foreign-types 0.3.2",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"openssl-macros",
|
||||||
|
"openssl-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.104",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-probe"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "option-ext"
|
name = "option-ext"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -3499,10 +3600,12 @@ dependencies = [
|
|||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
|
"hyper-tls",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"mime",
|
"mime",
|
||||||
|
"native-tls",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"quinn",
|
"quinn",
|
||||||
@ -3513,6 +3616,7 @@ dependencies = [
|
|||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tower",
|
"tower",
|
||||||
@ -3675,6 +3779,15 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schannel"
|
||||||
|
version = "0.1.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schemars"
|
name = "schemars"
|
||||||
version = "0.8.22"
|
version = "0.8.22"
|
||||||
@ -3732,6 +3845,29 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "2.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.9.1",
|
||||||
|
"core-foundation 0.9.4",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework-sys"
|
||||||
|
version = "2.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "selectors"
|
name = "selectors"
|
||||||
version = "0.24.0"
|
version = "0.24.0"
|
||||||
@ -4040,7 +4176,7 @@ dependencies = [
|
|||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"core-graphics",
|
"core-graphics",
|
||||||
"foreign-types",
|
"foreign-types 0.5.0",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"objc2 0.5.2",
|
"objc2 0.5.2",
|
||||||
@ -4976,6 +5112,7 @@ dependencies = [
|
|||||||
"io-uring",
|
"io-uring",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"slab",
|
"slab",
|
||||||
@ -4996,6 +5133,16 @@ dependencies = [
|
|||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-native-tls"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
|
||||||
|
dependencies = [
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-rustls"
|
name = "tokio-rustls"
|
||||||
version = "0.26.2"
|
version = "0.26.2"
|
||||||
|
@ -31,6 +31,9 @@ winreg = "0.55.0"
|
|||||||
tauri-plugin-cors-fetch = "4.1.0"
|
tauri-plugin-cors-fetch = "4.1.0"
|
||||||
sysinfo = "0.35.2"
|
sysinfo = "0.35.2"
|
||||||
winapi = { version = "0.3", features = ["winuser"] }
|
winapi = { version = "0.3", features = ["winuser"] }
|
||||||
|
reqwest = { version = "0.12.22", features = ["json", "stream"] }
|
||||||
|
md5 = "0.8.0"
|
||||||
|
tokio = { version = "1.46.0", features = ["full"] }
|
||||||
|
|
||||||
[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,9 +1,16 @@
|
|||||||
use hardware_id::get_id;
|
use hardware_id::get_id;
|
||||||
|
use reqwest::Client;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use sysinfo::System;
|
use sysinfo::System;
|
||||||
|
use tauri::AppHandle;
|
||||||
|
use tauri::Emitter;
|
||||||
|
use tokio::fs;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
use winreg::RegKey;
|
use winreg::RegKey;
|
||||||
use winreg::enums::*;
|
use winreg::enums::*;
|
||||||
|
|
||||||
@ -368,3 +375,199 @@ pub fn run_osu(folder: String) -> Result<(), String> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct UpdateFile {
|
||||||
|
pub name: String,
|
||||||
|
pub folder: String,
|
||||||
|
pub url: String,
|
||||||
|
pub size: usize,
|
||||||
|
pub md5: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_ezpp_launcher_update_files(
|
||||||
|
folder: String,
|
||||||
|
update_url: String,
|
||||||
|
) -> Result<(Vec<UpdateFile>, Vec<UpdateFile>), String> {
|
||||||
|
let osu_path = PathBuf::from(folder);
|
||||||
|
let client = Client::new();
|
||||||
|
|
||||||
|
let update_files = client
|
||||||
|
.patch(update_url)
|
||||||
|
.header("User-Agent", "EZPPLauncher")
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
.json::<Vec<UpdateFile>>()
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let mut files_to_download = Vec::new();
|
||||||
|
|
||||||
|
for file in &update_files {
|
||||||
|
let file_path = osu_path.join(&file.folder).join(&file.name);
|
||||||
|
if file_path.exists() {
|
||||||
|
let data = fs::read(&file_path).await.map_err(|e| e.to_string())?;
|
||||||
|
let hash = format!("{:x}", md5::compute(&data));
|
||||||
|
if hash.to_lowercase() != file.md5.to_lowercase() {
|
||||||
|
files_to_download.push(file.clone());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
files_to_download.push(file.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((files_to_download, update_files))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct UpdateStatus {
|
||||||
|
pub file_name: String,
|
||||||
|
pub downloaded: u64,
|
||||||
|
pub size: usize,
|
||||||
|
pub progress: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn download_ezpp_launcher_update_files(
|
||||||
|
app: AppHandle,
|
||||||
|
folder: String,
|
||||||
|
update_files: Vec<UpdateFile>,
|
||||||
|
all_files: Vec<UpdateFile>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let osu_path = PathBuf::from(folder);
|
||||||
|
let client = Client::new();
|
||||||
|
|
||||||
|
let valid_paths: HashSet<PathBuf> = all_files
|
||||||
|
.iter()
|
||||||
|
.map(|f| osu_path.join(&f.folder).join(&f.name))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for folder in all_files
|
||||||
|
.iter()
|
||||||
|
.map(|f| osu_path.join(&f.folder))
|
||||||
|
.collect::<HashSet<_>>()
|
||||||
|
{
|
||||||
|
if folder.exists() && folder != osu_path {
|
||||||
|
let mut dir = fs::read_dir(&folder).await.map_err(|e| e.to_string())?;
|
||||||
|
while let Some(entry) = dir.next_entry().await.map_err(|e| e.to_string())? {
|
||||||
|
let path = entry.path();
|
||||||
|
if !valid_paths.contains(&path) {
|
||||||
|
fs::remove_file(&path).await.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for file in update_files {
|
||||||
|
let file_path = osu_path.join(&file.folder).join(&file.name);
|
||||||
|
let parent = file_path.parent().unwrap();
|
||||||
|
if !parent.exists() {
|
||||||
|
fs::create_dir_all(parent)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut response = client
|
||||||
|
.get(&file.url)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let mut file_out = fs::File::create(&file_path)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
let mut downloaded = 0u64;
|
||||||
|
|
||||||
|
while let Some(chunk) = response.chunk().await.map_err(|e| e.to_string())? {
|
||||||
|
downloaded += chunk.len() as u64;
|
||||||
|
file_out
|
||||||
|
.write_all(&chunk)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
// Emit progress to frontend
|
||||||
|
app.emit(
|
||||||
|
"download-progress",
|
||||||
|
UpdateStatus {
|
||||||
|
file_name: file.name.clone(),
|
||||||
|
downloaded,
|
||||||
|
size: file.size,
|
||||||
|
progress: ((downloaded as f64 / file.size as f64 * 100.0) * 100.0).trunc()
|
||||||
|
/ 100.0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap_or_default();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
#[serde(tag = "type", content = "details")]
|
||||||
|
pub enum ReplaceUIError {
|
||||||
|
FileNotFound(String),
|
||||||
|
PermissionDenied(String),
|
||||||
|
IoError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn replace_ui_files(folder: String, revert: bool) -> Result<(), ReplaceUIError> {
|
||||||
|
let osu_path = PathBuf::from(folder);
|
||||||
|
let ezpp_ui = osu_path.join("EZPPLauncher").join("ezpp!ui.dll");
|
||||||
|
let osu_ui = osu_path.join("osu!ui.dll");
|
||||||
|
let ezpp_gameplay = osu_path.join("EZPPLauncher").join("ezpp!gameplay.dll");
|
||||||
|
let osu_gameplay = osu_path.join("osu!gameplay.dll");
|
||||||
|
|
||||||
|
let osu_ui_bak = osu_path.join("osu!ui.dll.bak");
|
||||||
|
let osu_gameplay_bak = osu_path.join("osu!gameplay.dll.bak");
|
||||||
|
|
||||||
|
let try_rename = |from: &PathBuf, to: &PathBuf| -> Result<(), ReplaceUIError> {
|
||||||
|
if !from.exists() {
|
||||||
|
return Err(ReplaceUIError::FileNotFound(from.display().to_string()));
|
||||||
|
}
|
||||||
|
std::fs::rename(from, to).map_err(|e| match e.kind() {
|
||||||
|
std::io::ErrorKind::NotFound => {
|
||||||
|
ReplaceUIError::FileNotFound(from.display().to_string())
|
||||||
|
}
|
||||||
|
std::io::ErrorKind::PermissionDenied => {
|
||||||
|
ReplaceUIError::PermissionDenied(from.display().to_string())
|
||||||
|
}
|
||||||
|
_ => ReplaceUIError::IoError(e.to_string()),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
if !revert {
|
||||||
|
try_rename(&osu_ui, &osu_ui_bak)?;
|
||||||
|
try_rename(&ezpp_ui, &osu_ui)?;
|
||||||
|
|
||||||
|
try_rename(&osu_gameplay, &osu_gameplay_bak)?;
|
||||||
|
try_rename(&ezpp_gameplay, &osu_gameplay)?;
|
||||||
|
} else {
|
||||||
|
try_rename(&osu_ui, &ezpp_ui)?;
|
||||||
|
try_rename(&osu_ui_bak, &osu_ui)?;
|
||||||
|
|
||||||
|
try_rename(&osu_gameplay, &ezpp_gameplay)?;
|
||||||
|
try_rename(&osu_gameplay_bak, &osu_gameplay)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn is_osu_running() -> bool {
|
||||||
|
let mut sys = System::new_all();
|
||||||
|
sys.refresh_processes(sysinfo::ProcessesToUpdate::All, true);
|
||||||
|
|
||||||
|
for process in sys.processes().values() {
|
||||||
|
if process.name().eq_ignore_ascii_case("osu!.exe") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
@ -4,9 +4,10 @@ use tauri::Manager;
|
|||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
use crate::commands::{
|
use crate::commands::{
|
||||||
find_osu_installation, get_beatmapsets_count, get_hwid, get_osu_release_stream,
|
download_ezpp_launcher_update_files, find_osu_installation, get_beatmapsets_count,
|
||||||
get_osu_version, get_skins_count, run_osu, run_osu_updater, set_osu_config_values,
|
get_ezpp_launcher_update_files, get_hwid, get_osu_release_stream, get_osu_skin,
|
||||||
set_osu_user_config_values, valid_osu_folder, get_osu_skin
|
get_osu_version, get_skins_count, replace_ui_files, run_osu, run_osu_updater,
|
||||||
|
set_osu_config_values, set_osu_user_config_values, valid_osu_folder, is_osu_running
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
@ -36,7 +37,11 @@ pub fn run() {
|
|||||||
set_osu_user_config_values,
|
set_osu_user_config_values,
|
||||||
run_osu_updater,
|
run_osu_updater,
|
||||||
run_osu,
|
run_osu,
|
||||||
get_osu_skin
|
get_osu_skin,
|
||||||
|
get_ezpp_launcher_update_files,
|
||||||
|
download_ezpp_launcher_update_files,
|
||||||
|
replace_ui_files,
|
||||||
|
is_osu_running
|
||||||
])
|
])
|
||||||
.plugin(tauri_plugin_fs::init())
|
.plugin(tauri_plugin_fs::init())
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { exists, mkdir, readTextFile, writeFile } from '@tauri-apps/plugin-fs';
|
import { exists, mkdir, readTextFile, writeFile } from '@tauri-apps/plugin-fs';
|
||||||
import * as path from '@tauri-apps/api/path';
|
import * as path from '@tauri-apps/api/path';
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
|
||||||
import { Crypto } from './crypto';
|
import { Crypto } from './crypto';
|
||||||
|
import { getHWID } from './osuUtil';
|
||||||
|
|
||||||
export class Config {
|
export class Config {
|
||||||
private fileName: string;
|
private fileName: string;
|
||||||
@ -16,7 +16,7 @@ export class Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async init(): Promise<boolean> {
|
async init(): Promise<boolean> {
|
||||||
const hwid: string = (await invoke('get_hwid')) ?? 'recorderinsandybridge';
|
const hwid = (await getHWID()) ?? 'recorderinsandybridge';
|
||||||
|
|
||||||
this.crypto = new Crypto(hwid);
|
this.crypto = new Crypto(hwid);
|
||||||
|
|
||||||
|
@ -1,4 +1,23 @@
|
|||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
|
import type { UpdateFile, UpdateStatus } from './types';
|
||||||
|
import { listen } from '@tauri-apps/api/event';
|
||||||
|
|
||||||
|
const updateUrl = 'https://ez-pp.farm/ezpplauncher';
|
||||||
|
|
||||||
|
export const getHWID = async () => {
|
||||||
|
const hwid = await invoke('get_hwid');
|
||||||
|
return typeof hwid === 'string' ? hwid : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isValidOsuFolder = async (folder: string): Promise<boolean> => {
|
||||||
|
const result = await invoke('valid_osu_folder', { folder });
|
||||||
|
return typeof result === 'boolean' ? result : false;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const autoDetectOsuInstallFolder = async () => {
|
||||||
|
const result = await invoke('find_osu_installation');
|
||||||
|
return typeof result === 'string' ? result : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
export const setUserConfigValues = async (
|
export const setUserConfigValues = async (
|
||||||
osuFolderPath: string,
|
osuFolderPath: string,
|
||||||
@ -22,3 +41,71 @@ export const getReleaseStream = async (folder: string) => {
|
|||||||
const result = await invoke('get_osu_release_stream', { folder });
|
const result = await invoke('get_osu_release_stream', { folder });
|
||||||
return typeof result === 'string' ? result : undefined;
|
return typeof result === 'string' ? result : undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getVersion = async (folder: string) => {
|
||||||
|
const result = await invoke('get_osu_version', { folder });
|
||||||
|
return typeof result === 'string' ? result : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getBeatmapSetsCount = async (folder: string) => {
|
||||||
|
const result = await invoke('get_beatmapsets_count', {
|
||||||
|
folder,
|
||||||
|
});
|
||||||
|
return typeof result === 'number' ? result : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getSkinsCount = async (folder: string) => {
|
||||||
|
const result = await invoke('get_skins_count', {
|
||||||
|
folder,
|
||||||
|
});
|
||||||
|
return typeof result === 'number' ? result : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getSkin = async (folder: string) => {
|
||||||
|
const result = await invoke('get_osu_skin', {
|
||||||
|
folder,
|
||||||
|
});
|
||||||
|
|
||||||
|
return typeof result === 'string' ? result : 'Default';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const runUpdater = async (folder: string) => await invoke('run_osu_updater', { folder });
|
||||||
|
export const runOsu = async (folder: string) => await invoke('run_osu', { folder });
|
||||||
|
|
||||||
|
export const getEZPPLauncherUpdateFiles = async (folder: string) => {
|
||||||
|
const result = await invoke('get_ezpp_launcher_update_files', { folder, updateUrl });
|
||||||
|
if (typeof result === 'object') {
|
||||||
|
const [filesToDownload, updateFiles] = result as [UpdateFile[], UpdateFile[]];
|
||||||
|
return {
|
||||||
|
filesToDownload,
|
||||||
|
updateFiles,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const downloadEZPPLauncherUpdateFiles = async (
|
||||||
|
folder: string,
|
||||||
|
updateFiles: UpdateFile[],
|
||||||
|
allFiles: UpdateFile[],
|
||||||
|
progressCallback: (file: UpdateStatus) => void
|
||||||
|
) => {
|
||||||
|
const downloadStatusListen = await listen('download-progress', (event) =>
|
||||||
|
progressCallback(event.payload as UpdateStatus)
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
await invoke('download_ezpp_launcher_update_files', { folder, updateFiles, allFiles });
|
||||||
|
} finally {
|
||||||
|
downloadStatusListen();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const replaceUIFiles = async (folder: string, revert: boolean) => {
|
||||||
|
await invoke('replace_ui_files', { folder, revert });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isOsuRunning = async () => {
|
||||||
|
const result = await invoke('is_osu_running');
|
||||||
|
return typeof result === 'boolean' ? result : false;
|
||||||
|
};
|
||||||
|
@ -119,3 +119,18 @@ export type StreamsResult = {
|
|||||||
user_count: number;
|
user_count: number;
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type UpdateFile = {
|
||||||
|
folder: string;
|
||||||
|
md5: string;
|
||||||
|
name: string;
|
||||||
|
size: number;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UpdateStatus = {
|
||||||
|
fileName: string;
|
||||||
|
downloaded: number;
|
||||||
|
size: number;
|
||||||
|
progress: number;
|
||||||
|
};
|
||||||
|
@ -81,3 +81,15 @@ export const compareBuildNumbers = (current: string, target: string): number =>
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatBytes = (bytes: number, decimals = 2) => {
|
||||||
|
if (!bytes) return '0 B';
|
||||||
|
|
||||||
|
const k = 1024;
|
||||||
|
const dm = decimals < 0 ? 0 : decimals;
|
||||||
|
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
|
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
|
||||||
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))}${sizes[i]}`;
|
||||||
|
};
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
import Progress from '@/components/ui/progress/progress.svelte';
|
import Progress from '@/components/ui/progress/progress.svelte';
|
||||||
import {
|
import {
|
||||||
compareBuildNumbers,
|
compareBuildNumbers,
|
||||||
|
formatBytes,
|
||||||
formatTimeReadable,
|
formatTimeReadable,
|
||||||
numberHumanReadable,
|
numberHumanReadable,
|
||||||
releaseStreamToReadable,
|
releaseStreamToReadable,
|
||||||
@ -55,7 +56,6 @@
|
|||||||
} from '@/userSettings';
|
} from '@/userSettings';
|
||||||
import Input from '@/components/ui/input/input.svelte';
|
import Input from '@/components/ui/input/input.svelte';
|
||||||
import { open } from '@tauri-apps/plugin-dialog';
|
import { open } from '@tauri-apps/plugin-dialog';
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import Login from './Login.svelte';
|
import Login from './Login.svelte';
|
||||||
import { currentUser, userAuth } from '@/userAuthentication';
|
import { currentUser, userAuth } from '@/userAuthentication';
|
||||||
@ -69,10 +69,26 @@
|
|||||||
} from '@/gamemode';
|
} from '@/gamemode';
|
||||||
import { currentUserInfo } from '@/data';
|
import { currentUserInfo } from '@/data';
|
||||||
import { osuapi } from '@/api/osuapi';
|
import { osuapi } from '@/api/osuapi';
|
||||||
import { getReleaseStream, setConfigValues, setUserConfigValues } from '@/osuUtil';
|
import {
|
||||||
|
downloadEZPPLauncherUpdateFiles,
|
||||||
|
getBeatmapSetsCount,
|
||||||
|
getEZPPLauncherUpdateFiles,
|
||||||
|
getReleaseStream,
|
||||||
|
getSkin,
|
||||||
|
getSkinsCount,
|
||||||
|
getVersion,
|
||||||
|
isOsuRunning,
|
||||||
|
isValidOsuFolder,
|
||||||
|
replaceUIFiles,
|
||||||
|
runOsu,
|
||||||
|
runUpdater,
|
||||||
|
setConfigValues,
|
||||||
|
setUserConfigValues,
|
||||||
|
} from '@/osuUtil';
|
||||||
import { getCurrentWindow } from '@tauri-apps/api/window';
|
import { getCurrentWindow } from '@tauri-apps/api/window';
|
||||||
|
|
||||||
let selectedTab = $state('home');
|
let selectedTab = $state('home');
|
||||||
|
let progress = $state(-1);
|
||||||
let launchInfo = $state('');
|
let launchInfo = $state('');
|
||||||
|
|
||||||
let selectedGamemode = $derived(
|
let selectedGamemode = $derived(
|
||||||
@ -96,7 +112,7 @@
|
|||||||
if (selectedPath === $osuInstallationPath) {
|
if (selectedPath === $osuInstallationPath) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const validFolder: boolean = await invoke('valid_osu_folder', { folder: selectedPath });
|
const validFolder = await isValidOsuFolder(selectedPath);
|
||||||
if (!validFolder) {
|
if (!validFolder) {
|
||||||
toast.error('Oops...', {
|
toast.error('Oops...', {
|
||||||
description:
|
description:
|
||||||
@ -109,27 +125,29 @@
|
|||||||
$userSettings.save();
|
$userSettings.save();
|
||||||
toast.success('osu! installation path set successfully.');
|
toast.success('osu! installation path set successfully.');
|
||||||
|
|
||||||
const beatmapSetCount: number | null = await invoke('get_beatmapsets_count', {
|
const beatmapSetCount: number | null = await getBeatmapSetsCount(selectedPath);
|
||||||
folder: selectedPath,
|
|
||||||
});
|
|
||||||
if (beatmapSetCount) {
|
if (beatmapSetCount) {
|
||||||
beatmapSets.set(beatmapSetCount);
|
beatmapSets.set(beatmapSetCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
const skinsCount: number | null = await invoke('get_skins_count', {
|
const skinsCount: number | null = await getSkinsCount(selectedPath);
|
||||||
folder: selectedPath,
|
|
||||||
});
|
|
||||||
if (skinsCount) {
|
if (skinsCount) {
|
||||||
skins.set(skinsCount);
|
skins.set(skinsCount);
|
||||||
}
|
}
|
||||||
const skin: string = await invoke('get_osu_skin', {
|
const skin: string = await getSkin(selectedPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
currentSkin.set(skin);
|
currentSkin.set(skin);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const launch = async (offline: boolean) => {
|
const launch = async (offline: boolean) => {
|
||||||
|
const osuRunning = await isOsuRunning();
|
||||||
|
if (osuRunning) {
|
||||||
|
toast.error('Hold on a second!', {
|
||||||
|
description:
|
||||||
|
'osu! is currently running, please exit osu! before launching via EZPPLauncher!',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!$osuBuild) {
|
if (!$osuBuild) {
|
||||||
toast.error('Hmmm...', {
|
toast.error('Hmmm...', {
|
||||||
description: 'There was an issue detecting your installed osu! version',
|
description: 'There was an issue detecting your installed osu! version',
|
||||||
@ -137,10 +155,11 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const osuPath = $osuInstallationPath;
|
const osuPath = $osuInstallationPath;
|
||||||
|
|
||||||
launchInfo = 'Validating osu! installation...';
|
launchInfo = 'Validating osu! installation...';
|
||||||
launching.set(true);
|
launching.set(true);
|
||||||
|
|
||||||
const validFolder: boolean = await invoke('valid_osu_folder', { folder: osuPath });
|
const validFolder = await isValidOsuFolder(osuPath);
|
||||||
if (!validFolder) {
|
if (!validFolder) {
|
||||||
toast.error('Hmmm...', {
|
toast.error('Hmmm...', {
|
||||||
description: 'Your selected osu! installation folder is not valid.',
|
description: 'Your selected osu! installation folder is not valid.',
|
||||||
@ -149,6 +168,34 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
launchInfo = 'Looking for EZPPLauncher File updates...';
|
||||||
|
const updateResult = await getEZPPLauncherUpdateFiles(osuPath);
|
||||||
|
if (updateResult) {
|
||||||
|
if (updateResult.filesToDownload.length > 0) {
|
||||||
|
launchInfo = 'Found EZPPLauncher File updates!';
|
||||||
|
await new Promise((res) => setTimeout(res, 1000));
|
||||||
|
await downloadEZPPLauncherUpdateFiles(
|
||||||
|
osuPath,
|
||||||
|
updateResult.filesToDownload,
|
||||||
|
updateResult.updateFiles,
|
||||||
|
(file) => {
|
||||||
|
progress = file.progress;
|
||||||
|
launchInfo = `Downloading ${file.fileName}(${formatBytes(
|
||||||
|
file.downloaded
|
||||||
|
)}/${formatBytes(file.size)})...`;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
progress = -1;
|
||||||
|
} else {
|
||||||
|
launchInfo = 'EZPPLauncher Files are up to date!';
|
||||||
|
await new Promise((res) => setTimeout(res, 1500));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const streamInfo = await osuapi.latestBuildVersion('stable40');
|
const streamInfo = await osuapi.latestBuildVersion('stable40');
|
||||||
if (!streamInfo) {
|
if (!streamInfo) {
|
||||||
@ -181,7 +228,7 @@
|
|||||||
]);
|
]);
|
||||||
osuStream.set('Stable40');
|
osuStream.set('Stable40');
|
||||||
osuBuild.set(`b${streamInfo}`);
|
osuBuild.set(`b${streamInfo}`);
|
||||||
await invoke('run_osu_updater', { folder: osuPath });
|
await runUpdater(osuPath);
|
||||||
launchInfo = 'osu! is now up to date!';
|
launchInfo = 'osu! is now up to date!';
|
||||||
if (forceUpdate)
|
if (forceUpdate)
|
||||||
await setConfigValues(osuPath, [
|
await setConfigValues(osuPath, [
|
||||||
@ -246,34 +293,27 @@
|
|||||||
}
|
}
|
||||||
await new Promise((res) => setTimeout(res, 1500));
|
await new Promise((res) => setTimeout(res, 1500));
|
||||||
launchInfo = 'Launching osu!...';
|
launchInfo = 'Launching osu!...';
|
||||||
|
await replaceUIFiles(osuPath, false);
|
||||||
await new Promise((res) => setTimeout(res, 1000));
|
await new Promise((res) => setTimeout(res, 1000));
|
||||||
await getCurrentWindow().hide();
|
await getCurrentWindow().hide();
|
||||||
await invoke('run_osu', { folder: osuPath });
|
await runOsu(osuPath);
|
||||||
launchInfo = 'Cleaning up...';
|
launchInfo = 'Cleaning up...';
|
||||||
await getCurrentWindow().show();
|
await getCurrentWindow().show();
|
||||||
|
await new Promise((res) => setTimeout(res, 1000));
|
||||||
|
await replaceUIFiles(osuPath, true);
|
||||||
|
|
||||||
const osuReleaseStream: string = await invoke('get_osu_release_stream', {
|
const osuReleaseStream = await getReleaseStream(osuPath);
|
||||||
folder: osuPath,
|
|
||||||
});
|
|
||||||
osuStream.set(osuReleaseStream);
|
osuStream.set(osuReleaseStream);
|
||||||
const osuVersion: string = await invoke('get_osu_version', {
|
const osuVersion = await getVersion(osuPath);
|
||||||
folder: osuPath,
|
|
||||||
});
|
|
||||||
osuBuild.set(osuVersion);
|
osuBuild.set(osuVersion);
|
||||||
|
|
||||||
const beatmapSetCount: number | null = await invoke('get_beatmapsets_count', {
|
const beatmapSetCount = await getBeatmapSetsCount(osuPath);
|
||||||
folder: osuPath,
|
|
||||||
});
|
|
||||||
if (beatmapSetCount) beatmapSets.set(beatmapSetCount);
|
if (beatmapSetCount) beatmapSets.set(beatmapSetCount);
|
||||||
|
|
||||||
const skinCount: number | null = await invoke('get_skins_count', {
|
const skinCount = await getSkinsCount(osuPath);
|
||||||
folder: osuPath,
|
|
||||||
});
|
|
||||||
if (skinCount) skins.set(skinCount);
|
if (skinCount) skins.set(skinCount);
|
||||||
|
|
||||||
const skin: string = await invoke('get_osu_skin', {
|
const skin = await getSkin(osuPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
currentSkin.set(skin);
|
currentSkin.set(skin);
|
||||||
|
|
||||||
launching.set(false);
|
launching.set(false);
|
||||||
@ -300,7 +340,7 @@
|
|||||||
<span class="font-semibold text-xl">Launching...</span>
|
<span class="font-semibold text-xl">Launching...</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-center justify-center gap-2 p-3 rounded-lg">
|
<div class="flex flex-col items-center justify-center gap-2 p-3 rounded-lg">
|
||||||
<Progress indeterminate />
|
<Progress indeterminate={progress === -1} value={progress} />
|
||||||
<span class="text-muted-foreground">{launchInfo}</span>
|
<span class="text-muted-foreground">{launchInfo}</span>
|
||||||
</div>
|
</div>
|
||||||
</AlertDialog.Content>
|
</AlertDialog.Content>
|
||||||
|
@ -26,7 +26,14 @@
|
|||||||
import { ezppfarm } from '@/api/ezpp';
|
import { ezppfarm } from '@/api/ezpp';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import { currentUserInfo } from '@/data';
|
import { currentUserInfo } from '@/data';
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
import {
|
||||||
|
getBeatmapSetsCount,
|
||||||
|
getReleaseStream,
|
||||||
|
getSkin,
|
||||||
|
getSkinsCount,
|
||||||
|
getVersion,
|
||||||
|
isValidOsuFolder,
|
||||||
|
} from '@/osuUtil';
|
||||||
|
|
||||||
let ezppLogo: HTMLImageElement;
|
let ezppLogo: HTMLImageElement;
|
||||||
let spinnerCircle: SVGCircleElement;
|
let spinnerCircle: SVGCircleElement;
|
||||||
@ -105,9 +112,7 @@
|
|||||||
|
|
||||||
if (!$firstStartup) {
|
if (!$firstStartup) {
|
||||||
currentLoadingInfo.set('Checking osu installation path...');
|
currentLoadingInfo.set('Checking osu installation path...');
|
||||||
const validFolder: boolean = await invoke('valid_osu_folder', {
|
const validFolder = await isValidOsuFolder($osuInstallationPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
if (!validFolder) {
|
if (!validFolder) {
|
||||||
osuInstallationPath.set('');
|
osuInstallationPath.set('');
|
||||||
$userSettings.value('osu_installation_path').del();
|
$userSettings.value('osu_installation_path').del();
|
||||||
@ -117,29 +122,19 @@
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
currentLoadingInfo.set('Getting osu version...');
|
currentLoadingInfo.set('Getting osu version...');
|
||||||
const osuReleaseStream: string = await invoke('get_osu_release_stream', {
|
const osuReleaseStream = await getReleaseStream($osuInstallationPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
osuStream.set(osuReleaseStream);
|
osuStream.set(osuReleaseStream);
|
||||||
const osuVersion: string = await invoke('get_osu_version', {
|
const osuVersion = await getVersion($osuInstallationPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
osuBuild.set(osuVersion);
|
osuBuild.set(osuVersion);
|
||||||
|
|
||||||
currentLoadingInfo.set('Counting beatmapsets...');
|
currentLoadingInfo.set('Counting beatmapsets...');
|
||||||
const beatmapSetCount: number | null = await invoke('get_beatmapsets_count', {
|
const beatmapSetCount = await getBeatmapSetsCount($osuInstallationPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
if (beatmapSetCount) beatmapSets.set(beatmapSetCount);
|
if (beatmapSetCount) beatmapSets.set(beatmapSetCount);
|
||||||
|
|
||||||
currentLoadingInfo.set('Counting skins...');
|
currentLoadingInfo.set('Counting skins...');
|
||||||
const skinCount: number | null = await invoke('get_skins_count', {
|
const skinCount = await getSkinsCount($osuInstallationPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
if (skinCount) skins.set(skinCount);
|
if (skinCount) skins.set(skinCount);
|
||||||
const skin: string = await invoke('get_osu_skin', {
|
const skin: string = await getSkin($osuInstallationPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
currentSkin.set(skin);
|
currentSkin.set(skin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@
|
|||||||
import Input from '@/components/ui/input/input.svelte';
|
import Input from '@/components/ui/input/input.svelte';
|
||||||
import { animate } from 'animejs';
|
import { animate } from 'animejs';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { fade, scale } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { invoke } from '@tauri-apps/api/core';
|
|
||||||
import { Check, CheckCircle, CircleOff, Settings2 } from 'lucide-svelte';
|
import { Check, CheckCircle, CircleOff, Settings2 } from 'lucide-svelte';
|
||||||
import { open } from '@tauri-apps/plugin-dialog';
|
import { open } from '@tauri-apps/plugin-dialog';
|
||||||
import Checkbox from '@/components/ui/checkbox/checkbox.svelte';
|
import Checkbox from '@/components/ui/checkbox/checkbox.svelte';
|
||||||
@ -20,6 +19,15 @@
|
|||||||
import { beatmapSets, currentSkin, currentView, osuBuild, osuStream, skins } from '@/global';
|
import { beatmapSets, currentSkin, currentView, osuBuild, osuStream, skins } from '@/global';
|
||||||
import Launch from './Launch.svelte';
|
import Launch from './Launch.svelte';
|
||||||
import Confetti from 'svelte-confetti';
|
import Confetti from 'svelte-confetti';
|
||||||
|
import {
|
||||||
|
autoDetectOsuInstallFolder,
|
||||||
|
getBeatmapSetsCount,
|
||||||
|
getReleaseStream,
|
||||||
|
getSkin,
|
||||||
|
getSkinsCount,
|
||||||
|
getVersion,
|
||||||
|
isValidOsuFolder,
|
||||||
|
} from '@/osuUtil';
|
||||||
|
|
||||||
let selectedStep = $state(1);
|
let selectedStep = $state(1);
|
||||||
const steps = ['Welcome', 'Locate your osu! Installation', 'Appearance Settings'];
|
const steps = ['Welcome', 'Locate your osu! Installation', 'Appearance Settings'];
|
||||||
@ -60,7 +68,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (typeof selectedPath === 'string') {
|
if (typeof selectedPath === 'string') {
|
||||||
const validFolder: boolean = await invoke('valid_osu_folder', { folder: selectedPath });
|
const validFolder = await isValidOsuFolder(selectedPath);
|
||||||
manualSelect = true;
|
manualSelect = true;
|
||||||
if (!validFolder) {
|
if (!validFolder) {
|
||||||
manualSelectValid = false;
|
manualSelectValid = false;
|
||||||
@ -78,39 +86,29 @@
|
|||||||
await $userSettings.save();
|
await $userSettings.save();
|
||||||
osuInstallationPath.set(osuInstallPath);
|
osuInstallationPath.set(osuInstallPath);
|
||||||
|
|
||||||
const beatmapSetCount: number | null = await invoke('get_beatmapsets_count', {
|
const beatmapSetCount = await getBeatmapSetsCount(osuInstallPath);
|
||||||
folder: osuInstallPath,
|
|
||||||
});
|
|
||||||
if (beatmapSetCount) {
|
if (beatmapSetCount) {
|
||||||
beatmapSets.set(beatmapSetCount);
|
beatmapSets.set(beatmapSetCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
const skinsCount: number | null = await invoke('get_skins_count', {
|
const skinsCount: number | null = await getSkinsCount(osuInstallPath);
|
||||||
folder: osuInstallPath,
|
|
||||||
});
|
|
||||||
if (skinsCount) {
|
if (skinsCount) {
|
||||||
skins.set(skinsCount);
|
skins.set(skinsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
const skin: string = await invoke('get_osu_skin', {
|
const skin: string = await getSkin(osuInstallPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
currentSkin.set(skin);
|
currentSkin.set(skin);
|
||||||
|
|
||||||
const osuReleaseStream: string = await invoke('get_osu_release_stream', {
|
const osuReleaseStream = await getReleaseStream(osuInstallPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
osuStream.set(osuReleaseStream);
|
osuStream.set(osuReleaseStream);
|
||||||
const osuVersion: string = await invoke('get_osu_version', {
|
const osuVersion = await getVersion(osuInstallPath);
|
||||||
folder: $osuInstallationPath,
|
|
||||||
});
|
|
||||||
osuBuild.set(osuVersion);
|
osuBuild.set(osuVersion);
|
||||||
|
|
||||||
currentView.set(Launch);
|
currentView.set(Launch);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const osuPath: string | null = await invoke('find_osu_installation');
|
const osuPath = await autoDetectOsuInstallFolder();
|
||||||
if (osuPath) {
|
if (osuPath) {
|
||||||
osuInstallPath = osuPath;
|
osuInstallPath = osuPath;
|
||||||
autoDetectedOsuPath = true;
|
autoDetectedOsuPath = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user