mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-13 08:12:44 +10:00
refactor: Ran cargo clippy & fmt
Signed-off-by: quexeky <git@quexeky.dev>
This commit is contained in:
@ -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();
|
||||||
|
|||||||
@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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")
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@ -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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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>> {
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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!()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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(()),
|
||||||
|
|||||||
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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) => {
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
pub mod downloads;
|
pub mod downloads;
|
||||||
pub mod library;
|
pub mod library;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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| {
|
||||||
|
|||||||
@ -46,6 +46,4 @@ impl CompatibilityManager {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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())
|
||||||
|
}
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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};
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1 @@
|
|||||||
pub struct CompatibilityLayer {
|
pub struct CompatibilityLayer {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
|
mod compatibility_layer;
|
||||||
mod prefix;
|
mod prefix;
|
||||||
mod registry;
|
mod registry;
|
||||||
mod tool;
|
mod tool;
|
||||||
mod compatibility_layer;
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
|
||||||
|
|||||||
@ -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>,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user