From 104e90345423dd5ada7b8ca5eaf6ca41fb69b601 Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sun, 24 Nov 2024 21:04:56 +1100 Subject: [PATCH] feat(settings): ability to add more download dirs --- desktop/components/HeaderUserWidget.vue | 2 +- desktop/composables/current-page-engine.ts | 2 +- desktop/package.json | 2 +- desktop/pages/library/[id]/index.vue | 2 +- desktop/pages/settings.vue | 8 +- desktop/pages/settings/downloads.vue | 218 +++++++++++++++++- desktop/src-tauri/Cargo.lock | 28 +-- desktop/src-tauri/src/db.rs | 40 ++-- .../src/downloads/download_commands.rs | 29 +-- desktop/src-tauri/src/lib.rs | 12 +- desktop/src-tauri/src/library.rs | 17 +- desktop/src-tauri/src/remote.rs | 3 +- desktop/yarn.lock | 8 +- 13 files changed, 291 insertions(+), 80 deletions(-) diff --git a/desktop/components/HeaderUserWidget.vue b/desktop/components/HeaderUserWidget.vue index 410ba72d..27f2867d 100644 --- a/desktop/components/HeaderUserWidget.vue +++ b/desktop/components/HeaderUserWidget.vue @@ -21,7 +21,7 @@ leave-to-class="transform opacity-0 scale-95" > diff --git a/desktop/package.json b/desktop/package.json index 163e8f33..49c2009f 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -17,7 +17,7 @@ "@prisma/client": "5.20.0", "@tauri-apps/api": ">=2.0.0", "@tauri-apps/plugin-deep-link": "~2", - "@tauri-apps/plugin-dialog": "~2", + "@tauri-apps/plugin-dialog": "^2.0.1", "@tauri-apps/plugin-shell": ">=2.0.0", "nuxt": "^3.13.0", "scss": "^0.2.4", diff --git a/desktop/pages/library/[id]/index.vue b/desktop/pages/library/[id]/index.vue index 2341cab2..94275bad 100644 --- a/desktop/pages/library/[id]/index.vue +++ b/desktop/pages/library/[id]/index.vue @@ -3,7 +3,7 @@ class="mx-auto w-full relative flex flex-col justify-center pt-64 z-10 overflow-hidden" > -
+

@@ -22,8 +22,8 @@ :is="item.icon" :class="[ itemIdx === currentPageIndex - ? 'text-blue-600' - : 'text-zinc-400 group-hover:text-blue-600', + ? 'text-zinc-100' + : 'text-zinc-400 group-hover:text-zinc-200', 'transition h-6 w-6 shrink-0', ]" aria-hidden="true" diff --git a/desktop/pages/settings/downloads.vue b/desktop/pages/settings/downloads.vue index 27e0f695..0878be79 100644 --- a/desktop/pages/settings/downloads.vue +++ b/desktop/pages/settings/downloads.vue @@ -1,3 +1,217 @@ \ No newline at end of file +
+
+
+
+

+ Install directories +

+

+ This is where Drop will download game files to, and store them + indefinitely while you play. Drop and games may store other + information elsewhere, like saves or mods. +

+
+
+ +
+
+
+
    +
  • +
    + +
    +

    + {{ dir }} +

    +
    +
    +
    + +
    +
  • +
+
+ + + +
+ + +
+
+ + +
+
+
+ +
+ +
+

+ Select an empty directory to add. +

+
+
+
+
+ + Upload + + +
+
+
+
+
+
+

+ {{ error }} +

