diff options
Diffstat (limited to 'src-tauri/src/core')
| -rw-r--r-- | src-tauri/src/core/config.rs | 2 | ||||
| -rw-r--r-- | src-tauri/src/core/downloader.rs | 99 | ||||
| -rw-r--r-- | src-tauri/src/core/game_version.rs | 4 | ||||
| -rw-r--r-- | src-tauri/src/core/mod.rs | 4 | ||||
| -rw-r--r-- | src-tauri/src/core/rules.rs | 14 |
5 files changed, 69 insertions, 54 deletions
diff --git a/src-tauri/src/core/config.rs b/src-tauri/src/core/config.rs index 5558786..47c5306 100644 --- a/src-tauri/src/core/config.rs +++ b/src-tauri/src/core/config.rs @@ -34,7 +34,7 @@ impl ConfigState { pub fn new(app_handle: &AppHandle) -> Self { let app_dir = app_handle.path().app_data_dir().unwrap(); let config_path = app_dir.join("config.json"); - + let config = if config_path.exists() { let content = fs::read_to_string(&config_path).unwrap_or_default(); serde_json::from_str(&content).unwrap_or_default() diff --git a/src-tauri/src/core/downloader.rs b/src-tauri/src/core/downloader.rs index 33404e9..5f6ec80 100644 --- a/src-tauri/src/core/downloader.rs +++ b/src-tauri/src/core/downloader.rs @@ -1,9 +1,9 @@ +use futures::StreamExt; +use serde::{Deserialize, Serialize}; use std::path::PathBuf; -use serde::{Serialize, Deserialize}; +use std::sync::Arc; use tauri::{Emitter, Window}; -use futures::StreamExt; use tokio::io::AsyncWriteExt; -use std::sync::Arc; use tokio::sync::Semaphore; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -24,7 +24,7 @@ pub struct ProgressEvent { pub async fn download_files(window: Window, tasks: Vec<DownloadTask>) -> Result<(), String> { let client = reqwest::Client::new(); let semaphore = Arc::new(Semaphore::new(10)); // Max 10 concurrent downloads - + // Notify start (total files) let _ = window.emit("download-start", tasks.len()); @@ -32,43 +32,49 @@ pub async fn download_files(window: Window, tasks: Vec<DownloadTask>) -> Result< let client = client.clone(); let window = window.clone(); let semaphore = semaphore.clone(); - + async move { let _permit = semaphore.acquire().await.unwrap(); let file_name = task.path.file_name().unwrap().to_string_lossy().to_string(); // 1. Check if file exists and verify SHA1 if task.path.exists() { - let _ = window.emit("download-progress", ProgressEvent { - file: file_name.clone(), - downloaded: 0, - total: 0, - status: "Verifying".into(), - }); + let _ = window.emit( + "download-progress", + ProgressEvent { + file: file_name.clone(), + downloaded: 0, + total: 0, + status: "Verifying".into(), + }, + ); if let Some(expected_sha1) = &task.sha1 { if let Ok(data) = tokio::fs::read(&task.path).await { - let mut hasher = sha1::Sha1::new(); - use sha1::Digest; - hasher.update(&data); - let result = hex::encode(hasher.finalize()); - if &result == expected_sha1 { - // Already valid - let _ = window.emit("download-progress", ProgressEvent { - file: file_name.clone(), - downloaded: 0, - total: 0, - status: "Skipped".into(), - }); - return Ok(()); - } + let mut hasher = sha1::Sha1::new(); + use sha1::Digest; + hasher.update(&data); + let result = hex::encode(hasher.finalize()); + if &result == expected_sha1 { + // Already valid + let _ = window.emit( + "download-progress", + ProgressEvent { + file: file_name.clone(), + downloaded: 0, + total: 0, + status: "Skipped".into(), + }, + ); + return Ok(()); + } } } } // 2. Download if let Some(parent) = task.path.parent() { - let _ = tokio::fs::create_dir_all(parent).await; + let _ = tokio::fs::create_dir_all(parent).await; } match client.get(&task.url).send().await { @@ -78,7 +84,7 @@ pub async fn download_files(window: Window, tasks: Vec<DownloadTask>) -> Result< Ok(f) => f, Err(e) => return Err(format!("Create file error: {}", e)), }; - + let mut downloaded: u64 = 0; loop { match resp.chunk().await { @@ -87,35 +93,44 @@ pub async fn download_files(window: Window, tasks: Vec<DownloadTask>) -> Result< return Err(format!("Write error: {}", e)); } downloaded += chunk.len() as u64; - let _ = window.emit("download-progress", ProgressEvent { - file: file_name.clone(), - downloaded, - total: total_size, - status: "Downloading".into(), - }); + let _ = window.emit( + "download-progress", + ProgressEvent { + file: file_name.clone(), + downloaded, + total: total_size, + status: "Downloading".into(), + }, + ); } Ok(None) => break, Err(e) => return Err(format!("Download error: {}", e)), } } - }, + } Err(e) => return Err(format!("Request error: {}", e)), } - let _ = window.emit("download-progress", ProgressEvent { - file: file_name.clone(), - downloaded: 0, - total: 0, - status: "Finished".into(), - }); + let _ = window.emit( + "download-progress", + ProgressEvent { + file: file_name.clone(), + downloaded: 0, + total: 0, + status: "Finished".into(), + }, + ); Ok(()) } }); // Buffer unordered to run concurrently - tasks_stream.buffer_unordered(10).collect::<Vec<Result<(), String>>>().await; - + tasks_stream + .buffer_unordered(10) + .collect::<Vec<Result<(), String>>>() + .await; + let _ = window.emit("download-complete", ()); Ok(()) } diff --git a/src-tauri/src/core/game_version.rs b/src-tauri/src/core/game_version.rs index 9eb8d67..572882f 100644 --- a/src-tauri/src/core/game_version.rs +++ b/src-tauri/src/core/game_version.rs @@ -56,9 +56,9 @@ pub struct Rule { #[derive(Debug, Deserialize)] pub struct OsRule { - pub name: Option<String>, // "linux", "osx", "windows" + pub name: Option<String>, // "linux", "osx", "windows" pub version: Option<String>, // Regex - pub arch: Option<String>, // "x86" + pub arch: Option<String>, // "x86" } #[derive(Debug, Deserialize)] diff --git a/src-tauri/src/core/mod.rs b/src-tauri/src/core/mod.rs index 6f7c3fe..746afe6 100644 --- a/src-tauri/src/core/mod.rs +++ b/src-tauri/src/core/mod.rs @@ -1,6 +1,6 @@ -pub mod manifest; pub mod auth; +pub mod config; pub mod downloader; pub mod game_version; +pub mod manifest; pub mod rules; -pub mod config; diff --git a/src-tauri/src/core/rules.rs b/src-tauri/src/core/rules.rs index 214d9bc..877982a 100644 --- a/src-tauri/src/core/rules.rs +++ b/src-tauri/src/core/rules.rs @@ -11,7 +11,7 @@ pub fn is_library_allowed(rules: &Option<Vec<Rule>>) -> bool { return true; } - // Default depends on the first rule theoretically, but usually "allow" if no "disallow" matches? + // Default depends on the first rule theoretically, but usually "allow" if no "disallow" matches? // Actually MC logic: implicit disallow? No, implicit allow usually? // Official launcher Rule logic: // "Libraries are allowed unless restricted by a rule." @@ -24,23 +24,23 @@ pub fn is_library_allowed(rules: &Option<Vec<Rule>>) -> bool { // This implies base allowed, but OS X disallowed. // Pattern 2: [ {action: allow, os: "osx"} ] // This implies ONLY osx allowed? - + // Correct logic: // If rules are present, start with result = false (deny all). // Loop through rules. If a rule applies (os matches), update result to (action == "allow"). // Wait, let's verify. // If the list is [ {action: allow} ], result becomes true. - // If list is [ {action: allow}, {action: disallow, os: "osx"} ]. + // If list is [ {action: allow}, {action: disallow, os: "osx"} ]. // On Linux: Rule 1 matches -> true. Rule 2 (osx) doesn't match -> ignore. Final: true. // On OSX: Rule 1 matches -> true. Rule 2 matches -> false. Final: false. - + // So: Start false. Apply rules in order. - + let mut allowed = false; for rule in rules { if rule_matches(rule) { - allowed = (rule.action == "allow"); + allowed = rule.action == "allow"; } } allowed @@ -60,7 +60,7 @@ fn rule_matches(rule: &Rule) -> bool { } else { // OS rule exists but name is None? Maybe checking version/arch only. // For simplicity, mostly name is used. - true + true } } } |