refactor: Ran cargo clippy & fmt

Signed-off-by: quexeky <git@quexeky.dev>
This commit is contained in:
quexeky
2025-01-05 20:29:15 +11:00
parent 8aad64ffa7
commit 82804ebc67
31 changed files with 380 additions and 284 deletions

View File

@ -236,7 +236,7 @@ pub fn setup() -> Result<(AppStatus, Option<User>), ()> {
#[tauri::command] #[tauri::command]
pub fn sign_out(app: AppHandle) -> Result<(), String> { pub fn sign_out(app: AppHandle) -> Result<(), String> {
info!("Signing out user"); info!("Signing out user");
// Clear auth from database // Clear auth from database
{ {
let mut handle = DB.borrow_data_mut().unwrap(); let mut handle = DB.borrow_data_mut().unwrap();

View File

@ -1,69 +1,69 @@
use log::info; use crate::DB;
use tauri::AppHandle; use log::info;
use tauri_plugin_autostart::ManagerExt; use tauri::AppHandle;
use crate::DB; use tauri_plugin_autostart::ManagerExt;
#[tauri::command] #[tauri::command]
pub async fn toggle_autostart(app: AppHandle, enabled: bool) -> Result<(), String> { pub async fn toggle_autostart(app: AppHandle, enabled: bool) -> Result<(), String> {
let manager = app.autolaunch(); let manager = app.autolaunch();
if enabled { if enabled {
manager.enable().map_err(|e| e.to_string())?; manager.enable().map_err(|e| e.to_string())?;
info!("Enabled autostart"); info!("Enabled autostart");
} else { } else {
manager.disable().map_err(|e| e.to_string())?; manager.disable().map_err(|e| e.to_string())?;
info!("Disabled autostart"); info!("Disabled autostart");
} }
// Store the state in DB // Store the state in DB
let mut db_handle = DB.borrow_data_mut().map_err(|e| e.to_string())?; let mut db_handle = DB.borrow_data_mut().map_err(|e| e.to_string())?;
db_handle.settings.autostart = enabled; db_handle.settings.autostart = enabled;
drop(db_handle); drop(db_handle);
DB.save().map_err(|e| e.to_string())?; DB.save().map_err(|e| e.to_string())?;
Ok(()) Ok(())
} }
#[tauri::command] #[tauri::command]
pub async fn get_autostart_enabled(app: AppHandle) -> Result<bool, String> { pub async fn get_autostart_enabled(app: AppHandle) -> Result<bool, String> {
// First check DB state // First check DB state
let db_handle = DB.borrow_data().map_err(|e| e.to_string())?; let db_handle = DB.borrow_data().map_err(|e| e.to_string())?;
let db_state = db_handle.settings.autostart; let db_state = db_handle.settings.autostart;
drop(db_handle); drop(db_handle);
// Get actual system state // Get actual system state
let manager = app.autolaunch(); let manager = app.autolaunch();
let system_state = manager.is_enabled().map_err(|e| e.to_string())?; let system_state = manager.is_enabled().map_err(|e| e.to_string())?;
// If they don't match, sync to DB state // If they don't match, sync to DB state
if db_state != system_state { if db_state != system_state {
if db_state { if db_state {
manager.enable().map_err(|e| e.to_string())?; manager.enable().map_err(|e| e.to_string())?;
} else { } else {
manager.disable().map_err(|e| e.to_string())?; manager.disable().map_err(|e| e.to_string())?;
} }
} }
Ok(db_state) Ok(db_state)
} }
// New function to sync state on startup // New function to sync state on startup
pub fn sync_autostart_on_startup(app: &AppHandle) -> Result<(), String> { pub fn sync_autostart_on_startup(app: &AppHandle) -> Result<(), String> {
let db_handle = DB.borrow_data().map_err(|e| e.to_string())?; let db_handle = DB.borrow_data().map_err(|e| e.to_string())?;
let should_be_enabled = db_handle.settings.autostart; let should_be_enabled = db_handle.settings.autostart;
drop(db_handle); drop(db_handle);
let manager = app.autolaunch(); let manager = app.autolaunch();
let current_state = manager.is_enabled().map_err(|e| e.to_string())?; let current_state = manager.is_enabled().map_err(|e| e.to_string())?;
if current_state != should_be_enabled { if current_state != should_be_enabled {
if should_be_enabled { if should_be_enabled {
manager.enable().map_err(|e| e.to_string())?; manager.enable().map_err(|e| e.to_string())?;
info!("Synced autostart: enabled"); info!("Synced autostart: enabled");
} else { } else {
manager.disable().map_err(|e| e.to_string())?; manager.disable().map_err(|e| e.to_string())?;
info!("Synced autostart: disabled"); info!("Synced autostart: disabled");
} }
} }
Ok(()) Ok(())
} }

View File

@ -1,8 +1,6 @@
use log::info; use log::info;
use tauri::AppHandle; use tauri::AppHandle;
#[tauri::command] #[tauri::command]
pub fn quit(app: tauri::AppHandle) { pub fn quit(app: tauri::AppHandle) {
cleanup_and_exit(&app); cleanup_and_exit(&app);

View File

@ -2,7 +2,7 @@ use std::{
collections::HashMap, collections::HashMap,
fs::{self, create_dir_all}, fs::{self, create_dir_all},
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::{Arc, LazyLock, Mutex, RwLockWriteGuard}, time::{Instant, SystemTime, UNIX_EPOCH}, sync::{LazyLock, Mutex, RwLockWriteGuard},
}; };
use chrono::Utc; use chrono::Utc;
@ -14,7 +14,12 @@ use serde_with::serde_as;
use tauri::AppHandle; use tauri::AppHandle;
use url::Url; use url::Url;
use crate::{download_manager::downloadable_metadata::DownloadableMetadata, games::{library::push_game_update, state::GameStatusManager}, process::process_manager::Platform, DB}; use crate::{
download_manager::downloadable_metadata::DownloadableMetadata,
games::{library::push_game_update, state::GameStatusManager},
process::process_manager::Platform,
DB,
};
#[derive(serde::Serialize, Clone, Deserialize)] #[derive(serde::Serialize, Clone, Deserialize)]
pub struct DatabaseAuth { pub struct DatabaseAuth {
@ -71,21 +76,12 @@ pub struct DatabaseApplications {
pub transient_statuses: HashMap<DownloadableMetadata, ApplicationTransientStatus>, pub transient_statuses: HashMap<DownloadableMetadata, ApplicationTransientStatus>,
} }
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone, Default)]
pub struct Settings { pub struct Settings {
pub autostart: bool, pub autostart: bool,
// ... other settings ... // ... other settings ...
} }
impl Default for Settings {
fn default() -> Self {
Self {
autostart: false,
// ... other settings defaults ...
}
}
}
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone)]
pub struct Database { pub struct Database {
#[serde(default)] #[serde(default)]
@ -93,7 +89,7 @@ pub struct Database {
pub auth: Option<DatabaseAuth>, pub auth: Option<DatabaseAuth>,
pub base_url: String, pub base_url: String,
pub applications: DatabaseApplications, pub applications: DatabaseApplications,
pub prev_database: Option<PathBuf> pub prev_database: Option<PathBuf>,
} }
pub static DATA_ROOT_DIR: LazyLock<Mutex<PathBuf>> = pub static DATA_ROOT_DIR: LazyLock<Mutex<PathBuf>> =
LazyLock::new(|| Mutex::new(BaseDirs::new().unwrap().data_dir().join("drop"))); LazyLock::new(|| Mutex::new(BaseDirs::new().unwrap().data_dir().join("drop")));
@ -137,11 +133,10 @@ impl DatabaseImpls for DatabaseInterface {
let exists = fs::exists(db_path.clone()).unwrap(); let exists = fs::exists(db_path.clone()).unwrap();
match exists { match exists {
true => true => match PathDatabase::load_from_path(db_path.clone()) {
match PathDatabase::load_from_path(db_path.clone()) { Ok(db) => db,
Ok(db) => db, Err(e) => handle_invalid_database(e, db_path, games_base_dir),
Err(e) => handle_invalid_database(e, db_path, games_base_dir), },
},
false => { false => {
let default = Database { let default = Database {
settings: Settings::default(), settings: Settings::default(),
@ -247,8 +242,12 @@ pub fn set_game_status<F: FnOnce(&mut RwLockWriteGuard<'_, Database>, &Downloada
} }
// TODO: Make the error relelvant rather than just assume that it's a Deserialize error // TODO: Make the error relelvant rather than just assume that it's a Deserialize error
fn handle_invalid_database(_e: RustbreakError, db_path: PathBuf, games_base_dir: PathBuf) -> rustbreak::Database<Database, rustbreak::backend::PathBackend, DropDatabaseSerializer> { fn handle_invalid_database(
let new_path = { _e: RustbreakError,
db_path: PathBuf,
games_base_dir: PathBuf,
) -> rustbreak::Database<Database, rustbreak::backend::PathBackend, DropDatabaseSerializer> {
let new_path = {
let time = Utc::now().timestamp(); let time = Utc::now().timestamp();
let mut base = db_path.clone().into_os_string(); let mut base = db_path.clone().into_os_string();
base.push("."); base.push(".");
@ -271,8 +270,5 @@ fn handle_invalid_database(_e: RustbreakError, db_path: PathBuf, games_base_dir:
settings: Settings { autostart: false }, settings: Settings { autostart: false },
}; };
PathDatabase::create_at_path(db_path, db) PathDatabase::create_at_path(db_path, db).expect("Database could not be created")
.expect("Database could not be created") }
}

View File

@ -1,4 +1,7 @@
use std::{fmt::{Display, Formatter}, io}; use std::{
fmt::{Display, Formatter},
io,
};
use crate::remote::RemoteAccessError; use crate::remote::RemoteAccessError;
@ -38,4 +41,3 @@ impl Display for SetupError {
} }
} }
} }

View File

@ -4,7 +4,7 @@ use std::{
fmt::Debug, fmt::Debug,
sync::{ sync::{
mpsc::{SendError, Sender}, mpsc::{SendError, Sender},
Arc, Mutex, MutexGuard, MutexGuard,
}, },
thread::JoinHandle, thread::JoinHandle,
}; };
@ -12,8 +12,12 @@ use std::{
use log::info; use log::info;
use serde::Serialize; use serde::Serialize;
use super::{
use super::{application_download_error::ApplicationDownloadError, download_manager_builder::{CurrentProgressObject, DownloadAgent}, downloadable_metadata::DownloadableMetadata, queue::Queue}; application_download_error::ApplicationDownloadError,
download_manager_builder::{CurrentProgressObject, DownloadAgent},
downloadable_metadata::DownloadableMetadata,
queue::Queue,
};
pub enum DownloadManagerSignal { pub enum DownloadManagerSignal {
/// Resumes (or starts) the DownloadManager /// Resumes (or starts) the DownloadManager
@ -103,10 +107,11 @@ impl DownloadManager {
pub fn queue_download( pub fn queue_download(
&self, &self,
download: DownloadAgent download: DownloadAgent,
) -> Result<(), SendError<DownloadManagerSignal>> { ) -> Result<(), SendError<DownloadManagerSignal>> {
info!("Adding download id {:?}", download.metadata()); info!("Adding download id {:?}", download.metadata());
self.command_sender.send(DownloadManagerSignal::Queue(download))?; self.command_sender
.send(DownloadManagerSignal::Queue(download))?;
self.command_sender.send(DownloadManagerSignal::Go) self.command_sender.send(DownloadManagerSignal::Go)
} }
pub fn edit(&self) -> MutexGuard<'_, VecDeque<DownloadableMetadata>> { pub fn edit(&self) -> MutexGuard<'_, VecDeque<DownloadableMetadata>> {

View File

@ -1,19 +1,26 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
fs::remove_dir_all,
sync::{ sync::{
mpsc::{channel, Receiver, Sender}, mpsc::{channel, Receiver, Sender},
Arc, Mutex, RwLockWriteGuard, Arc, Mutex,
}, },
thread::{spawn, JoinHandle}, thread::{spawn, JoinHandle},
}; };
use log::{error, info}; use log::info;
use tauri::{AppHandle, Emitter}; use tauri::{AppHandle, Emitter};
use crate::games::library::{QueueUpdateEvent, QueueUpdateEventQueueData, StatsUpdateEvent}; use crate::games::library::{QueueUpdateEvent, QueueUpdateEventQueueData, StatsUpdateEvent};
use super::{application_download_error::ApplicationDownloadError, download_manager::{DownloadManager, DownloadManagerSignal, DownloadManagerStatus}, download_thread_control_flag::{DownloadThreadControl, DownloadThreadControlFlag}, downloadable::Downloadable, downloadable_metadata::DownloadableMetadata, progress_object::ProgressObject, queue::Queue}; use super::{
application_download_error::ApplicationDownloadError,
download_manager::{DownloadManager, DownloadManagerSignal, DownloadManagerStatus},
download_thread_control_flag::{DownloadThreadControl, DownloadThreadControlFlag},
downloadable::Downloadable,
downloadable_metadata::DownloadableMetadata,
progress_object::ProgressObject,
queue::Queue,
};
pub type DownloadAgent = Arc<Box<dyn Downloadable + Send + Sync>>; pub type DownloadAgent = Arc<Box<dyn Downloadable + Send + Sync>>;
pub type CurrentProgressObject = Arc<Mutex<Option<Arc<ProgressObject>>>>; pub type CurrentProgressObject = Arc<Mutex<Option<Arc<ProgressObject>>>>;
@ -115,7 +122,6 @@ impl DownloadManagerBuilder {
let mut download_thread_lock = self.current_download_thread.lock().unwrap(); let mut download_thread_lock = self.current_download_thread.lock().unwrap();
*download_thread_lock = None; *download_thread_lock = None;
drop(download_thread_lock); drop(download_thread_lock);
} }
fn stop_and_wait_current_download(&self) { fn stop_and_wait_current_download(&self) {
@ -130,7 +136,6 @@ impl DownloadManagerBuilder {
} }
} }
fn manage_queue(mut self) -> Result<(), ()> { fn manage_queue(mut self) -> Result<(), ()> {
loop { loop {
let signal = match self.command_receiver.recv() { let signal = match self.command_receiver.recv() {
@ -186,18 +191,26 @@ impl DownloadManagerBuilder {
self.download_queue.append(meta.clone()); self.download_queue.append(meta.clone());
self.download_agent_registry.insert(meta, download_agent); self.download_agent_registry.insert(meta, download_agent);
self.sender.send(DownloadManagerSignal::UpdateUIQueue).unwrap(); self.sender
.send(DownloadManagerSignal::UpdateUIQueue)
.unwrap();
} }
fn manage_go_signal(&mut self) { fn manage_go_signal(&mut self) {
info!("Got signal Go"); info!("Got signal Go");
if self.download_agent_registry.is_empty() { if self.download_agent_registry.is_empty() {
info!("Download agent registry: {:?}", self.download_agent_registry.len()); info!(
return; "Download agent registry: {:?}",
self.download_agent_registry.len()
);
return;
} }
if self.current_download_agent.is_some() { if self.current_download_agent.is_some() {
info!("Current download agent: {:?}", self.current_download_agent.as_ref().unwrap().metadata()); info!(
"Current download agent: {:?}",
self.current_download_agent.as_ref().unwrap().metadata()
);
return; return;
} }
@ -227,16 +240,18 @@ impl DownloadManagerBuilder {
// Ok(true) is for completed and exited properly // Ok(true) is for completed and exited properly
Ok(true) => { Ok(true) => {
download_agent.on_complete(&app_handle); download_agent.on_complete(&app_handle);
sender.send(DownloadManagerSignal::Completed(download_agent.metadata())).unwrap(); sender
}, .send(DownloadManagerSignal::Completed(download_agent.metadata()))
.unwrap();
}
// Ok(false) is for incomplete but exited properly // Ok(false) is for incomplete but exited properly
Ok(false) => { Ok(false) => {
download_agent.on_incomplete(&app_handle); download_agent.on_incomplete(&app_handle);
}, }
Err(e) => { Err(e) => {
download_agent.on_error(&app_handle, e.clone()); download_agent.on_error(&app_handle, e.clone());
sender.send(DownloadManagerSignal::Error(e)).unwrap(); sender.send(DownloadManagerSignal::Error(e)).unwrap();
}, }
} }
sender.send(DownloadManagerSignal::UpdateUIQueue).unwrap(); sender.send(DownloadManagerSignal::UpdateUIQueue).unwrap();
})); }));
@ -290,30 +305,33 @@ impl DownloadManagerBuilder {
info!("Current donwload queue: {:?}", self.download_queue.read()); info!("Current donwload queue: {:?}", self.download_queue.read());
} }
// TODO: Collapse these two into a single if statement somehow // TODO: Collapse these two into a single if statement somehow
else { else if let Some(download_agent) = self.download_agent_registry.get(meta) {
if let Some(download_agent) = self.download_agent_registry.get(meta) {
info!("Object exists in registry");
let index = self.download_queue.get_by_meta(meta);
if let Some(index) = index {
download_agent.on_cancelled(&self.app_handle);
let _ = self.download_queue.edit().remove(index).unwrap();
let removed = self.download_agent_registry.remove(meta);
info!("Removed {:?} from queue {:?}", removed.and_then(|x| Some(x.metadata())), self.download_queue.read());
}
}
}
}
else {
if let Some(download_agent) = self.download_agent_registry.get(meta) {
info!("Object exists in registry"); info!("Object exists in registry");
let index = self.download_queue.get_by_meta(meta); let index = self.download_queue.get_by_meta(meta);
if let Some(index) = index { if let Some(index) = index {
download_agent.on_cancelled(&self.app_handle); download_agent.on_cancelled(&self.app_handle);
let _ = self.download_queue.edit().remove(index).unwrap(); let _ = self.download_queue.edit().remove(index).unwrap();
let removed = self.download_agent_registry.remove(meta); let removed = self.download_agent_registry.remove(meta);
info!("Removed {:?} from queue {:?}", removed.and_then(|x| Some(x.metadata())), self.download_queue.read()); info!(
"Removed {:?} from queue {:?}",
removed.map(|x| x.metadata()),
self.download_queue.read()
);
} }
} }
} else if let Some(download_agent) = self.download_agent_registry.get(meta) {
info!("Object exists in registry");
let index = self.download_queue.get_by_meta(meta);
if let Some(index) = index {
download_agent.on_cancelled(&self.app_handle);
let _ = self.download_queue.edit().remove(index).unwrap();
let removed = self.download_agent_registry.remove(meta);
info!(
"Removed {:?} from queue {:?}",
removed.map(|x| x.metadata()),
self.download_queue.read()
);
}
} }
self.push_ui_queue_update(); self.push_ui_queue_update();
} }
@ -326,18 +344,17 @@ impl DownloadManagerBuilder {
let queue = &self.download_queue.read(); let queue = &self.download_queue.read();
let queue_objs = queue let queue_objs = queue
.iter() .iter()
.map(|(key)| { .map(|key| {
let val = self.download_agent_registry.get(key).unwrap(); let val = self.download_agent_registry.get(key).unwrap();
QueueUpdateEventQueueData { QueueUpdateEventQueueData {
meta: DownloadableMetadata::clone(&key), meta: DownloadableMetadata::clone(key),
status: val.status(), status: val.status(),
progress: val.progress().get_progress() progress: val.progress().get_progress(),
}}) }
})
.collect(); .collect();
let event_data = QueueUpdateEvent { let event_data = QueueUpdateEvent { queue: queue_objs };
queue: queue_objs,
};
self.app_handle.emit("update_queue", event_data).unwrap(); self.app_handle.emit("update_queue", event_data).unwrap();
} }
} }