+
+
+
+
+
+
+
+
+
+ + + diff --git a/desktop/src-tauri/Cargo.lock b/desktop/src-tauri/Cargo.lock index 0b030427..88505d99 100644 --- a/desktop/src-tauri/Cargo.lock +++ b/desktop/src-tauri/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -73,36 +73,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -612,9 +612,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "combine" diff --git a/desktop/src-tauri/src/db.rs b/desktop/src-tauri/src/db.rs index 4daf9844..c6d32e7e 100644 --- a/desktop/src-tauri/src/db.rs +++ b/desktop/src-tauri/src/db.rs @@ -6,7 +6,7 @@ use std::{ }; use directories::BaseDirs; -use log::debug; +use log::{debug, info}; use rustbreak::{deser::Bincode, PathDatabase}; use rustix::path::Arg; use serde::{Deserialize, Serialize}; @@ -68,23 +68,23 @@ impl DatabaseImpls for DatabaseInterface { debug!("Creating games directory"); create_dir_all(games_base_dir.clone()).unwrap(); - let default = Database { - auth: None, - base_url: "".to_string(), - games: DatabaseGames { - install_dirs: vec![games_base_dir.to_str().unwrap().to_string()], - games_statuses: HashMap::new(), - }, - }; - #[allow(clippy::let_and_return)] let exists = fs::exists(db_path.clone()).unwrap(); let db = match exists { true => PathDatabase::load_from_path(db_path).expect("Database loading failed"), false => { + let default = Database { + auth: None, + base_url: "".to_string(), + games: DatabaseGames { + install_dirs: vec![games_base_dir.to_str().unwrap().to_string()], + games_statuses: HashMap::new(), + }, + }; debug!("Creating database at path {}", db_path.as_str().unwrap()); - PathDatabase::create_at_path(db_path, default).expect("Database could not be created") - }, + PathDatabase::create_at_path(db_path, default) + .expect("Database could not be created") + } }; db @@ -114,8 +114,8 @@ pub fn add_new_download_dir(new_dir: String) -> Result<(), String> { let dir_contents = new_dir_path .read_dir() .map_err(|e| format!("Unable to check directory contents: {}", e))?; - if dir_contents.count() == 0 { - return Err("Path is not empty".to_string()); + if dir_contents.count() != 0 { + return Err("Directory is not empty".to_string()); } } else { create_dir_all(new_dir_path) @@ -126,6 +126,18 @@ pub fn add_new_download_dir(new_dir: String) -> Result<(), String> { let mut lock = DB.borrow_data_mut().unwrap(); lock.games.install_dirs.push(new_dir); drop(lock); + DB.save().unwrap(); Ok(()) } + +// Will, in future, return disk/remaining size +// Just returns the directories that have been set up +#[tauri::command] +pub fn fetch_download_dir_stats() -> Result, String> { + let lock = DB.borrow_data().unwrap(); + let directories = lock.games.install_dirs.clone(); + drop(lock); + + Ok(directories) +} diff --git a/desktop/src-tauri/src/downloads/download_commands.rs b/desktop/src-tauri/src/downloads/download_commands.rs index 5b429dfb..56441067 100644 --- a/desktop/src-tauri/src/downloads/download_commands.rs +++ b/desktop/src-tauri/src/downloads/download_commands.rs @@ -2,43 +2,39 @@ use std::sync::Mutex; use log::info; -use crate::{AppError, AppState}; +use crate::AppState; #[tauri::command] pub fn download_game( game_id: String, game_version: String, state: tauri::State<'_, Mutex>, -) -> Result<(), AppError> { - +) -> Result<(), String> { state .lock() .unwrap() .download_manager .queue_game(game_id, game_version, 0) - .map_err(|_| AppError::Signal) + .map_err(|_| "An error occurred while communicating with the download manager.".to_string()) } #[tauri::command] pub fn get_current_game_download_progress( state: tauri::State<'_, Mutex>, -) -> Result { +) -> Result { match state .lock() .unwrap() .download_manager .get_current_game_download_progress() - { - Some(progress) => Ok(progress), - None => Err(AppError::DoesNotExist), - } + { + Some(progress) => Ok(progress), + None => Err("Game does not exist".to_string()), + } } #[tauri::command] -pub fn stop_game_download( - state: tauri::State<'_, Mutex>, - game_id: String -) { +pub fn stop_game_download(state: tauri::State<'_, Mutex>, game_id: String) { info!("Cancelling game download {}", game_id); state .lock() @@ -47,12 +43,7 @@ pub fn stop_game_download( .cancel_download(game_id); } #[tauri::command] -pub fn get_current_write_speed( - state: tauri::State<'_, Mutex>, -) { - -} - +pub fn get_current_write_speed(state: tauri::State<'_, Mutex>) {} /* fn use_download_agent( diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index beb1aeb7..707b787a 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -10,7 +10,7 @@ mod tests; use crate::db::DatabaseImpls; use auth::{auth_initiate, generate_authorization_header, recieve_handshake}; -use db::{add_new_download_dir, DatabaseInterface, DATA_ROOT_DIR}; +use db::{add_new_download_dir, fetch_download_dir_stats, DatabaseInterface, DATA_ROOT_DIR}; use downloads::download_commands::*; use downloads::download_manager::DownloadManagerBuilder; use downloads::download_manager_interface::DownloadManager; @@ -36,12 +36,6 @@ pub enum AppStatus { SignedInNeedsReauth, ServerUnavailable, } -#[derive(Debug, Serialize)] -pub enum AppError { - DoesNotExist, - Signal, - RemoteAccess(String) -} #[derive(Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -65,7 +59,7 @@ pub struct AppState { } #[tauri::command] -fn fetch_state(state: tauri::State<'_, Mutex>) -> Result { +fn fetch_state(state: tauri::State<'_, Mutex>) -> Result { let guard = state.lock().unwrap(); let cloned_state = guard.clone(); drop(guard); @@ -133,12 +127,14 @@ pub fn run() { fetch_library, fetch_game, add_new_download_dir, + fetch_download_dir_stats, // Downloads download_game, get_current_game_download_progress, stop_game_download ]) .plugin(tauri_plugin_shell::init()) + .plugin(tauri_plugin_dialog::init()) .setup(|app| { #[cfg(any(target_os = "linux", all(debug_assertions, windows)))] { diff --git a/desktop/src-tauri/src/library.rs b/desktop/src-tauri/src/library.rs index 11277494..50da6af6 100644 --- a/desktop/src-tauri/src/library.rs +++ b/desktop/src-tauri/src/library.rs @@ -1,5 +1,6 @@ use std::sync::Mutex; +use log::info; use serde::{Deserialize, Serialize}; use serde_json::json; use tauri::{AppHandle, Manager}; @@ -7,7 +8,6 @@ use tauri::{AppHandle, Manager}; use crate::db::DatabaseGameStatus; use crate::db::DatabaseImpls; use crate::remote::RemoteAccessError; -use crate::AppError; use crate::{auth::generate_authorization_header, AppState, DB}; #[derive(serde::Serialize)] @@ -19,7 +19,7 @@ struct FetchGameStruct { #[derive(Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct Game { - game_id: String, + id: String, m_name: String, m_short_description: String, m_description: String, @@ -55,12 +55,12 @@ fn fetch_library_logic(app: AppHandle) -> Result { let mut db_handle = DB.borrow_data_mut().unwrap(); for game in games.iter() { - handle.games.insert(game.game_id.clone(), game.clone()); - if !db_handle.games.games_statuses.contains_key(&game.game_id) { + handle.games.insert(game.id.clone(), game.clone()); + if !db_handle.games.games_statuses.contains_key(&game.id) { db_handle .games .games_statuses - .insert(game.game_id.clone(), DatabaseGameStatus::Remote); + .insert(game.id.clone(), DatabaseGameStatus::Remote); } } @@ -70,9 +70,8 @@ fn fetch_library_logic(app: AppHandle) -> Result { } #[tauri::command] -pub fn fetch_library(app: AppHandle) -> Result { - fetch_library_logic(app) - .map_err(|e| AppError::RemoteAccess(e.to_string())) +pub fn fetch_library(app: AppHandle) -> Result { + fetch_library_logic(app).map_err(|e| e.to_string()) } fn fetch_game_logic(id: String, app: tauri::AppHandle) -> Result { @@ -88,7 +87,7 @@ fn fetch_game_logic(id: String, app: tauri::AppHandle) -> Result write!(f, "HTTP {}", error), - RemoteAccessError::ParsingError(parse_error) => todo!(), RemoteAccessError::InvalidEndpoint => write!(f, "Invalid drop endpoint"), RemoteAccessError::HandshakeFailed => write!(f, "Failed to complete handshake"), RemoteAccessError::GameNotFound => write!(f, "Could not find game on server"), diff --git a/desktop/yarn.lock b/desktop/yarn.lock index da122f89..af475d71 100644 --- a/desktop/yarn.lock +++ b/desktop/yarn.lock @@ -1376,10 +1376,10 @@ dependencies: "@tauri-apps/api" "^2.0.0" -"@tauri-apps/plugin-dialog@~2": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-dialog/-/plugin-dialog-2.0.0.tgz#f1e2840c7f824572a76b375fd1b538a36f28de14" - integrity sha512-ApNkejXP2jpPBSifznPPcHTXxu9/YaRW+eJ+8+nYwqp0lLUtebFHG4QhxitM43wwReHE81WAV1DQ/b+2VBftOA== +"@tauri-apps/plugin-dialog@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@tauri-apps/plugin-dialog/-/plugin-dialog-2.0.1.tgz#cca38f2ef361c6d92495f5aa12154492cf3fa779" + integrity sha512-fnUrNr6EfvTqdls/ufusU7h6UbNFzLKvHk/zTuOiBq01R3dTODqwctZlzakdbfSp/7pNwTKvgKTAgl/NAP/Z0Q== dependencies: "@tauri-apps/api" "^2.0.0"