mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-15 01:01:25 +10:00
refactor(download manager): Fully separate & generic download manager
Signed-off-by: quexeky <git@quexeky.dev>
This commit is contained in:
@ -12,16 +12,9 @@ use std::{
|
||||
use log::info;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::downloads::download_agent::GameDownloadAgent;
|
||||
|
||||
use super::{application_download_error::ApplicationDownloadError, download_manager_builder::{CurrentProgressObject, DownloadAgent, DownloadableQueueStandin}, downloadable::Downloadable, downloadable_metadata::DownloadableMetadata, queue::Queue};
|
||||
use super::{application_download_error::ApplicationDownloadError, download_manager_builder::{CurrentProgressObject, DownloadAgent}, downloadable_metadata::DownloadableMetadata, queue::Queue};
|
||||
|
||||
pub enum DownloadType {
|
||||
Game,
|
||||
Tool,
|
||||
DLC,
|
||||
Mod
|
||||
}
|
||||
pub enum DownloadManagerSignal {
|
||||
/// Resumes (or starts) the DownloadManager
|
||||
Go,
|
||||
@ -91,22 +84,6 @@ pub struct DownloadManager {
|
||||
progress: CurrentProgressObject,
|
||||
command_sender: Sender<DownloadManagerSignal>,
|
||||
}
|
||||
impl<T: Downloadable> From<Arc<T>> for DownloadableQueueStandin {
|
||||
fn from(value: Arc<T>) -> Self {
|
||||
Self {
|
||||
id: value.id(),
|
||||
status: Mutex::from(DownloadStatus::Queued),
|
||||
progress: value.progress().clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Debug for DownloadableQueueStandin {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("DownloadableQueueStandin")
|
||||
.field("id", &self.id)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl DownloadManager {
|
||||
@ -126,40 +103,34 @@ impl DownloadManager {
|
||||
|
||||
pub fn queue_download(
|
||||
&self,
|
||||
id: String,
|
||||
version: String,
|
||||
target_download_dir: usize,
|
||||
download: DownloadAgent
|
||||
) -> Result<(), SendError<DownloadManagerSignal>> {
|
||||
info!("Adding download id {}", id);
|
||||
self.command_sender.send(DownloadManagerSignal::Queue(
|
||||
id,
|
||||
version,
|
||||
target_download_dir,
|
||||
))?;
|
||||
info!("Adding download id {:?}", download.metadata());
|
||||
self.command_sender.send(DownloadManagerSignal::Queue(download))?;
|
||||
self.command_sender.send(DownloadManagerSignal::Go)
|
||||
}
|
||||
pub fn edit(&self) -> MutexGuard<'_, VecDeque<Arc<DownloadableQueueStandin>>> {
|
||||
pub fn edit(&self) -> MutexGuard<'_, VecDeque<Arc<DownloadableMetadata>>> {
|
||||
self.download_queue.edit()
|
||||
}
|
||||
pub fn read_queue(&self) -> VecDeque<Arc<DownloadableQueueStandin>> {
|
||||
pub fn read_queue(&self) -> VecDeque<Arc<DownloadableMetadata>> {
|
||||
self.download_queue.read()
|
||||
}
|
||||
pub fn get_current_download_progress(&self) -> Option<f64> {
|
||||
let progress_object = (*self.progress.lock().unwrap()).clone()?;
|
||||
Some(progress_object.get_progress())
|
||||
}
|
||||
pub fn rearrange_string(&self, id: String, new_index: usize) {
|
||||
pub fn rearrange_string(&self, meta: &Arc<DownloadableMetadata>, new_index: usize) {
|
||||
let mut queue = self.edit();
|
||||
let current_index = get_index_from_id(&mut queue, id).unwrap();
|
||||
let current_index = get_index_from_id(&mut queue, meta).unwrap();
|
||||
let to_move = queue.remove(current_index).unwrap();
|
||||
queue.insert(new_index, to_move);
|
||||
self.command_sender
|
||||
.send(DownloadManagerSignal::UpdateUIQueue)
|
||||
.unwrap();
|
||||
}
|
||||
pub fn cancel(&self, id: String) {
|
||||
pub fn cancel(&self, meta: Arc<DownloadableMetadata>) {
|
||||
self.command_sender
|
||||
.send(DownloadManagerSignal::Remove(id))
|
||||
.send(DownloadManagerSignal::Remove(meta))
|
||||
.unwrap();
|
||||
}
|
||||
pub fn rearrange(&self, current_index: usize, new_index: usize) {
|
||||
@ -170,7 +141,7 @@ impl DownloadManager {
|
||||
let needs_pause = current_index == 0 || new_index == 0;
|
||||
if needs_pause {
|
||||
self.command_sender
|
||||
.send(DownloadManagerSignal::Cancel)
|
||||
.send(DownloadManagerSignal::Stop)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@ -203,20 +174,23 @@ impl DownloadManager {
|
||||
.unwrap();
|
||||
self.terminator.join()
|
||||
}
|
||||
pub fn uninstall_application(&self, id: String) {
|
||||
pub fn uninstall_application(&self, meta: Arc<DownloadableMetadata>) {
|
||||
self.command_sender
|
||||
.send(DownloadManagerSignal::Uninstall(id))
|
||||
.send(DownloadManagerSignal::Uninstall(meta))
|
||||
.unwrap();
|
||||
}
|
||||
pub fn get_sender(&self) -> Sender<DownloadManagerSignal> {
|
||||
self.command_sender.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes in the locked value from .edit() and attempts to
|
||||
/// get the index of whatever id is passed in
|
||||
fn get_index_from_id(
|
||||
queue: &mut MutexGuard<'_, VecDeque<Arc<DownloadableQueueStandin>>>,
|
||||
id: String,
|
||||
queue: &mut MutexGuard<'_, VecDeque<Arc<DownloadableMetadata>>>,
|
||||
meta: &Arc<DownloadableMetadata>,
|
||||
) -> Option<usize> {
|
||||
queue
|
||||
.iter()
|
||||
.position(|download_agent| download_agent.id == id)
|
||||
.position(|download_agent| download_agent == meta)
|
||||
}
|
||||
|
||||
@ -12,19 +12,11 @@ use log::{error, info};
|
||||
use tauri::{AppHandle, Emitter};
|
||||
|
||||
use crate::{
|
||||
db::{set_application_status, ApplicationStatus, ApplicationTransientStatus, Database}, download_manager::{download_manager::{DownloadStatus, DownloadType}, generate_downloadable::generate_downloadable}, downloads::download_agent::{self, GameDownloadAgent}, library::{
|
||||
on_game_complete, push_application_update, QueueUpdateEvent,
|
||||
QueueUpdateEventQueueData, StatsUpdateEvent,
|
||||
}, state::GameStatusManager, DB
|
||||
};
|
||||
download_manager::{download_manager::DownloadStatus, generate_downloadable::generate_downloadable}, 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};
|
||||
|
||||
pub struct DownloadableQueueStandin {
|
||||
pub id: String,
|
||||
pub status: Mutex<DownloadStatus>,
|
||||
pub progress: Arc<ProgressObject>,
|
||||
}
|
||||
pub type DownloadAgent = Arc<Box<dyn Downloadable + Send + Sync>>;
|
||||
pub type CurrentProgressObject = Arc<Mutex<Option<Arc<ProgressObject>>>>;
|
||||
|
||||
@ -163,12 +155,12 @@ impl DownloadManagerBuilder {
|
||||
DownloadManagerSignal::Error(e) => {
|
||||
self.manage_error_signal(e);
|
||||
}
|
||||
//DownloadManagerSignal::UpdateUIQueue => {
|
||||
// self.push_ui_queue_update();
|
||||
//}
|
||||
//DownloadManagerSignal::UpdateUIStats(kbs, time) => {
|
||||
// self.push_ui_stats_update(kbs, time);
|
||||
//}
|
||||
DownloadManagerSignal::UpdateUIQueue => {
|
||||
self.push_ui_queue_update();
|
||||
}
|
||||
DownloadManagerSignal::UpdateUIStats(kbs, time) => {
|
||||
self.push_ui_stats_update(kbs, time);
|
||||
}
|
||||
DownloadManagerSignal::Finish => {
|
||||
self.stop_and_wait_current_download();
|
||||
return Ok(());
|
||||
@ -239,8 +231,7 @@ impl DownloadManagerBuilder {
|
||||
download_agent.on_incomplete(&app_handle);
|
||||
},
|
||||
Err(e) => {
|
||||
download_agent.on_error(&app_handle);
|
||||
error!("error while managing download: {}", e);
|
||||
download_agent.on_error(&app_handle, e.clone());
|
||||
sender.send(DownloadManagerSignal::Error(e)).unwrap();
|
||||
},
|
||||
}
|
||||
@ -272,7 +263,7 @@ impl DownloadManagerBuilder {
|
||||
info!("Got signal Error");
|
||||
let current_agent = self.current_download_agent.clone().unwrap();
|
||||
|
||||
current_agent.on_error(&self.app_handle);
|
||||
current_agent.on_error(&self.app_handle, error.clone());
|
||||
|
||||
self.stop_and_wait_current_download();
|
||||
self.remove_and_cleanup_front_download(¤t_agent.metadata());
|
||||
@ -310,6 +301,28 @@ impl DownloadManagerBuilder {
|
||||
self.manage_cancel_signal(meta);
|
||||
download_agent.on_uninstall(&self.app_handle);
|
||||
}
|
||||
fn push_ui_stats_update(&self, kbs: usize, time: usize) {
|
||||
let event_data = StatsUpdateEvent { speed: kbs, time };
|
||||
|
||||
self.app_handle.emit("update_stats", event_data);
|
||||
}
|
||||
fn push_ui_queue_update(&self) {
|
||||
let registry = &self.download_agent_registry;
|
||||
let queue_objs = registry
|
||||
.iter()
|
||||
.map(|(key, val)| QueueUpdateEventQueueData {
|
||||
meta: DownloadableMetadata::clone(&key),
|
||||
status: val.status(),
|
||||
progress: val.progress().get_progress()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let event_data = QueueUpdateEvent {
|
||||
queue: queue_objs,
|
||||
status: self.status.lock().unwrap().clone(),
|
||||
};
|
||||
self.app_handle.emit("update_queue", event_data);
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Refactored to consolidate this type. It's a monster.
|
||||
@ -317,6 +330,33 @@ pub type DownloadAgent = Arc<Mutex<Box<dyn Downloadable + Send + Sync>>>;
|
||||
|
||||
|
||||
impl DownloadManagerBuilder {
|
||||
fn push_ui_stats_update(&self, kbs: usize, time: usize) {
|
||||
let event_data = StatsUpdateEvent { speed: kbs, time };
|
||||
|
||||
self.app_handle.emit("update_stats", event_data).unwrap();
|
||||
}
|
||||
|
||||
fn push_ui_queue_update(&self) {
|
||||
let queue = self.download_queue.read();
|
||||
let queue_objs: Vec<QueueUpdateEventQueueData> = queue
|
||||
.iter()
|
||||
.map(|interface| QueueUpdateEventQueueData {
|
||||
id: interface.id.clone(),
|
||||
status: interface.status.lock().unwrap().clone(),
|
||||
progress: interface.progress.get_progress(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let status_handle = self.status.lock().unwrap();
|
||||
let status = status_handle.clone();
|
||||
drop(status_handle);
|
||||
|
||||
let event_data = QueueUpdateEvent {
|
||||
queue: queue_objs,
|
||||
status,
|
||||
};
|
||||
self.app_handle.emit("update_queue", event_data).unwrap();
|
||||
}
|
||||
fn uninstall_application(&mut self, id: String) {
|
||||
// Removes the download if it's in the queue
|
||||
self.manage_remove_download_from_queue(id.clone());
|
||||
@ -606,34 +646,6 @@ impl DownloadManagerBuilder {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn push_ui_stats_update(&self, kbs: usize, time: usize) {
|
||||
let event_data = StatsUpdateEvent { speed: kbs, time };
|
||||
|
||||
self.app_handle.emit("update_stats", event_data).unwrap();
|
||||
}
|
||||
|
||||
fn push_ui_queue_update(&self) {
|
||||
let queue = self.download_queue.read();
|
||||
let queue_objs: Vec<QueueUpdateEventQueueData> = queue
|
||||
.iter()
|
||||
.map(|interface| QueueUpdateEventQueueData {
|
||||
id: interface.id.clone(),
|
||||
status: interface.status.lock().unwrap().clone(),
|
||||
progress: interface.progress.get_progress(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let status_handle = self.status.lock().unwrap();
|
||||
let status = status_handle.clone();
|
||||
drop(status_handle);
|
||||
|
||||
let event_data = QueueUpdateEvent {
|
||||
queue: queue_objs,
|
||||
status,
|
||||
};
|
||||
self.app_handle.emit("update_queue", event_data).unwrap();
|
||||
}
|
||||
|
||||
fn stop_and_wait_current_download(&self) {
|
||||
self.set_status(DownloadManagerStatus::Paused);
|
||||
if let Some(current_flag) = &self.active_control_flag {
|
||||
@ -816,4 +828,4 @@ impl DownloadManagerBuilder {
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::{mpsc::Sender, Arc};
|
||||
|
||||
use tauri::AppHandle;
|
||||
|
||||
use super::{
|
||||
application_download_error::ApplicationDownloadError, download_thread_control_flag::DownloadThreadControl, downloadable_metadata::DownloadableMetadata, progress_object::ProgressObject
|
||||
application_download_error::ApplicationDownloadError, download_manager::{DownloadManagerSignal, DownloadStatus}, download_thread_control_flag::DownloadThreadControl, downloadable_metadata::DownloadableMetadata, progress_object::ProgressObject
|
||||
};
|
||||
|
||||
pub trait Downloadable: Send + Sync {
|
||||
fn download(&self) -> Result<bool, ApplicationDownloadError>;
|
||||
fn progress(&self) -> Arc<ProgressObject>;
|
||||
fn control_flag(&self) -> DownloadThreadControl;
|
||||
fn status(&self) -> DownloadStatus;
|
||||
fn metadata(&self) -> Arc<DownloadableMetadata>;
|
||||
fn on_initialised(&self, app_handle: &AppHandle);
|
||||
fn on_error(&self, app_handle: &AppHandle);
|
||||
fn on_error(&self, app_handle: &AppHandle, error: ApplicationDownloadError);
|
||||
fn on_complete(&self, app_handle: &AppHandle);
|
||||
fn on_incomplete(&self, app_handle: &AppHandle);
|
||||
fn on_cancelled(&self, app_handle: &AppHandle);
|
||||
|
||||
@ -1,4 +1,25 @@
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DownloadableMetadata {
|
||||
id: String,
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Clone)]
|
||||
pub enum DownloadType {
|
||||
Game,
|
||||
Tool,
|
||||
DLC,
|
||||
Mod
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Clone)]
|
||||
pub struct DownloadableMetadata {
|
||||
pub id: String,
|
||||
pub version: String,
|
||||
pub download_type: DownloadType
|
||||
}
|
||||
impl DownloadableMetadata {
|
||||
pub fn new(id: String, version: String, download_type: DownloadType) -> Self {
|
||||
Self {
|
||||
id,
|
||||
version,
|
||||
download_type
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,11 +34,11 @@ impl Queue {
|
||||
}
|
||||
/// Either inserts `interface` at the specified index, or appends to
|
||||
/// the back of the deque if index is greater than the length of the deque
|
||||
pub fn insert(&self, interface: DownloadableMetadata, index: usize) {
|
||||
pub fn insert(&self, interface: Arc<DownloadableMetadata>, index: usize) {
|
||||
if self.read().len() > index {
|
||||
self.append(interface);
|
||||
} else {
|
||||
self.edit().insert(index, Arc::new(interface));
|
||||
self.edit().insert(index, interface);
|
||||
}
|
||||
}
|
||||
pub fn append(&self, interface: Arc<DownloadableMetadata>) {
|
||||
|
||||
Reference in New Issue
Block a user