View File

@ -1,9 +1,11 @@
use std::{fmt::{self, Debug}, sync::{mpsc::Sender, Arc}}; use std::sync::Arc;
use tauri::AppHandle; use tauri::AppHandle;
use super::{ use super::{
application_download_error::ApplicationDownloadError, download_manager::{DownloadManagerSignal, DownloadStatus}, download_thread_control_flag::DownloadThreadControl, downloadable_metadata::DownloadableMetadata, progress_object::ProgressObject application_download_error::ApplicationDownloadError, download_manager::DownloadStatus,
download_thread_control_flag::DownloadThreadControl,
downloadable_metadata::DownloadableMetadata, progress_object::ProgressObject,
}; };
pub trait Downloadable: Send + Sync { pub trait Downloadable: Send + Sync {
@ -17,4 +19,4 @@ pub trait Downloadable: Send + Sync {
fn on_complete(&self, app_handle: &AppHandle); fn on_complete(&self, app_handle: &AppHandle);
fn on_incomplete(&self, app_handle: &AppHandle); fn on_incomplete(&self, app_handle: &AppHandle);
fn on_cancelled(&self, app_handle: &AppHandle); fn on_cancelled(&self, app_handle: &AppHandle);
} }

View File

@ -5,7 +5,7 @@ pub enum DownloadType {
Game, Game,
Tool, Tool,
DLC, DLC,
Mod Mod,
} }
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Clone)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Clone)]
@ -13,14 +13,14 @@ pub enum DownloadType {
pub struct DownloadableMetadata { pub struct DownloadableMetadata {
pub id: String, pub id: String,
pub version: Option<String>, pub version: Option<String>,
pub download_type: DownloadType pub download_type: DownloadType,
} }
impl DownloadableMetadata { impl DownloadableMetadata {
pub fn new(id: String, version: Option<String>, download_type: DownloadType) -> Self { pub fn new(id: String, version: Option<String>, download_type: DownloadType) -> Self {
Self { Self {
id, id,
version, version,
download_type download_type,
} }
} }
} }

View File

@ -1,7 +1,5 @@
use std::sync::Arc;
use super::{download_manager_builder::DownloadAgent, downloadable_metadata::DownloadableMetadata}; use super::{download_manager_builder::DownloadAgent, downloadable_metadata::DownloadableMetadata};
pub fn generate_downloadable(meta: DownloadableMetadata) -> DownloadAgent { pub fn generate_downloadable(meta: DownloadableMetadata) -> DownloadAgent {
todo!() todo!()
} }

View File

@ -1,9 +1,9 @@
pub mod application_download_error;
pub mod download_manager; pub mod download_manager;
pub mod download_manager_builder; pub mod download_manager_builder;
pub mod progress_object;
pub mod queue;
pub mod download_thread_control_flag; pub mod download_thread_control_flag;
pub mod downloadable; pub mod downloadable;
pub mod application_download_error;
pub mod downloadable_metadata; pub mod downloadable_metadata;
pub mod generate_downloadable; pub mod generate_downloadable;
pub mod progress_object;
pub mod queue;

View File

@ -98,7 +98,8 @@ impl ProgressObject {
let amount_since_last_update = current_amount - amount_at_last_update; let amount_since_last_update = current_amount - amount_at_last_update;
let kilobytes_per_second = amount_since_last_update / (last_update_difference as usize).max(1); let kilobytes_per_second =
amount_since_last_update / (last_update_difference as usize).max(1);
let remaining = max - current_amount; // bytes let remaining = max - current_amount; // bytes
let time_remaining = (remaining / 1000) / kilobytes_per_second.max(1); let time_remaining = (remaining / 1000) / kilobytes_per_second.max(1);

View File

@ -11,6 +11,12 @@ pub struct Queue {
} }
#[allow(dead_code)] #[allow(dead_code)]
impl Default for Queue {
fn default() -> Self {
Self::new()
}
}
impl Queue { impl Queue {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
@ -44,10 +50,7 @@ impl Queue {
pub fn append(&self, interface: DownloadableMetadata) { pub fn append(&self, interface: DownloadableMetadata) {
self.edit().push_back(interface); self.edit().push_back(interface);
} }
pub fn pop_front_if_equal( pub fn pop_front_if_equal(&self, meta: &DownloadableMetadata) -> Option<DownloadableMetadata> {
&self,
meta: &DownloadableMetadata,
) -> Option<DownloadableMetadata> {
let mut queue = self.edit(); let mut queue = self.edit();
let front = match queue.front() { let front = match queue.front() {
Some(front) => front, Some(front) => front,
@ -61,7 +64,11 @@ impl Queue {
pub fn get_by_meta(&self, meta: &DownloadableMetadata) -> Option<usize> { pub fn get_by_meta(&self, meta: &DownloadableMetadata) -> Option<usize> {
self.read().iter().position(|data| data == meta) self.read().iter().position(|data| data == meta)
} }
pub fn move_to_index_by_meta(&self, meta: &DownloadableMetadata, new_index: usize) -> Result<(), ()> { pub fn move_to_index_by_meta(
&self,
meta: &DownloadableMetadata,
new_index: usize,
) -> Result<(), ()> {
let index = match self.get_by_meta(meta) { let index = match self.get_by_meta(meta) {
Some(index) => index, Some(index) => index,
None => return Err(()), None => return Err(()),

View File

@ -1,8 +1,10 @@
use crate::auth::generate_authorization_header; use crate::auth::generate_authorization_header;
use crate::db::{set_game_status, GameDownloadStatus, ApplicationTransientStatus, DatabaseImpls}; use crate::db::{set_game_status, ApplicationTransientStatus, DatabaseImpls};
use crate::download_manager::application_download_error::ApplicationDownloadError; use crate::download_manager::application_download_error::ApplicationDownloadError;
use crate::download_manager::download_manager::{DownloadManagerSignal, DownloadStatus}; use crate::download_manager::download_manager::{DownloadManagerSignal, DownloadStatus};
use crate::download_manager::download_thread_control_flag::{DownloadThreadControl, DownloadThreadControlFlag}; use crate::download_manager::download_thread_control_flag::{
DownloadThreadControl, DownloadThreadControlFlag,
};
use crate::download_manager::downloadable::Downloadable; use crate::download_manager::downloadable::Downloadable;
use crate::download_manager::downloadable_metadata::{DownloadType, DownloadableMetadata}; use crate::download_manager::downloadable_metadata::{DownloadType, DownloadableMetadata};
use crate::download_manager::progress_object::{ProgressHandle, ProgressObject}; use crate::download_manager::progress_object::{ProgressHandle, ProgressObject};
@ -12,14 +14,13 @@ use crate::remote::RemoteAccessError;
use crate::DB; use crate::DB;
use log::{debug, error, info}; use log::{debug, error, info};
use rayon::ThreadPoolBuilder; use rayon::ThreadPoolBuilder;
use tauri::{AppHandle, Emitter};
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fs::{create_dir_all, remove_dir_all, File}; use std::fs::{create_dir_all, File};
use std::path::Path; use std::path::Path;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::thread::spawn;
use std::time::Instant; use std::time::Instant;
use tauri::{AppHandle, Emitter};
use urlencoding::encode; use urlencoding::encode;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@ -38,7 +39,7 @@ pub struct GameDownloadAgent {
pub progress: Arc<ProgressObject>, pub progress: Arc<ProgressObject>,
sender: Sender<DownloadManagerSignal>, sender: Sender<DownloadManagerSignal>,
pub stored_manifest: StoredManifest, pub stored_manifest: StoredManifest,
status: Mutex<DownloadStatus> status: Mutex<DownloadStatus>,
} }
impl GameDownloadAgent { impl GameDownloadAgent {
@ -96,8 +97,19 @@ impl GameDownloadAgent {
self.set_progress_object_params(); self.set_progress_object_params();
info!("Running"); info!("Running");
let timer = Instant::now(); let timer = Instant::now();
push_game_update(app_handle, &self.metadata(), (None, Some(ApplicationTransientStatus::Downloading { version_name: self.version.clone() }))); push_game_update(
let res = self.run().map_err(|_| ApplicationDownloadError::DownloadError); app_handle,
&self.metadata(),
(
None,
Some(ApplicationTransientStatus::Downloading {
version_name: self.version.clone(),
}),
),
);
let res = self
.run()
.map_err(|_| ApplicationDownloadError::DownloadError);
info!( info!(
"{} took {}ms to download", "{} took {}ms to download",
@ -192,12 +204,10 @@ impl GameDownloadAgent {
let base_path = Path::new(&self.stored_manifest.base_path); let base_path = Path::new(&self.stored_manifest.base_path);
create_dir_all(base_path).unwrap(); create_dir_all(base_path).unwrap();
{ {
let mut completed_contexts_lock = self.completed_contexts.lock().unwrap(); let mut completed_contexts_lock = self.completed_contexts.lock().unwrap();
completed_contexts_lock.clear(); completed_contexts_lock.clear();
completed_contexts_lock completed_contexts_lock.extend(self.stored_manifest.get_completed_contexts());
.extend(self.stored_manifest.get_completed_contexts());
} }
for (raw_path, chunk) in manifest { for (raw_path, chunk) in manifest {
@ -248,8 +258,6 @@ impl GameDownloadAgent {
let base_url = DB.fetch_base_url(); let base_url = DB.fetch_base_url();
let contexts = self.contexts.lock().unwrap(); let contexts = self.contexts.lock().unwrap();
pool.scope(|scope| { pool.scope(|scope| {
let client = &reqwest::blocking::Client::new(); let client = &reqwest::blocking::Client::new();
@ -267,11 +275,11 @@ impl GameDownloadAgent {
let sender = self.sender.clone(); let sender = self.sender.clone();
let request = generate_request(&base_url, client, &context); let request = generate_request(&base_url, client, context);
scope.spawn(move |_| { scope.spawn(move |_| {
match download_game_chunk(context, &self.control_flag, progress_handle, request) { match download_game_chunk(context, &self.control_flag, progress_handle, request)
{
Ok(res) => { Ok(res) => {
if res { if res {
completed_indexes.push(index); completed_indexes.push(index);
@ -289,7 +297,6 @@ impl GameDownloadAgent {
let newly_completed = completed_indexes.to_owned(); let newly_completed = completed_indexes.to_owned();
let completed_lock_len = { let completed_lock_len = {
let mut completed_contexts_lock = self.completed_contexts.lock().unwrap(); let mut completed_contexts_lock = self.completed_contexts.lock().unwrap();
for (item, _) in newly_completed.iter() { for (item, _) in newly_completed.iter() {
@ -314,7 +321,6 @@ impl GameDownloadAgent {
info!("Sending completed signal"); info!("Sending completed signal");
// We've completed // We've completed
self.sender self.sender
.send(DownloadManagerSignal::Completed(self.metadata())) .send(DownloadManagerSignal::Completed(self.metadata()))
@ -324,7 +330,11 @@ impl GameDownloadAgent {
} }
} }
fn generate_request(base_url: &url::Url, client: reqwest::blocking::Client, context: &DropDownloadContext) -> reqwest::blocking::RequestBuilder { fn generate_request(
base_url: &url::Url,
client: reqwest::blocking::Client,
context: &DropDownloadContext,
) -> reqwest::blocking::RequestBuilder {
let chunk_url = base_url let chunk_url = base_url
.join(&format!( .join(&format!(
"/api/v1/client/chunk?id={}&version={}&name={}&chunk={}", "/api/v1/client/chunk?id={}&version={}&name={}&chunk={}",
@ -335,13 +345,10 @@ fn generate_request(base_url: &url::Url, client: reqwest::blocking::Client, cont
context.index context.index
)) ))
.unwrap(); .unwrap();
let header = generate_authorization_header(); let header = generate_authorization_header();
let request = client client.get(chunk_url).header("Authorization", header)
.get(chunk_url)
.header("Authorization", header);
request
} }
impl Downloadable for GameDownloadAgent { impl Downloadable for GameDownloadAgent {
@ -368,7 +375,6 @@ impl Downloadable for GameDownloadAgent {
fn on_initialised(&self, _app_handle: &tauri::AppHandle) { fn on_initialised(&self, _app_handle: &tauri::AppHandle) {
*self.status.lock().unwrap() = DownloadStatus::Queued; *self.status.lock().unwrap() = DownloadStatus::Queued;
return;
} }
fn on_error(&self, app_handle: &tauri::AppHandle, error: ApplicationDownloadError) { fn on_error(&self, app_handle: &tauri::AppHandle, error: ApplicationDownloadError) {
@ -382,23 +388,24 @@ impl Downloadable for GameDownloadAgent {
set_game_status(app_handle, self.metadata(), |db_handle, meta| { set_game_status(app_handle, self.metadata(), |db_handle, meta| {
db_handle.applications.transient_statuses.remove(meta); db_handle.applications.transient_statuses.remove(meta);
}); });
} }
fn on_complete(&self, app_handle: &tauri::AppHandle) { fn on_complete(&self, app_handle: &tauri::AppHandle) {
on_game_complete(&self.metadata(), self.stored_manifest.base_path.to_string_lossy().to_string(), app_handle).unwrap(); on_game_complete(
&self.metadata(),
self.stored_manifest.base_path.to_string_lossy().to_string(),
app_handle,
)
.unwrap();
} }
fn on_incomplete(&self, _app_handle: &tauri::AppHandle) { fn on_incomplete(&self, _app_handle: &tauri::AppHandle) {
*self.status.lock().unwrap() = DownloadStatus::Queued; *self.status.lock().unwrap() = DownloadStatus::Queued;
return;
} }
fn on_cancelled(&self, _app_handle: &tauri::AppHandle) { fn on_cancelled(&self, _app_handle: &tauri::AppHandle) {}
return;
}
fn status(&self) -> DownloadStatus { fn status(&self) -> DownloadStatus {
self.status.lock().unwrap().clone() self.status.lock().unwrap().clone()
} }
} }

View File

@ -1,6 +1,9 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use crate::{download_manager::{downloadable::Downloadable, downloadable_metadata::DownloadableMetadata}, AppState}; use crate::{
download_manager::{downloadable::Downloadable, downloadable_metadata::DownloadableMetadata},
AppState,
};
use super::download_agent::GameDownloadAgent; use super::download_agent::GameDownloadAgent;
@ -12,9 +15,12 @@ pub fn download_game(
state: tauri::State<'_, Mutex<AppState>>, state: tauri::State<'_, Mutex<AppState>>,
) -> Result<(), String> { ) -> Result<(), String> {
let sender = state.lock().unwrap().download_manager.get_sender(); let sender = state.lock().unwrap().download_manager.get_sender();
let game_download_agent = Arc::new( let game_download_agent = Arc::new(Box::new(GameDownloadAgent::new(
Box::new(GameDownloadAgent::new(game_id, game_version, install_dir, sender)) as Box<dyn Downloadable + Send + Sync> game_id,
); game_version,
install_dir,
sender,
)) as Box<dyn Downloadable + Send + Sync>);
state state
.lock() .lock()
.unwrap() .unwrap()

View File

@ -1,26 +1,23 @@
use crate::auth::generate_authorization_header;
use crate::db::DatabaseImpls;
use crate::download_manager::application_download_error::ApplicationDownloadError; use crate::download_manager::application_download_error::ApplicationDownloadError;
use crate::download_manager::download_thread_control_flag::{DownloadThreadControl, DownloadThreadControlFlag}; use crate::download_manager::download_thread_control_flag::{
DownloadThreadControl, DownloadThreadControlFlag,
};
use crate::download_manager::progress_object::ProgressHandle; use crate::download_manager::progress_object::ProgressHandle;
use crate::games::downloads::manifest::DropDownloadContext; use crate::games::downloads::manifest::DropDownloadContext;
use crate::remote::RemoteAccessError; use crate::remote::RemoteAccessError;
use crate::DB; use log::{error, warn};
use log::{error, info, warn};
use md5::{Context, Digest}; use md5::{Context, Digest};
use reqwest::blocking::{Client, Request, RequestBuilder, Response}; use reqwest::blocking::{RequestBuilder, Response};
use std::fs::{set_permissions, Permissions}; use std::fs::{set_permissions, Permissions};
use std::io::Read; use std::io::Read;
#[cfg(unix)] #[cfg(unix)]
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::sync::Arc;
use std::{ use std::{
fs::{File, OpenOptions}, fs::{File, OpenOptions},
io::{self, BufWriter, Seek, SeekFrom, Write}, io::{self, BufWriter, Seek, SeekFrom, Write},
path::PathBuf, path::PathBuf,
}; };
use urlencoding::encode;
pub struct DropWriter<W: Write> { pub struct DropWriter<W: Write> {
hasher: Context, hasher: Context,
@ -124,7 +121,7 @@ pub fn download_game_chunk(
ctx: &DropDownloadContext, ctx: &DropDownloadContext,
control_flag: &DownloadThreadControl, control_flag: &DownloadThreadControl,
progress: ProgressHandle, progress: ProgressHandle,
request: RequestBuilder request: RequestBuilder,
) -> Result<bool, ApplicationDownloadError> { ) -> Result<bool, ApplicationDownloadError> {
// If we're paused // If we're paused
if control_flag.get() == DownloadThreadControlFlag::Stop { if control_flag.get() == DownloadThreadControlFlag::Stop {

View File

@ -2,4 +2,4 @@ pub mod download_agent;
pub mod download_commands; pub mod download_commands;
mod download_logic; mod download_logic;
mod manifest; mod manifest;
mod stored_manifest; mod stored_manifest;

View File

@ -43,8 +43,6 @@ impl StoredManifest {
} }
}; };
match serde_binary::from_vec::<StoredManifest>(s, Endian::Little) { match serde_binary::from_vec::<StoredManifest>(s, Endian::Little) {
Ok(manifest) => manifest, Ok(manifest) => manifest,
Err(e) => { Err(e) => {

View File

@ -2,19 +2,19 @@ use std::fs::remove_dir_all;
use std::sync::Mutex; use std::sync::Mutex;
use std::thread::spawn; use std::thread::spawn;
use log::{error, info, warn}; use log::{error, info};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tauri::Emitter; use tauri::Emitter;
use tauri::{AppHandle, Manager}; use tauri::{AppHandle, Manager};
use urlencoding::encode; use urlencoding::encode;
use crate::db::{ApplicationTransientStatus, DatabaseImpls, GameDownloadStatus};
use crate::db::GameVersion; use crate::db::GameVersion;
use crate::db::{ApplicationTransientStatus, DatabaseImpls, GameDownloadStatus};
use crate::download_manager::download_manager::DownloadStatus; use crate::download_manager::download_manager::DownloadStatus;
use crate::download_manager::downloadable_metadata::DownloadableMetadata; use crate::download_manager::downloadable_metadata::DownloadableMetadata;
use crate::games::state::{GameStatusManager, GameStatusWithTransient};
use crate::process::process_manager::Platform; use crate::process::process_manager::Platform;
use crate::remote::RemoteAccessError; use crate::remote::RemoteAccessError;
use crate::games::state::{GameStatusManager, GameStatusWithTransient};
use crate::{auth::generate_authorization_header, AppState, DB}; use crate::{auth::generate_authorization_header, AppState, DB};
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
@ -40,7 +40,10 @@ pub struct Game {
#[derive(serde::Serialize, Clone)] #[derive(serde::Serialize, Clone)]
pub struct GameUpdateEvent { pub struct GameUpdateEvent {
pub game_id: String, pub game_id: String,
pub status: (Option<GameDownloadStatus>, Option<ApplicationTransientStatus>), pub status: (
Option<GameDownloadStatus>,
Option<ApplicationTransientStatus>,
),
} }
#[derive(Serialize, Clone)] #[derive(Serialize, Clone)]
@ -237,7 +240,7 @@ fn fetch_game_verion_options_logic<'a>(
pub fn uninstall_game( pub fn uninstall_game(
game_id: String, game_id: String,
state: tauri::State<'_, Mutex<AppState>>, state: tauri::State<'_, Mutex<AppState>>,
app_handle: AppHandle app_handle: AppHandle,
) -> Result<(), String> { ) -> Result<(), String> {
let meta = get_current_meta(&game_id)?; let meta = get_current_meta(&game_id)?;
println!("{:?}", meta); println!("{:?}", meta);
@ -254,7 +257,7 @@ fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle) {
.transient_statuses .transient_statuses
.entry(meta.clone()) .entry(meta.clone())
.and_modify(|v| *v = ApplicationTransientStatus::Uninstalling {}); .and_modify(|v| *v = ApplicationTransientStatus::Uninstalling {});
push_game_update( push_game_update(
app_handle, app_handle,
&meta, &meta,
@ -303,14 +306,24 @@ fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle) {
info!("uninstalled game id {}", &meta.id); info!("uninstalled game id {}", &meta.id);
push_game_update(&app_handle, &meta, (Some(GameDownloadStatus::Remote {}), None)); push_game_update(
&app_handle,
&meta,
(Some(GameDownloadStatus::Remote {}), None),
);
} }
}); });
} }
} }
pub fn get_current_meta(game_id: &String) -> Result<DownloadableMetadata, String> { pub fn get_current_meta(game_id: &String) -> Result<DownloadableMetadata, String> {
match DB.borrow_data().unwrap().applications.installed_game_version.get(game_id) { match DB
.borrow_data()
.unwrap()
.applications
.installed_game_version
.get(game_id)
{
Some(meta) => Ok(meta.clone()), Some(meta) => Ok(meta.clone()),
None => Err(String::from("Could not find installed version")), None => Err(String::from("Could not find installed version")),
} }
@ -331,7 +344,9 @@ pub fn on_game_complete(
) -> Result<(), RemoteAccessError> { ) -> Result<(), RemoteAccessError> {
// Fetch game version information from remote // Fetch game version information from remote
let base_url = DB.fetch_base_url(); let base_url = DB.fetch_base_url();
if meta.version.is_none() { return Err(RemoteAccessError::GameNotFound) } if meta.version.is_none() {
return Err(RemoteAccessError::GameNotFound);
}
let endpoint = base_url.join( let endpoint = base_url.join(
format!( format!(
@ -398,7 +413,11 @@ pub fn on_game_complete(
Ok(()) Ok(())
} }
pub fn push_game_update(app_handle: &AppHandle, meta: &DownloadableMetadata, status: GameStatusWithTransient) { pub fn push_game_update(
app_handle: &AppHandle,
meta: &DownloadableMetadata,
status: GameStatusWithTransient,
) {
app_handle app_handle
.emit( .emit(
&format!("update_game/{}", meta.id), &format!("update_game/{}", meta.id),
@ -408,4 +427,4 @@ pub fn push_game_update(app_handle: &AppHandle, meta: &DownloadableMetadata, sta
}, },
) )
.unwrap(); .unwrap();
} }

View File

@ -1,3 +1,3 @@
pub mod downloads; pub mod downloads;
pub mod library; pub mod library;
pub mod state; pub mod state;

View File

@ -1,19 +1,19 @@
use crate::{ use crate::{
db::{ApplicationTransientStatus, GameDownloadStatus}, download_manager::downloadable_metadata::{DownloadType, DownloadableMetadata}, fetch_state, DB db::{ApplicationTransientStatus, GameDownloadStatus},
DB,
}; };
pub type GameStatusWithTransient = (Option<GameDownloadStatus>, Option<ApplicationTransientStatus>); pub type GameStatusWithTransient = (
Option<GameDownloadStatus>,
Option<ApplicationTransientStatus>,
);
pub struct GameStatusManager {} pub struct GameStatusManager {}
impl GameStatusManager { impl GameStatusManager {
pub fn fetch_state(game_id: &String) -> GameStatusWithTransient { pub fn fetch_state(game_id: &String) -> GameStatusWithTransient {
let db_lock = DB.borrow_data().unwrap(); let db_lock = DB.borrow_data().unwrap();
let online_state = match db_lock.applications.installed_game_version.get(game_id) { let online_state = match db_lock.applications.installed_game_version.get(game_id) {
Some(meta) => db_lock Some(meta) => db_lock.applications.transient_statuses.get(meta).cloned(),
.applications
.transient_statuses
.get(meta)
.cloned(),
None => None, None => None,
}; };
let offline_state = db_lock.applications.game_statuses.get(game_id).cloned(); let offline_state = db_lock.applications.game_statuses.get(game_id).cloned();
@ -29,4 +29,4 @@ impl GameStatusManager {
(None, None) (None, None)
} }
} }

View File

@ -5,12 +5,12 @@ mod games;
mod autostart; mod autostart;
mod cleanup; mod cleanup;
mod debug; mod debug;
pub mod download_manager;
mod process; mod process;
mod remote; mod remote;
mod tools;
pub mod download_manager;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
mod tools;
use crate::autostart::{get_autostart_enabled, toggle_autostart}; use crate::autostart::{get_autostart_enabled, toggle_autostart};
use crate::db::DatabaseImpls; use crate::db::DatabaseImpls;
@ -20,18 +20,20 @@ use auth::{
}; };
use cleanup::{cleanup_and_exit, quit}; use cleanup::{cleanup_and_exit, quit};
use db::{ use db::{
add_download_dir, delete_download_dir, fetch_download_dir_stats, DatabaseInterface, GameDownloadStatus, add_download_dir, delete_download_dir, fetch_download_dir_stats, DatabaseInterface,
DATA_ROOT_DIR, GameDownloadStatus, DATA_ROOT_DIR,
}; };
use debug::fetch_system_data; use debug::fetch_system_data;
use download_manager::download_manager::DownloadManager; use download_manager::download_manager::DownloadManager;
use download_manager::download_manager_builder::DownloadManagerBuilder; use download_manager::download_manager_builder::DownloadManagerBuilder;
use games::downloads::download_commands::{cancel_game, download_game, move_game_in_queue, pause_game_downloads, resume_game_downloads}; use games::downloads::download_commands::{
cancel_game, download_game, move_game_in_queue, pause_game_downloads, resume_game_downloads,
};
use games::library::{
fetch_game, fetch_game_status, fetch_game_verion_options, fetch_library, uninstall_game, Game,
};
use http::Response; use http::Response;
use http::{header::*, response::Builder as ResponseBuilder}; use http::{header::*, response::Builder as ResponseBuilder};
use games::library::{
fetch_game, fetch_game_status, fetch_game_verion_options, fetch_library, uninstall_game, Game
};
use log::{debug, info, warn, LevelFilter}; use log::{debug, info, warn, LevelFilter};
use log4rs::append::console::ConsoleAppender; use log4rs::append::console::ConsoleAppender;
use log4rs::append::file::FileAppender; use log4rs::append::file::FileAppender;
@ -43,7 +45,6 @@ use process::process_commands::{kill_game, launch_game};
use process::process_manager::ProcessManager; use process::process_manager::ProcessManager;
use remote::{gen_drop_url, use_remote}; use remote::{gen_drop_url, use_remote};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tauri_plugin_dialog::DialogExt;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use std::{ use std::{
@ -52,8 +53,9 @@ use std::{
}; };
use tauri::menu::{Menu, MenuItem, PredefinedMenuItem}; use tauri::menu::{Menu, MenuItem, PredefinedMenuItem};
use tauri::tray::TrayIconBuilder; use tauri::tray::TrayIconBuilder;
use tauri::{AppHandle, Emitter, Manager, RunEvent, WindowEvent}; use tauri::{AppHandle, Manager, RunEvent, WindowEvent};
use tauri_plugin_deep_link::DeepLinkExt; use tauri_plugin_deep_link::DeepLinkExt;
use tauri_plugin_dialog::DialogExt;
#[derive(Clone, Copy, Serialize)] #[derive(Clone, Copy, Serialize)]
pub enum AppStatus { pub enum AppStatus {
@ -186,7 +188,6 @@ fn setup(handle: AppHandle) -> AppState<'static> {
drop(db_handle); drop(db_handle);
info!("finished setup!"); info!("finished setup!");
// Sync autostart state // Sync autostart state
@ -335,15 +336,24 @@ pub fn run() {
{ {
let mut db_handle = DB.borrow_data_mut().unwrap(); let mut db_handle = DB.borrow_data_mut().unwrap();
if let Some(original) = db_handle.prev_database.take() { if let Some(original) = db_handle.prev_database.take() {
warn!("Database corrupted. Original file at {}", original.canonicalize().unwrap().to_string_lossy().to_string()); warn!(
"Database corrupted. Original file at {}",
original
.canonicalize()
.unwrap()
.to_string_lossy()
.to_string()
);
app.dialog() app.dialog()
.message("Database corrupted. A copy has been saved at: ".to_string() + original.to_str().unwrap()) .message(
"Database corrupted. A copy has been saved at: ".to_string()
+ original.to_str().unwrap(),
)
.title("Database corrupted") .title("Database corrupted")
.show(|_| {}); .show(|_| {});
} }
} }
Ok(()) Ok(())
}) })
.register_asynchronous_uri_scheme_protocol("object", move |_ctx, request, responder| { .register_asynchronous_uri_scheme_protocol("object", move |_ctx, request, responder| {

View File

@ -46,6 +46,4 @@ impl CompatibilityManager {
Ok(()) Ok(())
} }
} }

View File

@ -1,24 +1,41 @@
use std::sync::Mutex; use std::sync::Mutex;
use crate::{db::GameDownloadStatus, download_manager::downloadable_metadata::{DownloadType, DownloadableMetadata}, games::library::get_current_meta, AppState, DB}; use crate::{
db::GameDownloadStatus,
download_manager::downloadable_metadata::{DownloadType, DownloadableMetadata},
games::library::get_current_meta,
AppState, DB,
};
#[tauri::command] #[tauri::command]
pub fn launch_game( pub fn launch_game(id: String, state: tauri::State<'_, Mutex<AppState>>) -> Result<(), String> {
id: String,
state: tauri::State<'_, Mutex<AppState>>,
) -> Result<(), String> {
let state_lock = state.lock().unwrap(); let state_lock = state.lock().unwrap();
let mut process_manager_lock = state_lock.process_manager.lock().unwrap(); let mut process_manager_lock = state_lock.process_manager.lock().unwrap();
let version = match DB.borrow_data().unwrap().applications.game_statuses.get(&id).cloned() { let version = match DB
Some(GameDownloadStatus::Installed { version_name, install_dir }) => version_name, .borrow_data()
Some(GameDownloadStatus::SetupRequired { version_name, install_dir }) => return Err(String::from("Game setup still required")), .unwrap()
_ => return Err(String::from("Game not installed")) .applications
.game_statuses
.get(&id)
.cloned()
{
Some(GameDownloadStatus::Installed {
version_name,
install_dir,
}) => version_name,
Some(GameDownloadStatus::SetupRequired {
version_name,
install_dir,
}) => return Err(String::from("Game setup still required")),
_ => return Err(String::from("Game not installed")),
}; };
let meta = DownloadableMetadata {
let meta = DownloadableMetadata { id, version: Some(version), download_type: DownloadType::Game }; id,
version: Some(version),
download_type: DownloadType::Game,
};
process_manager_lock.launch_process(meta)?; process_manager_lock.launch_process(meta)?;
@ -29,12 +46,11 @@ pub fn launch_game(
} }
#[tauri::command] #[tauri::command]
pub fn kill_game( pub fn kill_game(game_id: String, state: tauri::State<'_, Mutex<AppState>>) -> Result<(), String> {
game_id: String,
state: tauri::State<'_, Mutex<AppState>>,
) -> Result<(), String> {
let meta = get_current_meta(&game_id)?; let meta = get_current_meta(&game_id)?;
let state_lock = state.lock().unwrap(); let state_lock = state.lock().unwrap();
let mut process_manager_lock = state_lock.process_manager.lock().unwrap(); let mut process_manager_lock = state_lock.process_manager.lock().unwrap();
process_manager_lock.kill_game(meta).map_err(|x| x.to_string()) process_manager_lock
} .kill_game(meta)
.map_err(|x| x.to_string())
}

View File

@ -15,7 +15,11 @@ use tauri::{AppHandle, Manager};
use umu_wrapper_lib::command_builder::UmuCommandBuilder; use umu_wrapper_lib::command_builder::UmuCommandBuilder;
use crate::{ use crate::{
db::{GameDownloadStatus, ApplicationTransientStatus, DATA_ROOT_DIR}, download_manager::{downloadable::Downloadable, downloadable_metadata::DownloadableMetadata}, games::library::push_game_update, games::state::GameStatusManager, AppState, DB db::{ApplicationTransientStatus, GameDownloadStatus, DATA_ROOT_DIR},
download_manager::downloadable_metadata::DownloadableMetadata,
games::library::push_game_update,
games::state::GameStatusManager,
AppState, DB,
}; };
pub struct ProcessManager<'a> { pub struct ProcessManager<'a> {
@ -85,7 +89,7 @@ impl ProcessManager<'_> {
child.kill()?; child.kill()?;
child.wait()?; child.wait()?;
Ok(()) Ok(())
}, }
None => Err(io::Error::new( None => Err(io::Error::new(
io::ErrorKind::NotFound, io::ErrorKind::NotFound,
"Game ID not running", "Game ID not running",
@ -93,7 +97,11 @@ impl ProcessManager<'_> {
}; };
} }
fn on_process_finish(&mut self, meta: DownloadableMetadata, result: Result<ExitStatus, std::io::Error>) { fn on_process_finish(
&mut self,
meta: DownloadableMetadata,
result: Result<ExitStatus, std::io::Error>,
) {
if !self.processes.contains_key(&meta) { if !self.processes.contains_key(&meta) {
warn!("process on_finish was called, but game_id is no longer valid. finished with result: {:?}", result); warn!("process on_finish was called, but game_id is no longer valid. finished with result: {:?}", result);
return; return;
@ -148,7 +156,10 @@ impl ProcessManager<'_> {
} }
let mut db_lock = DB.borrow_data_mut().unwrap(); let mut db_lock = DB.borrow_data_mut().unwrap();
info!("Launching process {:?} with games {:?}", meta, db_lock.applications.game_versions); info!(
"Launching process {:?} with games {:?}",
meta, db_lock.applications.game_versions
);
let game_status = db_lock let game_status = db_lock
.applications .applications
@ -210,10 +221,12 @@ impl ProcessManager<'_> {
.truncate(true) .truncate(true)
.read(true) .read(true)
.create(true) .create(true)
.open( .open(self.log_output_dir.join(format!(
self.log_output_dir "{}-{}-{}.log",
.join(format!("{}-{}-{}.log", meta.id.clone(), meta.version.clone().unwrap_or_default(), current_time.timestamp())), meta.id.clone(),
) meta.version.clone().unwrap_or_default(),
current_time.timestamp()
)))
.map_err(|v| v.to_string())?; .map_err(|v| v.to_string())?;
let error_file = OpenOptions::new() let error_file = OpenOptions::new()

View File

@ -6,7 +6,6 @@ use std::{
use http::StatusCode; use http::StatusCode;
use log::{info, warn}; use log::{info, warn};
use reqwest::blocking::Response;
use serde::Deserialize; use serde::Deserialize;
use url::{ParseError, Url}; use url::{ParseError, Url};

View File

@ -1,3 +1 @@
pub struct CompatibilityLayer { pub struct CompatibilityLayer {}
}

View File

@ -1,4 +1,4 @@
mod compatibility_layer;
mod prefix; mod prefix;
mod registry; mod registry;
mod tool; mod tool;
mod compatibility_layer;

View File

@ -0,0 +1 @@

View File

@ -3,5 +3,5 @@ use std::collections::HashMap;
use crate::download_manager::downloadable::Downloadable; use crate::download_manager::downloadable::Downloadable;
pub struct Registry<T: Downloadable> { pub struct Registry<T: Downloadable> {
tools: HashMap<String, T> tools: HashMap<String, T>,
} }

View File

@ -2,7 +2,11 @@ use std::sync::Arc;
use tauri::AppHandle; use tauri::AppHandle;
use crate::download_manager::{application_download_error::ApplicationDownloadError, download_thread_control_flag::DownloadThreadControl, downloadable::Downloadable, downloadable_metadata::DownloadableMetadata, progress_object::ProgressObject}; use crate::download_manager::{
application_download_error::ApplicationDownloadError,
download_thread_control_flag::DownloadThreadControl, downloadable::Downloadable,
downloadable_metadata::DownloadableMetadata, progress_object::ProgressObject,
};
pub struct ToolDownloadAgent { pub struct ToolDownloadAgent {
id: String, id: String,
@ -36,7 +40,11 @@ impl Downloadable for ToolDownloadAgent {
todo!() todo!()
} }
fn on_error(&self, app_handle: &tauri::AppHandle, error: crate::download_manager::application_download_error::ApplicationDownloadError) { fn on_error(
&self,
app_handle: &tauri::AppHandle,
error: crate::download_manager::application_download_error::ApplicationDownloadError,
) {
todo!() todo!()
} }
@ -51,4 +59,4 @@ impl Downloadable for ToolDownloadAgent {
fn on_cancelled(&self, app_handle: &tauri::AppHandle) { fn on_cancelled(&self, app_handle: &tauri::AppHandle) {
todo!() todo!()
} }
} }