diff --git a/components/GameStatusButton.vue b/components/GameStatusButton.vue index e23c314..a721442 100644 --- a/components/GameStatusButton.vue +++ b/components/GameStatusButton.vue @@ -1,29 +1,45 @@ buttonActions[props.status]()" :class="[ styles[props.status], 'inline-flex uppercase font-display items-center gap-x-2 rounded-md px-4 py-3 text-md font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2', ]" > - + {{ buttonNames[props.status] }} diff --git a/components/LoadingButton.vue b/components/LoadingButton.vue index b61303f..ec0adfa 100644 --- a/components/LoadingButton.vue +++ b/components/LoadingButton.vue @@ -1,7 +1,7 @@ - + installFlow()" :status="status" /> + + + + + + + + + + + install()" + class="relative transform rounded-lg bg-zinc-900 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg" + > + + + + Install {{ game.mName }}? + + + + Drop will add {{ game.mName }} to the queue to be + downloaded. While downloading, Drop may use up a large + amount of resources, particularly network bandwidth and + CPU utilisation. + + + + + + + + + Version + + + {{ + versionOptions[installVersionIndex].versionName + }} + on + {{ + versionOptions[installVersionIndex].platform + }} + + + + + + + + + + {{ version.versionName }} on + {{ version.platform }} + + + + + + + + + + + + + + + + + + + There are no versions to install. Please contact your + server admin or try again later. + + + + + + + Install to + + + {{ + installDirs[installDir] + }} + + + + + + + + + + {{ dir }}} + + + + + + + + + + + + + + + + + + + + + {{ installError }} + + + + + + + + Install + + + Cancel + + + + + + + + diff --git a/pages/store/index.vue b/pages/store/index.vue index 85d220b..696d67c 100644 --- a/pages/store/index.vue +++ b/pages/store/index.vue @@ -39,11 +39,6 @@ const versionName = ref(""); const progress = ref(0); async function startGameDownload() { - await invoke("download_game", { - gameId: gameId.value, - gameVersion: versionName.value, - }); - setInterval(() => { (async () => { const currentProgress = await invoke( diff --git a/src-tauri/src/downloads/download_agent.rs b/src-tauri/src/downloads/download_agent.rs index 2e960e3..e6c630b 100644 --- a/src-tauri/src/downloads/download_agent.rs +++ b/src-tauri/src/downloads/download_agent.rs @@ -172,7 +172,6 @@ impl GameDownloadAgent { pub fn ensure_contexts(&self) -> Result<(), GameDownloadError> { let context_lock = self.contexts.lock().unwrap(); - info!("{:?} {}", context_lock, context_lock.is_empty()); if !context_lock.is_empty() { return Ok(()); } @@ -209,7 +208,7 @@ impl GameDownloadAgent { for (i, length) in chunk.lengths.iter().enumerate() { contexts.push(DropDownloadContext { file_name: raw_path.to_string(), - version: version.to_string(), + version: chunk.versionName.to_string(), offset: running_offset, index: i, game_id: game_id.to_string(), diff --git a/src-tauri/src/downloads/download_commands.rs b/src-tauri/src/downloads/download_commands.rs index c6f3c42..044a067 100644 --- a/src-tauri/src/downloads/download_commands.rs +++ b/src-tauri/src/downloads/download_commands.rs @@ -8,13 +8,14 @@ use crate::AppState; pub fn download_game( game_id: String, game_version: String, + install_dir: usize, state: tauri::State<'_, Mutex>, ) -> Result<(), String> { state .lock() .unwrap() .download_manager - .queue_game(game_id, game_version, 0) + .queue_game(game_id, game_version, install_dir) .map_err(|_| "An error occurred while communicating with the download manager.".to_string()) } diff --git a/src-tauri/src/downloads/download_logic.rs b/src-tauri/src/downloads/download_logic.rs index ed2645f..a290970 100644 --- a/src-tauri/src/downloads/download_logic.rs +++ b/src-tauri/src/downloads/download_logic.rs @@ -3,7 +3,7 @@ use crate::db::DatabaseImpls; use crate::downloads::manifest::DropDownloadContext; use crate::remote::RemoteAccessError; use crate::DB; -use log::info; +use log::{info, warn}; use md5::{Context, Digest}; use reqwest::blocking::Response; @@ -150,6 +150,13 @@ pub fn download_game_chunk( .send() .map_err(|e| GameDownloadError::Communication(e.into()))?; + if response.status() != 200 { + warn!("{}", response.text().unwrap()); + return Err(GameDownloadError::Communication( + RemoteAccessError::InvalidCodeError(400), + )); + } + let mut destination = DropWriter::new(ctx.path); if ctx.offset != 0 { @@ -160,7 +167,9 @@ pub fn download_game_chunk( let content_length = response.content_length(); if content_length.is_none() { - return Err(GameDownloadError::Communication(RemoteAccessError::InvalidResponse)); + return Err(GameDownloadError::Communication( + RemoteAccessError::InvalidResponse, + )); } let mut pipeline = DropDownloadPipeline::new( @@ -176,7 +185,9 @@ pub fn download_game_chunk( return Ok(false); }; - let checksum = pipeline.finish().map_err(|e| GameDownloadError::IoError(e))?; + let checksum = pipeline + .finish() + .map_err(|e| GameDownloadError::IoError(e))?; let res = hex::encode(checksum.0); if res != ctx.checksum { diff --git a/src-tauri/src/downloads/download_manager_builder.rs b/src-tauri/src/downloads/download_manager_builder.rs index 822549c..e9990db 100644 --- a/src-tauri/src/downloads/download_manager_builder.rs +++ b/src-tauri/src/downloads/download_manager_builder.rs @@ -8,6 +8,7 @@ use std::{ }; use log::{error, info, warn}; +use rustbreak::Database; use tauri::{AppHandle, Emitter}; use crate::{db::DatabaseGameStatus, library::GameUpdateEvent, DB}; @@ -247,6 +248,11 @@ impl DownloadManagerBuilder { let mut lock = current_status.status.lock().unwrap(); *lock = GameDownloadStatus::Error; self.set_status(DownloadManagerStatus::Error(error)); + + self.set_game_status( + self.current_game_interface.as_ref().unwrap().id.clone(), + DatabaseGameStatus::Remote, + ); } fn manage_cancel_signal(&mut self, game_id: String) { if let Some(current_flag) = &self.active_control_flag { diff --git a/src-tauri/src/downloads/manifest.rs b/src-tauri/src/downloads/manifest.rs index 2c28ea5..d6cf8ec 100644 --- a/src-tauri/src/downloads/manifest.rs +++ b/src-tauri/src/downloads/manifest.rs @@ -9,6 +9,7 @@ pub struct DropChunk { pub ids: Vec, pub checksums: Vec, pub lengths: Vec, + pub versionName: String, } #[derive(Serialize, Deserialize, Debug, Clone)] diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index a245d3d..0d9a505 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -19,7 +19,7 @@ use downloads::download_manager::DownloadManager; use downloads::download_manager_builder::DownloadManagerBuilder; use env_logger::Env; use http::{header::*, response::Builder as ResponseBuilder}; -use library::{fetch_game, fetch_game_status, fetch_library, Game}; +use library::{fetch_game, fetch_game_status, fetch_game_verion_options, fetch_library, Game}; use log::{debug, info}; use remote::{gen_drop_url, use_remote, RemoteAccessError}; use serde::{Deserialize, Serialize}; @@ -131,6 +131,7 @@ pub fn run() { delete_download_dir, fetch_download_dir_stats, fetch_game_status, + fetch_game_verion_options, // Downloads download_game, get_current_game_download_progress, diff --git a/src-tauri/src/library.rs b/src-tauri/src/library.rs index fe792a3..0afb0bc 100644 --- a/src-tauri/src/library.rs +++ b/src-tauri/src/library.rs @@ -39,6 +39,19 @@ pub struct GameUpdateEvent { pub status: DatabaseGameStatus, } +// Game version with some fields missing and size information +#[derive(serde::Deserialize, serde::Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GameVersionOption { + version_index: usize, + version_name: String, + platform: String, + setup_command: String, + launch_command: String, + delta: bool, + // total_size: usize, +} + fn fetch_library_logic(app: AppHandle) -> Result { let base_url = DB.fetch_base_url(); let library_url = base_url.join("/api/v1/client/user/library")?; @@ -172,3 +185,32 @@ pub fn fetch_game_status(id: String) -> Result { return Ok(status); } + +fn fetch_game_verion_options_logic(game_id: String) -> Result, RemoteAccessError> { + let base_url = DB.fetch_base_url(); + + let endpoint = + base_url.join(format!("/api/v1/client/metadata/versions?id={}", game_id).as_str())?; + let header = generate_authorization_header(); + + let client = reqwest::blocking::Client::new(); + let response = client + .get(endpoint.to_string()) + .header("Authorization", header) + .send()?; + + if response.status() != 200 { + return Err(RemoteAccessError::InvalidCodeError( + response.status().into(), + )); + } + + let data = response.json::>()?; + + return Ok(data); +} + +#[tauri::command] +pub fn fetch_game_verion_options(game_id: String) -> Result, String> { + fetch_game_verion_options_logic(game_id).map_err(|e| e.to_string()) +}
+ Drop will add {{ game.mName }} to the queue to be + downloaded. While downloading, Drop may use up a large + amount of resources, particularly network bandwidth and + CPU utilisation. +