feat(install ui): ui to install games

This commit is contained in:
DecDuck
2024-12-06 22:16:50 +11:00
parent b5568429f5
commit 8670bca834
11 changed files with 436 additions and 25 deletions

View File

@ -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(),

View File

@ -8,13 +8,14 @@ use crate::AppState;
pub fn download_game(
game_id: String,
game_version: String,
install_dir: usize,
state: tauri::State<'_, Mutex<AppState>>,
) -> 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())
}

View File

@ -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 {

View File

@ -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 {

View File

@ -9,6 +9,7 @@ pub struct DropChunk {
pub ids: Vec<String>,
pub checksums: Vec<String>,
pub lengths: Vec<usize>,
pub versionName: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]

View File

@ -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,

View File

@ -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<String, RemoteAccessError> {
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<DatabaseGameStatus, String> {
return Ok(status);
}
fn fetch_game_verion_options_logic(game_id: String) -> Result<Vec<GameVersionOption>, 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::<Vec<GameVersionOption>>()?;
return Ok(data);
}
#[tauri::command]
pub fn fetch_game_verion_options(game_id: String) -> Result<Vec<GameVersionOption>, String> {
fetch_game_verion_options_logic(game_id).map_err(|e| e.to_string())
}