mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-10 12:32:14 +10:00
feat(cache): Added forceOffline in settings and caching games & library
This commit is contained in:
@ -46,7 +46,7 @@ pub enum GameDownloadStatus {
|
||||
}
|
||||
|
||||
// Stuff that shouldn't be synced to disk
|
||||
#[derive(Clone, Serialize)]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub enum ApplicationTransientStatus {
|
||||
Downloading { version_name: String },
|
||||
Uninstalling {},
|
||||
@ -149,7 +149,7 @@ impl DatabaseImpls for DatabaseInterface {
|
||||
let db_path = data_root_dir.join("drop.db");
|
||||
let games_base_dir = data_root_dir.join("games");
|
||||
let logs_root_dir = data_root_dir.join("logs");
|
||||
let cache_dir = data_root_dir.join("cache/");
|
||||
let cache_dir = data_root_dir.join("cache");
|
||||
|
||||
debug!("creating data directory at {:?}", data_root_dir);
|
||||
create_dir_all(data_root_dir.clone()).unwrap();
|
||||
|
||||
@ -48,7 +48,7 @@ pub enum DownloadManagerSignal {
|
||||
Uninstall(DownloadableMetadata),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug)]
|
||||
pub enum DownloadManagerStatus {
|
||||
Downloading,
|
||||
Paused,
|
||||
|
||||
@ -255,7 +255,7 @@ impl DownloadManagerBuilder {
|
||||
}
|
||||
Err(e) => {
|
||||
error!("download {:?} has error {}", download_agent.metadata(), &e);
|
||||
download_agent.on_error(&app_handle, e.clone());
|
||||
download_agent.on_error(&app_handle, &e);
|
||||
sender.send(DownloadManagerSignal::Error(e)).unwrap();
|
||||
}
|
||||
}
|
||||
@ -287,7 +287,7 @@ impl DownloadManagerBuilder {
|
||||
fn manage_error_signal(&mut self, error: ApplicationDownloadError) {
|
||||
debug!("got signal Error");
|
||||
if let Some(current_agent) = self.current_download_agent.clone() {
|
||||
current_agent.on_error(&self.app_handle, error.clone());
|
||||
current_agent.on_error(&self.app_handle, &error);
|
||||
|
||||
self.stop_and_wait_current_download();
|
||||
self.remove_and_cleanup_front_download(¤t_agent.metadata());
|
||||
|
||||
@ -16,7 +16,7 @@ pub trait Downloadable: Send + Sync {
|
||||
fn status(&self) -> DownloadStatus;
|
||||
fn metadata(&self) -> DownloadableMetadata;
|
||||
fn on_initialised(&self, app_handle: &AppHandle);
|
||||
fn on_error(&self, app_handle: &AppHandle, error: ApplicationDownloadError);
|
||||
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);
|
||||
|
||||
@ -8,7 +8,7 @@ use serde_with::SerializeDisplay;
|
||||
use super::{remote_access_error::RemoteAccessError, setup_error::SetupError};
|
||||
|
||||
// TODO: Rename / separate from downloads
|
||||
#[derive(Debug, Clone, SerializeDisplay)]
|
||||
#[derive(Debug, SerializeDisplay)]
|
||||
pub enum ApplicationDownloadError {
|
||||
Communication(RemoteAccessError),
|
||||
Checksum,
|
||||
|
||||
@ -10,7 +10,7 @@ use url::ParseError;
|
||||
|
||||
use super::drop_server_error::DropServerError;
|
||||
|
||||
#[derive(Debug, Clone, SerializeDisplay)]
|
||||
#[derive(Debug, SerializeDisplay)]
|
||||
pub enum RemoteAccessError {
|
||||
FetchError(Arc<reqwest::Error>),
|
||||
ParsingError(ParseError),
|
||||
@ -21,6 +21,7 @@ pub enum RemoteAccessError {
|
||||
InvalidRedirect,
|
||||
ManifestDownloadFailed(StatusCode, String),
|
||||
OutOfSync,
|
||||
Cache(cacache::Error),
|
||||
Generic(String),
|
||||
}
|
||||
|
||||
@ -52,6 +53,7 @@ impl Display for RemoteAccessError {
|
||||
),
|
||||
RemoteAccessError::OutOfSync => write!(f, "server's and client's time are out of sync. Please ensure they are within at least 30 seconds of each other"),
|
||||
RemoteAccessError::Generic(message) => write!(f, "{}", message),
|
||||
RemoteAccessError::Cache(error) => write!(f, "Cache Error: {}", error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use std::sync::Mutex;
|
||||
use tauri::{AppHandle, Manager};
|
||||
|
||||
use crate::{
|
||||
database::db::GameVersion, error::{library_error::LibraryError, remote_access_error::RemoteAccessError}, games::library::{get_current_meta, uninstall_game_logic}, offline, AppState
|
||||
database::db::GameVersion, error::{library_error::LibraryError, remote_access_error::RemoteAccessError}, games::library::{fetch_game_logic_offline, fetch_library_logic_offline, get_current_meta, uninstall_game_logic}, offline, AppState
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -15,17 +15,16 @@ use super::{
|
||||
};
|
||||
|
||||
#[tauri::command]
|
||||
pub fn fetch_library(app: AppHandle) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
let state = app.state::<Mutex<AppState>>();
|
||||
offline!(state, fetch_library_logic, fetch_library_logic, app)
|
||||
pub fn fetch_library(state: tauri::State<'_, Mutex<AppState>>) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
offline!(state, fetch_library_logic, fetch_library_logic_offline, state)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn fetch_game(
|
||||
game_id: String,
|
||||
app: tauri::AppHandle,
|
||||
state: tauri::State<'_, Mutex<AppState>>
|
||||
) -> Result<FetchGameStruct, RemoteAccessError> {
|
||||
fetch_game_logic(game_id, app)
|
||||
offline!(state, fetch_game_logic, fetch_game_logic_offline, game_id, state)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
||||
@ -362,7 +362,7 @@ impl Downloadable for GameDownloadAgent {
|
||||
*self.status.lock().unwrap() = DownloadStatus::Queued;
|
||||
}
|
||||
|
||||
fn on_error(&self, app_handle: &tauri::AppHandle, error: ApplicationDownloadError) {
|
||||
fn on_error(&self, app_handle: &tauri::AppHandle, error: &ApplicationDownloadError) {
|
||||
*self.status.lock().unwrap() = DownloadStatus::Error;
|
||||
app_handle
|
||||
.emit("download_error", error.to_string())
|
||||
|
||||
@ -14,10 +14,11 @@ use crate::download_manager::downloadable_metadata::DownloadableMetadata;
|
||||
use crate::error::remote_access_error::RemoteAccessError;
|
||||
use crate::games::state::{GameStatusManager, GameStatusWithTransient};
|
||||
use crate::remote::auth::generate_authorization_header;
|
||||
use crate::remote::cache::{cache_object, get_cached_object};
|
||||
use crate::remote::requests::make_request;
|
||||
use crate::AppState;
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct FetchGameStruct {
|
||||
game: Game,
|
||||
status: GameStatusWithTransient,
|
||||
@ -66,10 +67,11 @@ pub struct StatsUpdateEvent {
|
||||
pub time: usize,
|
||||
}
|
||||
|
||||
pub fn fetch_library_logic(app: AppHandle) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
pub fn fetch_library_logic(state: tauri::State<'_, Mutex<AppState>>) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
let header = generate_authorization_header();
|
||||
|
||||
let client = reqwest::blocking::Client::new();
|
||||
println!("Making library request");
|
||||
let response = make_request(&client, &["/api/v1/client/user/library"], &[], |f| {
|
||||
f.header("Authorization", header)
|
||||
})?
|
||||
@ -80,10 +82,10 @@ pub fn fetch_library_logic(app: AppHandle) -> Result<Vec<Game>, RemoteAccessErro
|
||||
warn!("{:?}", err);
|
||||
return Err(RemoteAccessError::InvalidResponse(err));
|
||||
}
|
||||
println!("Getting Games");
|
||||
|
||||
let games: Vec<Game> = response.json()?;
|
||||
|
||||
let state = app.state::<Mutex<AppState>>();
|
||||
let mut handle = state.lock().unwrap();
|
||||
|
||||
let mut db_handle = borrow_db_mut_checked();
|
||||
@ -97,17 +99,30 @@ pub fn fetch_library_logic(app: AppHandle) -> Result<Vec<Game>, RemoteAccessErro
|
||||
.insert(game.id.clone(), GameDownloadStatus::Remote {});
|
||||
}
|
||||
}
|
||||
|
||||
drop(handle);
|
||||
drop(db_handle);
|
||||
println!("Caching");
|
||||
cache_object("library", &games)?;
|
||||
|
||||
println!("Finished caching");
|
||||
|
||||
Ok(games)
|
||||
}
|
||||
pub fn fetch_library_logic_offline(_state: tauri::State<'_, Mutex<AppState>>) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
let mut games: Vec<Game> = get_cached_object("library")?;
|
||||
|
||||
let db_handle = borrow_db_checked();
|
||||
|
||||
games.retain(|game| {
|
||||
db_handle.applications.installed_game_version.contains_key(&game.id)
|
||||
});
|
||||
|
||||
Ok(games)
|
||||
}
|
||||
pub fn fetch_game_logic(
|
||||
id: String,
|
||||
app: tauri::AppHandle,
|
||||
state: tauri::State<'_, Mutex<AppState>>
|
||||
) -> Result<FetchGameStruct, RemoteAccessError> {
|
||||
let state = app.state::<Mutex<AppState>>();
|
||||
let mut state_handle = state.lock().unwrap();
|
||||
|
||||
let game = state_handle.games.get(&id);
|
||||
@ -155,9 +170,18 @@ pub fn fetch_game_logic(
|
||||
status,
|
||||
};
|
||||
|
||||
cache_object(id, &data)?;
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
pub fn fetch_game_logic_offline(
|
||||
id: String,
|
||||
_state: tauri::State<'_, Mutex<AppState>>
|
||||
) -> Result<FetchGameStruct, RemoteAccessError> {
|
||||
get_cached_object(id)
|
||||
}
|
||||
|
||||
pub fn fetch_game_verion_options_logic(
|
||||
game_id: String,
|
||||
state: tauri::State<'_, Mutex<AppState>>,
|
||||
|
||||
@ -1,12 +1,27 @@
|
||||
use cacache::Integrity;
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
|
||||
use crate::{database::db::borrow_db_checked, error::remote_access_error::RemoteAccessError};
|
||||
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! offline {
|
||||
($var:expr, $func1:expr, $func2:expr, $( $arg:expr ),* ) => {
|
||||
|
||||
if crate::borrow_db_checked().settings.force_offline || $var.lock().unwrap().status == crate::AppStatus::Offline {
|
||||
$func1( $( $arg ), *)
|
||||
} else {
|
||||
$func2( $( $arg ), *)
|
||||
} else {
|
||||
$func1( $( $arg ), *)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cache_object<'a, K: AsRef<str>, D: Serialize + DeserializeOwned>(key: K, data: &D) -> Result<Integrity, RemoteAccessError> {
|
||||
let bytes = bincode::serialize(data).unwrap();
|
||||
cacache::write_sync(&borrow_db_checked().cache_dir, key, bytes).map_err(|e| RemoteAccessError::Cache(e))
|
||||
}
|
||||
pub fn get_cached_object<'a, K: AsRef<str>, D: Serialize + DeserializeOwned>(key: K) -> Result<D,RemoteAccessError> {
|
||||
let bytes = cacache::read_sync(&borrow_db_checked().cache_dir, key).map_err(|e| RemoteAccessError::Cache(e))?;
|
||||
let data = bincode::deserialize::<D>(&bytes).unwrap();
|
||||
Ok(data)
|
||||
}
|
||||
Reference in New Issue
Block a user