diff --git a/pages/store/index.vue b/pages/store/index.vue
index bb2bedb..8ee2ae7 100644
--- a/pages/store/index.vue
+++ b/pages/store/index.vue
@@ -1,17 +1,17 @@
diff --git a/src-tauri/src/downloads/download_agent.rs b/src-tauri/src/downloads/download_agent.rs
index 487f388..28e93b5 100644
--- a/src-tauri/src/downloads/download_agent.rs
+++ b/src-tauri/src/downloads/download_agent.rs
@@ -14,8 +14,8 @@ use std::sync::atomic::AtomicUsize;
use std::sync::{Arc, Mutex};
pub struct GameDownloadAgent {
- id: String,
- version: String,
+ pub id: String,
+ pub version: String,
state: Mutex,
contexts: Mutex>,
progress: ProgressChecker,
@@ -126,6 +126,10 @@ impl GameDownloadAgent {
let mut lock = self.state.lock().unwrap();
*lock = state;
}
+ pub fn get_state(&self) -> GameDownloadState {
+ let lock = self.state.lock().unwrap();
+ lock.clone()
+ }
pub fn generate_job_contexts(
&self,
@@ -174,27 +178,3 @@ impl GameDownloadAgent {
}
}
-#[tauri::command]
-pub async fn start_game_download(
- game_id: String,
- game_version: String,
- max_threads: usize,
- state: tauri::State<'_, Mutex>,
-) -> Result<(), GameDownloadError> {
- info!("Triggered Game Download");
-
- let download_agent = GameDownloadAgent::new(game_id.clone(), game_version.clone());
-
- download_agent.ensure_manifest_exists().await?;
-
- let local_manifest = {
- let manifest = download_agent.manifest.lock().unwrap();
- (*manifest).clone().unwrap()
- };
-
- download_agent.generate_job_contexts(&local_manifest, game_version.clone(), game_id).unwrap();
-
- download_agent.begin_download(max_threads)?;
-
- Ok(())
-}
diff --git a/src-tauri/src/downloads/download_commands.rs b/src-tauri/src/downloads/download_commands.rs
new file mode 100644
index 0000000..05a17ef
--- /dev/null
+++ b/src-tauri/src/downloads/download_commands.rs
@@ -0,0 +1,76 @@
+use std::sync::{Arc, Mutex};
+
+use log::info;
+
+use crate::{downloads::download_agent::GameDownloadAgent, AppState};
+
+use super::download_agent::{GameDownloadError, GameDownloadState};
+
+#[tauri::command]
+pub async fn queue_game_download(
+ game_id: String,
+ game_version: String,
+ state: tauri::State<'_, Mutex>,
+) -> Result<(), GameDownloadError> {
+ info!("Queuing Game Download");
+ let download_agent = Arc::new(GameDownloadAgent::new(game_id.clone(), game_version.clone()));
+ download_agent.queue().await?;
+
+ let mut queue = state.lock().unwrap();
+ queue.game_downloads.insert(game_id, download_agent);
+ Ok(())
+}
+
+#[tauri::command]
+pub async fn start_game_downloads(
+ max_threads: usize,
+ state: tauri::State<'_, Mutex>,
+) -> Result<(), GameDownloadError> {
+ info!("Downloading Games");
+ loop {
+ let mut current_id = String::new();
+ let mut download_agent = None;
+ {
+ let lock = state.lock().unwrap();
+ for (id, agent) in &lock.game_downloads {
+ if agent.get_state() == GameDownloadState::Queued {
+ download_agent = Some(agent.clone());
+ current_id = id.clone();
+ info!("Got queued game to download");
+ break;
+ }
+ }
+ if download_agent.is_none() {
+ info!("No more games left to download");
+ return Ok(())
+ }
+ };
+ info!("Downloading game");
+ start_game_download(max_threads, download_agent.unwrap()).await?;
+ {
+ let mut lock = state.lock().unwrap();
+ lock.game_downloads.remove_entry(¤t_id);
+ }
+ }
+}
+
+pub async fn start_game_download(
+ max_threads: usize,
+ download_agent: Arc
+) -> Result<(), GameDownloadError> {
+ info!("Triggered Game Download");
+
+
+ download_agent.ensure_manifest_exists().await?;
+
+ let local_manifest = {
+ let manifest = download_agent.manifest.lock().unwrap();
+ (*manifest).clone().unwrap()
+ };
+
+ download_agent.generate_job_contexts(&local_manifest, download_agent.version.clone(), download_agent.id.clone()).unwrap();
+
+ download_agent.begin_download(max_threads)?;
+
+ Ok(())
+}
\ No newline at end of file
diff --git a/src-tauri/src/downloads/download_logic.rs b/src-tauri/src/downloads/download_logic.rs
index b364959..170ee71 100644
--- a/src-tauri/src/downloads/download_logic.rs
+++ b/src-tauri/src/downloads/download_logic.rs
@@ -5,33 +5,28 @@ use crate::DB;
use gxhash::{gxhash128, GxHasher};
use log::info;
use md5::{Context, Digest};
-use std::{fs::{File, OpenOptions}, hash::Hasher, io::{Seek, SeekFrom, Write}, path::PathBuf};
+use std::{fs::{File, OpenOptions}, hash::Hasher, io::{self, Seek, SeekFrom, Write}, path::PathBuf};
use urlencoding::encode;
pub struct FileWriter {
file: File,
hasher: Context,
- data: Vec
}
impl FileWriter {
fn new(path: PathBuf) -> Self {
Self {
file: OpenOptions::new().write(true).open(path).unwrap(),
hasher: Context::new(),
- data: Vec::new()
}
}
- fn finish(mut self) -> Digest {
- self.flush();
- let res = self.hasher.compute();
- info!("Final calculated value hash: {:?}", hex::encode(res.0));
- res
+ fn finish(mut self) -> io::Result {
+ self.flush().unwrap();
+ Ok(self.hasher.compute())
}
}
impl Write for FileWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result {
- self.hasher.write(buf);
- self.data.extend_from_slice(buf);
+ self.hasher.write_all(buf).unwrap();
self.file.write(buf)
}
@@ -82,13 +77,9 @@ pub fn download_game_chunk(ctx: DropDownloadContext) {
response.copy_to(&mut file).unwrap();
- let res = hex::encode(file.finish().0);
- if res == ctx.checksum {
- info!("Matched Checksum {}", res);
- }
- else {
+ let res = hex::encode(file.finish().unwrap().0);
+ if res != ctx.checksum {
info!("Checksum failed. Original: {}, Calculated: {} for {}", ctx.checksum, res, ctx.file_name);
- //info!("Other Checksum: {}", hex::encode(checksum));
}
// stream.flush().unwrap();
diff --git a/src-tauri/src/downloads/mod.rs b/src-tauri/src/downloads/mod.rs
index d7fbe63..bfbc2bc 100644
--- a/src-tauri/src/downloads/mod.rs
+++ b/src-tauri/src/downloads/mod.rs
@@ -1,4 +1,5 @@
mod manifest;
pub mod progress;
pub mod download_agent;
-mod download_logic;
\ No newline at end of file
+mod download_logic;
+pub mod download_commands;
\ No newline at end of file
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index 5bed827..da0413b 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -10,6 +10,7 @@ mod tests;
use auth::{auth_initiate, generate_authorization_header, recieve_handshake};
use db::{DatabaseInterface, DATA_ROOT_DIR};
+use downloads::download_commands::{queue_game_download, start_game_downloads};
use env_logger::Env;
use http::{header::*, response::Builder as ResponseBuilder};
use library::{fetch_game, fetch_library, Game};
@@ -22,7 +23,7 @@ use std::{
use std::sync::Arc;
use tauri_plugin_deep_link::DeepLinkExt;
use crate::db::DatabaseImpls;
-use crate::downloads::download_agent::{start_game_download, GameDownloadAgent};
+use crate::downloads::download_agent::{GameDownloadAgent};
#[derive(Clone, Copy, Serialize)]
pub enum AppStatus {
@@ -49,7 +50,7 @@ pub struct AppState {
games: HashMap,
#[serde(skip_serializing)]
- game_downloads: Vec>
+ game_downloads: HashMap>
}
#[tauri::command]
@@ -69,7 +70,7 @@ fn setup() -> AppState {
status: AppStatus::NotConfigured,
user: None,
games: HashMap::new(),
- game_downloads: vec![],
+ game_downloads: HashMap::new(),
};
}
@@ -78,7 +79,7 @@ fn setup() -> AppState {
status: auth_result.0,
user: auth_result.1,
games: HashMap::new(),
- game_downloads: vec![],
+ game_downloads: HashMap::new(),
}
}
@@ -113,7 +114,8 @@ pub fn run() {
fetch_library,
fetch_game,
// Downloads
- start_game_download
+ queue_game_download,
+ start_game_downloads
])
.plugin(tauri_plugin_shell::init())
.setup(|app| {