mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-16 17:51:23 +10:00
Implement better error system and segregate errors and commands (#23)
* chore: Progress on amend_settings command Signed-off-by: quexeky <git@quexeky.dev> * chore(errors): Progress on better error handling with segragation of files * chore: Progress on amend_settings command Signed-off-by: quexeky <git@quexeky.dev> * chore(commands): Separated commands under each subdirectory into respective commands.rs files Signed-off-by: quexeky <git@quexeky.dev> * chore(errors): Almost all errors and commands have been segregated * chore(errors): Added drop server error Signed-off-by: quexeky <git@quexeky.dev> * feat(core): Update to using nightly compiler Signed-off-by: quexeky <git@quexeky.dev> * chore(errors): More progress on error handling Signed-off-by: quexeky <git@quexeky.dev> * chore(errors): Implementing Try and FromResidual for UserValue Signed-off-by: quexeky <git@quexeky.dev> * refactor(errors): Segregated errors and commands from code, and made commands return UserValue struct Signed-off-by: quexeky <git@quexeky.dev> * fix(errors): Added missing files * chore(errors): Convert match statement to map_err * feat(settings): Implemented settings editing from UI * feat(errors): Clarified return values from retry_connect command * chore(errors): Moved autostart commands to autostart.rs * chore(process manager): Converted launch_process function for games to use game_id --------- Signed-off-by: quexeky <git@quexeky.dev>
This commit is contained in:
57
src-tauri/src/games/commands.rs
Normal file
57
src-tauri/src/games/commands.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use std::sync::Mutex;
|
||||
|
||||
use tauri::AppHandle;
|
||||
|
||||
use crate::{
|
||||
error::{
|
||||
library_error::LibraryError, remote_access_error::RemoteAccessError, user_error::UserValue,
|
||||
},
|
||||
games::library::{get_current_meta, uninstall_game_logic},
|
||||
AppState,
|
||||
};
|
||||
|
||||
use super::{
|
||||
library::{
|
||||
fetch_game_logic, fetch_game_verion_options_logic, fetch_library_logic, FetchGameStruct,
|
||||
Game, GameVersionOption,
|
||||
},
|
||||
state::{GameStatusManager, GameStatusWithTransient},
|
||||
};
|
||||
|
||||
#[tauri::command]
|
||||
pub fn fetch_library(app: AppHandle) -> UserValue<Vec<Game>, RemoteAccessError> {
|
||||
fetch_library_logic(app).into()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn fetch_game(
|
||||
game_id: String,
|
||||
app: tauri::AppHandle,
|
||||
) -> UserValue<FetchGameStruct, RemoteAccessError> {
|
||||
fetch_game_logic(game_id, app).into()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn fetch_game_status(id: String) -> GameStatusWithTransient {
|
||||
GameStatusManager::fetch_state(&id)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn uninstall_game(game_id: String, app_handle: AppHandle) -> UserValue<(), LibraryError> {
|
||||
let meta = match get_current_meta(&game_id) {
|
||||
Some(data) => data,
|
||||
None => return UserValue::Err(LibraryError::MetaNotFound(game_id)),
|
||||
};
|
||||
println!("{:?}", meta);
|
||||
uninstall_game_logic(meta, &app_handle);
|
||||
|
||||
UserValue::Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn fetch_game_verion_options(
|
||||
game_id: String,
|
||||
state: tauri::State<'_, Mutex<AppState>>,
|
||||
) -> UserValue<Vec<GameVersionOption>, RemoteAccessError> {
|
||||
fetch_game_verion_options_logic(game_id, state).into()
|
||||
}
|
||||
31
src-tauri/src/games/downloads/commands.rs
Normal file
31
src-tauri/src/games/downloads/commands.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use std::sync::{mpsc::SendError, Arc, Mutex};
|
||||
|
||||
use crate::{
|
||||
download_manager::{download_manager::DownloadManagerSignal, downloadable::Downloadable},
|
||||
error::user_error::UserValue,
|
||||
AppState,
|
||||
};
|
||||
|
||||
use super::download_agent::GameDownloadAgent;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn download_game(
|
||||
game_id: String,
|
||||
game_version: String,
|
||||
install_dir: usize,
|
||||
state: tauri::State<'_, Mutex<AppState>>,
|
||||
) -> UserValue<(), SendError<DownloadManagerSignal>> {
|
||||
let sender = state.lock().unwrap().download_manager.get_sender();
|
||||
let game_download_agent = Arc::new(Box::new(GameDownloadAgent::new(
|
||||
game_id,
|
||||
game_version,
|
||||
install_dir,
|
||||
sender,
|
||||
)) as Box<dyn Downloadable + Send + Sync>);
|
||||
state
|
||||
.lock()
|
||||
.unwrap()
|
||||
.download_manager
|
||||
.queue_download(game_download_agent)
|
||||
.into()
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::auth::generate_authorization_header;
|
||||
use crate::db::{set_game_status, ApplicationTransientStatus, DatabaseImpls};
|
||||
use crate::download_manager::application_download_error::ApplicationDownloadError;
|
||||
use crate::database::db::{
|
||||
set_game_status, ApplicationTransientStatus, DatabaseImpls, GameDownloadStatus,
|
||||
};
|
||||
use crate::download_manager::download_manager::{DownloadManagerSignal, DownloadStatus};
|
||||
use crate::download_manager::download_thread_control_flag::{
|
||||
DownloadThreadControl, DownloadThreadControlFlag,
|
||||
@ -8,9 +9,10 @@ use crate::download_manager::download_thread_control_flag::{
|
||||
use crate::download_manager::downloadable::Downloadable;
|
||||
use crate::download_manager::downloadable_metadata::{DownloadType, DownloadableMetadata};
|
||||
use crate::download_manager::progress_object::{ProgressHandle, ProgressObject};
|
||||
use crate::error::application_download_error::ApplicationDownloadError;
|
||||
use crate::error::remote_access_error::RemoteAccessError;
|
||||
use crate::games::downloads::manifest::{DropDownloadContext, DropManifest};
|
||||
use crate::games::library::{on_game_complete, push_game_update};
|
||||
use crate::remote::RemoteAccessError;
|
||||
use crate::games::library::{on_game_complete, push_game_update, GameUpdateEvent};
|
||||
use crate::DB;
|
||||
use log::{debug, error, info};
|
||||
use rayon::ThreadPoolBuilder;
|
||||
@ -100,7 +102,7 @@ impl GameDownloadAgent {
|
||||
let timer = Instant::now();
|
||||
push_game_update(
|
||||
app_handle,
|
||||
&self.metadata(),
|
||||
&self.metadata().id,
|
||||
(
|
||||
None,
|
||||
Some(ApplicationTransientStatus::Downloading {
|
||||
@ -208,7 +210,8 @@ impl GameDownloadAgent {
|
||||
{
|
||||
let mut completed_contexts_lock = self.completed_contexts.lock().unwrap();
|
||||
completed_contexts_lock.clear();
|
||||
completed_contexts_lock.extend(self.stored_manifest.get_completed_contexts());
|
||||
completed_contexts_lock
|
||||
.extend_from_slice(&self.stored_manifest.get_completed_contexts());
|
||||
}
|
||||
|
||||
for (raw_path, chunk) in manifest {
|
||||
@ -247,9 +250,12 @@ impl GameDownloadAgent {
|
||||
|
||||
// TODO: Change return value on Err
|
||||
pub fn run(&self) -> Result<bool, ()> {
|
||||
info!("downloading game: {}", self.id);
|
||||
let max_download_threads = DB.borrow_data().unwrap().settings.max_download_threads;
|
||||
|
||||
info!(
|
||||
"downloading game: {} with {} threads",
|
||||
self.id, max_download_threads
|
||||
);
|
||||
let pool = ThreadPoolBuilder::new()
|
||||
.num_threads(max_download_threads)
|
||||
.build()
|
||||
@ -401,8 +407,18 @@ impl Downloadable for GameDownloadAgent {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn on_incomplete(&self, _app_handle: &tauri::AppHandle) {
|
||||
fn on_incomplete(&self, app_handle: &tauri::AppHandle) {
|
||||
let meta = self.metadata();
|
||||
*self.status.lock().unwrap() = DownloadStatus::Queued;
|
||||
app_handle
|
||||
.emit(
|
||||
&format!("update_game/{}", meta.id),
|
||||
GameUpdateEvent {
|
||||
game_id: meta.id.clone(),
|
||||
status: (Some(GameDownloadStatus::Remote {}), None),
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn on_cancelled(&self, _app_handle: &tauri::AppHandle) {}
|
||||
|
||||
@ -1,58 +0,0 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::{
|
||||
download_manager::{downloadable::Downloadable, downloadable_metadata::DownloadableMetadata},
|
||||
AppState,
|
||||
};
|
||||
|
||||
use super::download_agent::GameDownloadAgent;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn download_game(
|
||||
game_id: String,
|
||||
game_version: String,
|
||||
install_dir: usize,
|
||||
state: tauri::State<'_, Mutex<AppState>>,
|
||||
) -> Result<(), String> {
|
||||
let sender = state.lock().unwrap().download_manager.get_sender();
|
||||
let game_download_agent = Arc::new(Box::new(GameDownloadAgent::new(
|
||||
game_id,
|
||||
game_version,
|
||||
install_dir,
|
||||
sender,
|
||||
)) as Box<dyn Downloadable + Send + Sync>);
|
||||
state
|
||||
.lock()
|
||||
.unwrap()
|
||||
.download_manager
|
||||
.queue_download(game_download_agent)
|
||||
.map_err(|_| "An error occurred while communicating with the download manager.".to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn pause_game_downloads(state: tauri::State<'_, Mutex<AppState>>) {
|
||||
state.lock().unwrap().download_manager.pause_downloads()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn resume_game_downloads(state: tauri::State<'_, Mutex<AppState>>) {
|
||||
state.lock().unwrap().download_manager.resume_downloads()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn move_game_in_queue(
|
||||
state: tauri::State<'_, Mutex<AppState>>,
|
||||
old_index: usize,
|
||||
new_index: usize,
|
||||
) {
|
||||
state
|
||||
.lock()
|
||||
.unwrap()
|
||||
.download_manager
|
||||
.rearrange(old_index, new_index)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn cancel_game(state: tauri::State<'_, Mutex<AppState>>, meta: DownloadableMetadata) {
|
||||
state.lock().unwrap().download_manager.cancel(meta)
|
||||
}
|
||||
@ -1,10 +1,10 @@
|
||||
use crate::download_manager::application_download_error::ApplicationDownloadError;
|
||||
use crate::download_manager::download_thread_control_flag::{
|
||||
DownloadThreadControl, DownloadThreadControlFlag,
|
||||
};
|
||||
use crate::download_manager::progress_object::ProgressHandle;
|
||||
use crate::error::application_download_error::ApplicationDownloadError;
|
||||
use crate::error::remote_access_error::RemoteAccessError;
|
||||
use crate::games::downloads::manifest::DropDownloadContext;
|
||||
use crate::remote::RemoteAccessError;
|
||||
use log::{error, warn};
|
||||
use md5::{Context, Digest};
|
||||
use reqwest::blocking::{RequestBuilder, Response};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
pub mod commands;
|
||||
pub mod download_agent;
|
||||
pub mod download_commands;
|
||||
mod download_logic;
|
||||
mod manifest;
|
||||
mod stored_manifest;
|
||||
|
||||
@ -8,14 +8,15 @@ use tauri::Emitter;
|
||||
use tauri::{AppHandle, Manager};
|
||||
use urlencoding::encode;
|
||||
|
||||
use crate::db::GameVersion;
|
||||
use crate::db::{ApplicationTransientStatus, DatabaseImpls, GameDownloadStatus};
|
||||
use crate::database::db::GameVersion;
|
||||
use crate::database::db::{ApplicationTransientStatus, DatabaseImpls, GameDownloadStatus};
|
||||
use crate::download_manager::download_manager::DownloadStatus;
|
||||
use crate::download_manager::downloadable_metadata::DownloadableMetadata;
|
||||
use crate::error::remote_access_error::RemoteAccessError;
|
||||
use crate::games::state::{GameStatusManager, GameStatusWithTransient};
|
||||
use crate::process::process_manager::Platform;
|
||||
use crate::remote::RemoteAccessError;
|
||||
use crate::{auth::generate_authorization_header, AppState, DB};
|
||||
use crate::remote::auth::generate_authorization_header;
|
||||
use crate::{AppState, DB};
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
pub struct FetchGameStruct {
|
||||
@ -78,7 +79,7 @@ pub struct GameVersionOption {
|
||||
// total_size: usize,
|
||||
}
|
||||
|
||||
fn fetch_library_logic(app: AppHandle) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
pub fn fetch_library_logic(app: AppHandle) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
let base_url = DB.fetch_base_url();
|
||||
let library_url = base_url.join("/api/v1/client/user/library")?;
|
||||
|
||||
@ -118,12 +119,7 @@ fn fetch_library_logic(app: AppHandle) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
Ok(games)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn fetch_library(app: AppHandle) -> Result<Vec<Game>, String> {
|
||||
fetch_library_logic(app).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
fn fetch_game_logic(
|
||||
pub fn fetch_game_logic(
|
||||
id: String,
|
||||
app: tauri::AppHandle,
|
||||
) -> Result<FetchGameStruct, RemoteAccessError> {
|
||||
@ -184,25 +180,7 @@ fn fetch_game_logic(
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn fetch_game(game_id: String, app: tauri::AppHandle) -> Result<FetchGameStruct, String> {
|
||||
let result = fetch_game_logic(game_id, app);
|
||||
|
||||
if result.is_err() {
|
||||
return Err(result.err().unwrap().to_string());
|
||||
}
|
||||
|
||||
Ok(result.unwrap())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn fetch_game_status(id: String) -> Result<GameStatusWithTransient, String> {
|
||||
let status = GameStatusManager::fetch_state(&id);
|
||||
|
||||
Ok(status)
|
||||
}
|
||||
|
||||
fn fetch_game_verion_options_logic(
|
||||
pub fn fetch_game_verion_options_logic(
|
||||
game_id: String,
|
||||
state: tauri::State<'_, Mutex<AppState>>,
|
||||
) -> Result<Vec<GameVersionOption>, RemoteAccessError> {
|
||||
@ -238,19 +216,7 @@ fn fetch_game_verion_options_logic(
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn uninstall_game(
|
||||
game_id: String,
|
||||
app_handle: AppHandle,
|
||||
) -> Result<(), String> {
|
||||
let meta = get_current_meta(&game_id)?;
|
||||
println!("{:?}", meta);
|
||||
uninstall_game_logic(meta, &app_handle);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle) {
|
||||
pub fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle) {
|
||||
println!("Triggered uninstall for agent");
|
||||
let mut db_handle = DB.borrow_data_mut().unwrap();
|
||||
db_handle
|
||||
@ -261,7 +227,7 @@ fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle) {
|
||||
|
||||
push_game_update(
|
||||
app_handle,
|
||||
&meta,
|
||||
&meta.id,
|
||||
(None, Some(ApplicationTransientStatus::Uninstalling {})),
|
||||
);
|
||||
|
||||
@ -309,7 +275,7 @@ fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle) {
|
||||
|
||||
push_game_update(
|
||||
&app_handle,
|
||||
&meta,
|
||||
&meta.id,
|
||||
(Some(GameDownloadStatus::Remote {}), None),
|
||||
);
|
||||
}
|
||||
@ -317,25 +283,13 @@ fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_current_meta(game_id: &String) -> Result<DownloadableMetadata, String> {
|
||||
match DB
|
||||
.borrow_data()
|
||||
pub fn get_current_meta(game_id: &String) -> Option<DownloadableMetadata> {
|
||||
DB.borrow_data()
|
||||
.unwrap()
|
||||
.applications
|
||||
.installed_game_version
|
||||
.get(game_id)
|
||||
{
|
||||
Some(meta) => Ok(meta.clone()),
|
||||
None => Err(String::from("Could not find installed version")),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn fetch_game_verion_options(
|
||||
game_id: String,
|
||||
state: tauri::State<'_, Mutex<AppState>>,
|
||||
) -> Result<Vec<GameVersionOption>, String> {
|
||||
fetch_game_verion_options_logic(game_id, state).map_err(|e| e.to_string())
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn on_game_complete(
|
||||
@ -414,16 +368,12 @@ pub fn on_game_complete(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn push_game_update(
|
||||
app_handle: &AppHandle,
|
||||
meta: &DownloadableMetadata,
|
||||
status: GameStatusWithTransient,
|
||||
) {
|
||||
pub fn push_game_update(app_handle: &AppHandle, game_id: &String, status: GameStatusWithTransient) {
|
||||
app_handle
|
||||
.emit(
|
||||
&format!("update_game/{}", meta.id),
|
||||
&format!("update_game/{}", game_id),
|
||||
GameUpdateEvent {
|
||||
game_id: meta.id.clone(),
|
||||
game_id: game_id.clone(),
|
||||
status,
|
||||
},
|
||||
)
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
pub mod commands;
|
||||
pub mod downloads;
|
||||
pub mod library;
|
||||
pub mod state;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
db::{ApplicationTransientStatus, GameDownloadStatus},
|
||||
database::db::{ApplicationTransientStatus, GameDownloadStatus},
|
||||
DB,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user