From 772e6a124dca797d659924ba2497a579d1934160 Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sat, 21 Dec 2024 15:09:49 +1100 Subject: [PATCH] feat(tray): background processes and close/open menu --- desktop/pages/queue.vue | 6 +++ .../src-tauri/src/downloads/download_agent.rs | 48 +++++++++++++++++++ .../src/downloads/download_manager.rs | 7 +-- .../src/downloads/download_manager_builder.rs | 35 +++++++------- desktop/src-tauri/src/lib.rs | 45 ++++++++++++++--- 5 files changed, 114 insertions(+), 27 deletions(-) diff --git a/desktop/pages/queue.vue b/desktop/pages/queue.vue index 7d033442..d00466c8 100644 --- a/desktop/pages/queue.vue +++ b/desktop/pages/queue.vue @@ -49,6 +49,12 @@

Loading...

+
+ No items in the queue +
diff --git a/desktop/src-tauri/src/downloads/download_agent.rs b/desktop/src-tauri/src/downloads/download_agent.rs index 30680892..9930a83c 100644 --- a/desktop/src-tauri/src/downloads/download_agent.rs +++ b/desktop/src-tauri/src/downloads/download_agent.rs @@ -7,6 +7,8 @@ use crate::DB; use core::time; use log::{debug, error, info}; use rayon::ThreadPoolBuilder; +use serde::ser::{Error, SerializeMap}; +use serde::{Deserialize, Serialize}; use std::fmt::{Display, Formatter}; use std::fs::{create_dir_all, File}; use std::io; @@ -92,6 +94,30 @@ impl GameDownloadAgent { } } + pub fn from_contexts( + id: String, + version: String, + base_dir: String, + manifest: DropManifest, + contexts: Vec, + sender: Sender, + ) -> Self { + let control_flag = DownloadThreadControl::new(DownloadThreadControlFlag::Stop); + + let me = Self { + id, + version, + control_flag, + manifest: Mutex::new(Some(manifest)), + base_dir, + contexts: Mutex::new(contexts), + progress: Arc::new(ProgressObject::new(0, 0, sender.clone())), + sender, + }; + me.set_progress_object_params(); + me + } + // Blocking pub fn setup_download(&self) -> Result<(), GameDownloadError> { self.ensure_manifest_exists()?; @@ -307,3 +333,25 @@ impl GameDownloadAgent { Ok(()) } } + +#[derive(Serialize, Deserialize)] +pub struct GameDownloadAgentOfflineState { + id: String, + version: String, + base_dir: String, + manifest: DropManifest, + contexts: Vec, +} + +impl GameDownloadAgentOfflineState { + fn to_download_agent(self, sender: Sender) -> GameDownloadAgent { + GameDownloadAgent::from_contexts( + self.id, + self.version, + self.base_dir, + self.manifest, + self.contexts, + sender, + ) + } +} diff --git a/desktop/src-tauri/src/downloads/download_manager.rs b/desktop/src-tauri/src/downloads/download_manager.rs index ffc0b00c..36313a9b 100644 --- a/desktop/src-tauri/src/downloads/download_manager.rs +++ b/desktop/src-tauri/src/downloads/download_manager.rs @@ -30,21 +30,22 @@ pub enum DownloadManagerSignal { /// to the registry and queue Queue(String, String, usize), /// Tells the Manager to stop the current - /// download and return + /// download, sync everything to disk, and + /// then exit Finish, Cancel, /// Any error which occurs in the agent Error(GameDownloadError), /// Pushes UI update Update, - /// Causes the Download Agent status to be synced to disk - Sync(usize), } + pub enum DownloadManagerStatus { Downloading, Paused, Empty, Error(GameDownloadError), + Finished, } #[derive(Serialize, Clone)] diff --git a/desktop/src-tauri/src/downloads/download_manager_builder.rs b/desktop/src-tauri/src/downloads/download_manager_builder.rs index e89a588d..6ccf8c87 100644 --- a/desktop/src-tauri/src/downloads/download_manager_builder.rs +++ b/desktop/src-tauri/src/downloads/download_manager_builder.rs @@ -141,6 +141,19 @@ impl DownloadManagerBuilder { 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 { + current_flag.set(DownloadThreadControlFlag::Stop); + } + + let mut download_thread_lock = self.current_download_thread.lock().unwrap(); + if let Some(current_download_thread) = download_thread_lock.take() { + current_download_thread.join().unwrap(); + } + drop(download_thread_lock); + } + fn sync_download_agent(&self) {} fn remove_and_cleanup_game(&mut self, game_id: &String) -> Arc { @@ -182,12 +195,6 @@ impl DownloadManagerBuilder { DownloadManagerSignal::Queue(game_id, version, target_download_dir) => { self.manage_queue_signal(game_id, version, target_download_dir); } - DownloadManagerSignal::Finish => { - if let Some(active_control_flag) = self.active_control_flag { - active_control_flag.set(DownloadThreadControlFlag::Stop) - } - return Ok(()); - } DownloadManagerSignal::Error(e) => { self.manage_error_signal(e); } @@ -197,8 +204,9 @@ impl DownloadManagerBuilder { DownloadManagerSignal::Update => { self.push_manager_update(); } - DownloadManagerSignal::Sync(index) => { - self.sync_download_agent(); + DownloadManagerSignal::Finish => { + self.stop_and_wait_current_download(); + return Ok(()); } }; } @@ -345,16 +353,7 @@ impl DownloadManagerBuilder { self.sender.send(DownloadManagerSignal::Update).unwrap(); } fn manage_cancel_signal(&mut self) { - self.set_status(DownloadManagerStatus::Paused); - if let Some(current_flag) = &self.active_control_flag { - current_flag.set(DownloadThreadControlFlag::Stop); - } - - let mut download_thread_lock = self.current_download_thread.lock().unwrap(); - if let Some(current_download_thread) = download_thread_lock.take() { - current_download_thread.join().unwrap(); - } - drop(download_thread_lock); + self.stop_and_wait_current_download(); info!("cancel waited for download to finish"); diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index b3ab4319..acecd5f8 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -35,10 +35,11 @@ use std::{ collections::HashMap, sync::{LazyLock, Mutex}, }; -use tauri::menu::{Menu, MenuItem, MenuItemBuilder}; +use tauri::menu::{Menu, MenuItem, MenuItemBuilder, PredefinedMenuItem}; use tauri::tray::TrayIconBuilder; -use tauri::{AppHandle, Manager}; +use tauri::{AppHandle, Manager, RunEvent, WindowEvent}; use tauri_plugin_deep_link::DeepLinkExt; +use url::Url; #[derive(Clone, Copy, Serialize)] pub enum AppStatus { @@ -133,6 +134,12 @@ fn setup(handle: AppHandle) -> AppState { } } +pub fn cleanup_and_exit(app: &AppHandle) { + info!("exiting drop application..."); + + app.exit(0); +} + pub static DB: LazyLock = LazyLock::new(DatabaseInterface::set_up_database); #[cfg_attr(mobile, tauri::mobile_entry_point)] @@ -216,9 +223,13 @@ pub fn run() { let menu = Menu::with_items( app, &[ + &MenuItem::with_id(app, "open", "Open", true, None::<&str>)?, + &PredefinedMenuItem::separator(app)?, + /* &MenuItem::with_id(app, "show_library", "Library", true, None::<&str>)?, &MenuItem::with_id(app, "show_settings", "Settings", true, None::<&str>)?, - &MenuItem::with_id(app, "open", "Open", true, None::<&str>)?, + &PredefinedMenuItem::separator(app)?, + */ &MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?, ], )?; @@ -226,6 +237,18 @@ pub fn run() { let tray = TrayIconBuilder::new() .icon(app.default_window_icon().unwrap().clone()) .menu(&menu) + .on_menu_event(|app, event| match event.id.as_ref() { + "open" => { + app.webview_windows().get("main").unwrap().show().unwrap(); + } + "quit" => { + cleanup_and_exit(app); + } + + _ => { + println!("Menu event not handled: {:?}", event.id); + } + }) .build(app) .expect("error while setting up tray menu"); @@ -260,12 +283,22 @@ pub fn run() { responder.respond(resp); }) + .on_window_event(|window, event| match event { + WindowEvent::CloseRequested { api, .. } => { + window.hide().unwrap(); + api.prevent_close(); + } + _ => (), + }) .build(tauri::generate_context!()) .expect("error while running tauri application"); - app.run(|app_handle, e| match e { + app.run(|app_handle, event| match event { + RunEvent::ExitRequested { code, api, .. } => { + if code.is_none() { + api.prevent_exit(); + } + } _ => {} }); - - info!("exiting drop application..."); }