mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-18 18:51:16 +10:00
feat: Resume download button
Also added DBWrite and DBRead structs to make database management easier Signed-off-by: quexeky <git@quexeky.dev>
This commit is contained in:
@ -103,6 +103,7 @@ const emit = defineEmits<{
|
|||||||
(e: "uninstall"): void;
|
(e: "uninstall"): void;
|
||||||
(e: "kill"): void;
|
(e: "kill"): void;
|
||||||
(e: "options"): void;
|
(e: "options"): void;
|
||||||
|
(e: "resume"): void
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const showDropdown = computed(
|
const showDropdown = computed(
|
||||||
@ -128,6 +129,8 @@ const styles: { [key in GameStatusEnum]: string } = {
|
|||||||
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
||||||
[GameStatusEnum.Running]:
|
[GameStatusEnum.Running]:
|
||||||
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
"bg-zinc-800 text-white hover:bg-zinc-700 focus-visible:outline-zinc-700 hover:bg-zinc-700",
|
||||||
|
[GameStatusEnum.PartiallyInstalled]:
|
||||||
|
"bg-gray-600 text-white hover:bg-gray-500 focus-visible:outline-gray-600 hover:bg-gray-500"
|
||||||
};
|
};
|
||||||
|
|
||||||
const buttonNames: { [key in GameStatusEnum]: string } = {
|
const buttonNames: { [key in GameStatusEnum]: string } = {
|
||||||
@ -139,6 +142,7 @@ const buttonNames: { [key in GameStatusEnum]: string } = {
|
|||||||
[GameStatusEnum.Updating]: "Updating",
|
[GameStatusEnum.Updating]: "Updating",
|
||||||
[GameStatusEnum.Uninstalling]: "Uninstalling",
|
[GameStatusEnum.Uninstalling]: "Uninstalling",
|
||||||
[GameStatusEnum.Running]: "Stop",
|
[GameStatusEnum.Running]: "Stop",
|
||||||
|
[GameStatusEnum.PartiallyInstalled]: "Resume"
|
||||||
};
|
};
|
||||||
|
|
||||||
const buttonIcons: { [key in GameStatusEnum]: Component } = {
|
const buttonIcons: { [key in GameStatusEnum]: Component } = {
|
||||||
@ -150,6 +154,7 @@ const buttonIcons: { [key in GameStatusEnum]: Component } = {
|
|||||||
[GameStatusEnum.Updating]: ArrowDownTrayIcon,
|
[GameStatusEnum.Updating]: ArrowDownTrayIcon,
|
||||||
[GameStatusEnum.Uninstalling]: TrashIcon,
|
[GameStatusEnum.Uninstalling]: TrashIcon,
|
||||||
[GameStatusEnum.Running]: PlayIcon,
|
[GameStatusEnum.Running]: PlayIcon,
|
||||||
|
[GameStatusEnum.PartiallyInstalled]: ArrowDownTrayIcon
|
||||||
};
|
};
|
||||||
|
|
||||||
const buttonActions: { [key in GameStatusEnum]: () => void } = {
|
const buttonActions: { [key in GameStatusEnum]: () => void } = {
|
||||||
@ -161,5 +166,6 @@ const buttonActions: { [key in GameStatusEnum]: () => void } = {
|
|||||||
[GameStatusEnum.Updating]: () => emit("queue"),
|
[GameStatusEnum.Updating]: () => emit("queue"),
|
||||||
[GameStatusEnum.Uninstalling]: () => {},
|
[GameStatusEnum.Uninstalling]: () => {},
|
||||||
[GameStatusEnum.Running]: () => emit("kill"),
|
[GameStatusEnum.Running]: () => emit("kill"),
|
||||||
|
[GameStatusEnum.PartiallyInstalled]: () => emit("resume")
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
@uninstall="() => uninstall()"
|
@uninstall="() => uninstall()"
|
||||||
@kill="() => kill()"
|
@kill="() => kill()"
|
||||||
@options="() => (configureModalOpen = true)"
|
@options="() => (configureModalOpen = true)"
|
||||||
|
@resume="() => console.log('resume')"
|
||||||
:status="status"
|
:status="status"
|
||||||
/>
|
/>
|
||||||
<a
|
<a
|
||||||
@ -495,6 +496,7 @@ const currentImageIndex = ref(0);
|
|||||||
|
|
||||||
const configureModalOpen = ref(false);
|
const configureModalOpen = ref(false);
|
||||||
|
|
||||||
|
|
||||||
async function installFlow() {
|
async function installFlow() {
|
||||||
installFlowOpen.value = true;
|
installFlowOpen.value = true;
|
||||||
versionOptions.value = undefined;
|
versionOptions.value = undefined;
|
||||||
@ -532,6 +534,15 @@ async function install() {
|
|||||||
installLoading.value = false;
|
installLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function resumeDownload() {
|
||||||
|
try {
|
||||||
|
await invoke("resume_download", { game_id: game.value.id, version: status.value.version_name!, install_dir: status.value.install_dir! })
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function launch() {
|
async function launch() {
|
||||||
try {
|
try {
|
||||||
await invoke("launch_game", { id: game.value.id });
|
await invoke("launch_game", { id: game.value.id });
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::database::db::{borrow_db_checked, borrow_db_mut_checked, save_db};
|
use crate::database::db::{borrow_db_checked, borrow_db_mut_checked};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use tauri::AppHandle;
|
use tauri::AppHandle;
|
||||||
use tauri_plugin_autostart::ManagerExt;
|
use tauri_plugin_autostart::ManagerExt;
|
||||||
@ -17,7 +17,6 @@ pub fn toggle_autostart_logic(app: AppHandle, enabled: bool) -> Result<(), Strin
|
|||||||
let mut db_handle = borrow_db_mut_checked();
|
let mut db_handle = borrow_db_mut_checked();
|
||||||
db_handle.settings.autostart = enabled;
|
db_handle.settings.autostart = enabled;
|
||||||
drop(db_handle);
|
drop(db_handle);
|
||||||
save_db();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ use serde_json::Value;
|
|||||||
use crate::{database::db::borrow_db_mut_checked, error::download_manager_error::DownloadManagerError};
|
use crate::{database::db::borrow_db_mut_checked, error::download_manager_error::DownloadManagerError};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
db::{borrow_db_checked, save_db, DATA_ROOT_DIR},
|
db::{borrow_db_checked, DATA_ROOT_DIR},
|
||||||
debug::SystemData,
|
debug::SystemData,
|
||||||
models::data::Settings,
|
models::data::Settings,
|
||||||
};
|
};
|
||||||
@ -26,8 +26,6 @@ pub fn fetch_download_dir_stats() -> Vec<PathBuf> {
|
|||||||
pub fn delete_download_dir(index: usize) {
|
pub fn delete_download_dir(index: usize) {
|
||||||
let mut lock = borrow_db_mut_checked();
|
let mut lock = borrow_db_mut_checked();
|
||||||
lock.applications.install_dirs.remove(index);
|
lock.applications.install_dirs.remove(index);
|
||||||
drop(lock);
|
|
||||||
save_db();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@ -58,7 +56,6 @@ pub fn add_download_dir(new_dir: PathBuf) -> Result<(), DownloadManagerError<()>
|
|||||||
}
|
}
|
||||||
lock.applications.install_dirs.push(new_dir);
|
lock.applications.install_dirs.push(new_dir);
|
||||||
drop(lock);
|
drop(lock);
|
||||||
save_db();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -72,8 +69,6 @@ pub fn update_settings(new_settings: Value) {
|
|||||||
}
|
}
|
||||||
let new_settings: Settings = serde_json::from_value(current_settings).unwrap();
|
let new_settings: Settings = serde_json::from_value(current_settings).unwrap();
|
||||||
db_lock.settings = new_settings;
|
db_lock.settings = new_settings;
|
||||||
drop(db_lock);
|
|
||||||
save_db();
|
|
||||||
}
|
}
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn fetch_settings() -> Settings {
|
pub fn fetch_settings() -> Settings {
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fs::{self, create_dir_all},
|
fs::{self, create_dir_all}, mem::{replace, ManuallyDrop}, ops::{Deref, DerefMut}, path::PathBuf, sync::{LazyLock, Mutex, RwLockReadGuard, RwLockWriteGuard}
|
||||||
path::PathBuf,
|
|
||||||
sync::{LazyLock, Mutex, RwLockReadGuard, RwLockWriteGuard},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
@ -18,7 +16,6 @@ use super::models::data::Database;
|
|||||||
pub static DATA_ROOT_DIR: LazyLock<Mutex<PathBuf>> =
|
pub static DATA_ROOT_DIR: LazyLock<Mutex<PathBuf>> =
|
||||||
LazyLock::new(|| Mutex::new(dirs::data_dir().unwrap().join("drop")));
|
LazyLock::new(|| Mutex::new(dirs::data_dir().unwrap().join("drop")));
|
||||||
|
|
||||||
|
|
||||||
// Custom JSON serializer to support everything we need
|
// Custom JSON serializer to support everything we need
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct DropDatabaseSerializer;
|
pub struct DropDatabaseSerializer;
|
||||||
@ -27,15 +24,16 @@ impl<T: native_model::Model + Serialize + DeserializeOwned> DeSerializer<T>
|
|||||||
for DropDatabaseSerializer
|
for DropDatabaseSerializer
|
||||||
{
|
{
|
||||||
fn serialize(&self, val: &T) -> rustbreak::error::DeSerResult<Vec<u8>> {
|
fn serialize(&self, val: &T) -> rustbreak::error::DeSerResult<Vec<u8>> {
|
||||||
native_model::rmp_serde_1_3::RmpSerde::encode(val).map_err(|e| DeSerError::Internal(e.to_string()))
|
native_model::rmp_serde_1_3::RmpSerde::encode(val)
|
||||||
|
.map_err(|e| DeSerError::Internal(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize<R: std::io::Read>(&self, mut s: R) -> rustbreak::error::DeSerResult<T> {
|
fn deserialize<R: std::io::Read>(&self, mut s: R) -> rustbreak::error::DeSerResult<T> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
s.read_to_end(&mut buf)
|
s.read_to_end(&mut buf)
|
||||||
.map_err(|e| rustbreak::error::DeSerError::Other(e.into()))?;
|
.map_err(|e| rustbreak::error::DeSerError::Other(e.into()))?;
|
||||||
let val =
|
let val = native_model::rmp_serde_1_3::RmpSerde::decode(buf)
|
||||||
native_model::rmp_serde_1_3::RmpSerde::decode(buf).map_err(|e| DeSerError::Internal(e.to_string()))?;
|
.map_err(|e| DeSerError::Internal(e.to_string()))?;
|
||||||
Ok(val)
|
Ok(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,27 +120,35 @@ fn handle_invalid_database(
|
|||||||
PathDatabase::create_at_path(db_path, db).expect("Database could not be created")
|
PathDatabase::create_at_path(db_path, db).expect("Database could not be created")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn borrow_db_checked<'a>() -> RwLockReadGuard<'a, Database> {
|
// To automatically save the database upon drop
|
||||||
match DB.borrow_data() {
|
pub struct DBRead<'a>(RwLockReadGuard<'a, Database>);
|
||||||
Ok(data) => data,
|
pub struct DBWrite<'a>(ManuallyDrop<RwLockWriteGuard<'a, Database>>);
|
||||||
Err(e) => {
|
impl<'a> Deref for DBWrite<'a> {
|
||||||
error!("database borrow failed with error {}", e);
|
type Target = RwLockWriteGuard<'a, Database>;
|
||||||
panic!("database borrow failed with error {}", e);
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'a> Deref for DBRead<'a> {
|
||||||
|
type Target = RwLockReadGuard<'a, Database>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> DerefMut for DBWrite<'a> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> Drop for DBWrite<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ManuallyDrop::drop(&mut self.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn borrow_db_mut_checked<'a>() -> RwLockWriteGuard<'a, Database> {
|
|
||||||
match DB.borrow_data_mut() {
|
|
||||||
Ok(data) => data,
|
|
||||||
Err(e) => {
|
|
||||||
error!("database borrow mut failed with error {}", e);
|
|
||||||
panic!("database borrow mut failed with error {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn save_db() {
|
|
||||||
match DB.save() {
|
match DB.save() {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -151,3 +157,24 @@ pub fn save_db() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
pub fn borrow_db_checked<'a>() -> DBRead<'a> {
|
||||||
|
|
||||||
|
match DB.borrow_data() {
|
||||||
|
Ok(data) => DBRead(data),
|
||||||
|
Err(e) => {
|
||||||
|
error!("database borrow failed with error {}", e);
|
||||||
|
panic!("database borrow failed with error {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn borrow_db_mut_checked<'a>() -> DBWrite<'a> {
|
||||||
|
match DB.borrow_data_mut() {
|
||||||
|
Ok(data) => DBWrite(ManuallyDrop::new(data)),
|
||||||
|
Err(e) => {
|
||||||
|
error!("database borrow mut failed with error {}", e);
|
||||||
|
panic!("database borrow mut failed with error {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,19 +1,29 @@
|
|||||||
|
use crate::database::models::data::{Database, DatabaseCompatInfo};
|
||||||
|
|
||||||
pub mod data {
|
pub mod data {
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use native_model::{native_model, Model};
|
use native_model::{native_model, Model};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub type GameVersion = v1::GameVersion;
|
pub type GameVersion = v1::GameVersion;
|
||||||
pub type Database = v2::Database;
|
pub type Database = v3::Database;
|
||||||
pub type Settings = v1::Settings;
|
pub type Settings = v1::Settings;
|
||||||
pub type DatabaseAuth = v1::DatabaseAuth;
|
pub type DatabaseAuth = v1::DatabaseAuth;
|
||||||
|
|
||||||
pub type GameDownloadStatus = v1::GameDownloadStatus;
|
pub type GameDownloadStatus = v2::GameDownloadStatus;
|
||||||
pub type ApplicationTransientStatus = v1::ApplicationTransientStatus;
|
pub type ApplicationTransientStatus = v1::ApplicationTransientStatus;
|
||||||
pub type DownloadableMetadata = v1::DownloadableMetadata;
|
pub type DownloadableMetadata = v1::DownloadableMetadata;
|
||||||
pub type DownloadType = v1::DownloadType;
|
pub type DownloadType = v1::DownloadType;
|
||||||
pub type DatabaseApplications = v1::DatabaseApplications;
|
pub type DatabaseApplications = v2::DatabaseApplications;
|
||||||
pub type DatabaseCompatInfo = v2::DatabaseCompatInfo;
|
pub type DatabaseCompatInfo = v2::DatabaseCompatInfo;
|
||||||
|
|
||||||
|
use std::{collections::HashMap, process::Command};
|
||||||
|
|
||||||
|
use serde_with::serde_as;
|
||||||
|
|
||||||
|
use crate::process::process_manager::UMU_LAUNCHER_EXECUTABLE;
|
||||||
|
|
||||||
pub mod v1 {
|
pub mod v1 {
|
||||||
use crate::process::process_manager::Platform;
|
use crate::process::process_manager::Platform;
|
||||||
use serde_with::serde_as;
|
use serde_with::serde_as;
|
||||||
@ -102,7 +112,7 @@ pub mod data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stuff that shouldn't be synced to disk
|
// Stuff that shouldn't be synced to disk
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||||
pub enum ApplicationTransientStatus {
|
pub enum ApplicationTransientStatus {
|
||||||
Downloading { version_name: String },
|
Downloading { version_name: String },
|
||||||
Uninstalling {},
|
Uninstalling {},
|
||||||
@ -164,12 +174,126 @@ pub mod data {
|
|||||||
pub mod v2 {
|
pub mod v2 {
|
||||||
use std::{collections::HashMap, path::PathBuf, process::Command};
|
use std::{collections::HashMap, path::PathBuf, process::Command};
|
||||||
|
|
||||||
|
use serde_with::serde_as;
|
||||||
|
|
||||||
use crate::process::process_manager::UMU_LAUNCHER_EXECUTABLE;
|
use crate::process::process_manager::UMU_LAUNCHER_EXECUTABLE;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[native_model(id = 1, version = 2, with = native_model::rmp_serde_1_3::RmpSerde)]
|
#[native_model(id = 1, version = 2, with = native_model::rmp_serde_1_3::RmpSerde)]
|
||||||
#[derive(Serialize, Deserialize, Clone, Default)]
|
#[derive(Serialize, Deserialize, Clone, Default)]
|
||||||
|
pub struct Database {
|
||||||
|
#[serde(default)]
|
||||||
|
pub settings: Settings,
|
||||||
|
pub auth: Option<DatabaseAuth>,
|
||||||
|
pub base_url: String,
|
||||||
|
pub applications: v1::DatabaseApplications,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub prev_database: Option<PathBuf>,
|
||||||
|
pub cache_dir: PathBuf,
|
||||||
|
pub compat_info: Option<DatabaseCompatInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[native_model(id = 8, version = 2, with = native_model::rmp_serde_1_3::RmpSerde)]
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Default)]
|
||||||
|
|
||||||
|
pub struct DatabaseCompatInfo {
|
||||||
|
pub umu_installed: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<v1::Database> for Database {
|
||||||
|
fn from(value: v1::Database) -> Self {
|
||||||
|
Self {
|
||||||
|
settings: value.settings,
|
||||||
|
auth: value.auth,
|
||||||
|
base_url: value.base_url,
|
||||||
|
applications: value.applications,
|
||||||
|
prev_database: value.prev_database,
|
||||||
|
cache_dir: value.cache_dir,
|
||||||
|
compat_info: crate::database::models::Database::create_new_compat_info(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Strings are version names for a particular game
|
||||||
|
#[derive(Serialize, Clone, Deserialize, Debug)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
#[native_model(id = 5, version = 2, with = native_model::rmp_serde_1_3::RmpSerde)]
|
||||||
|
pub enum GameDownloadStatus {
|
||||||
|
Remote {},
|
||||||
|
SetupRequired {
|
||||||
|
version_name: String,
|
||||||
|
install_dir: String,
|
||||||
|
},
|
||||||
|
Installed {
|
||||||
|
version_name: String,
|
||||||
|
install_dir: String,
|
||||||
|
},
|
||||||
|
PartiallyInstalled {
|
||||||
|
version_name: String,
|
||||||
|
install_dir: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
impl From<v1::GameDownloadStatus> for GameDownloadStatus {
|
||||||
|
fn from(value: v1::GameDownloadStatus) -> Self {
|
||||||
|
match value {
|
||||||
|
v1::GameDownloadStatus::Remote {} => Self::Remote {},
|
||||||
|
v1::GameDownloadStatus::SetupRequired {
|
||||||
|
version_name,
|
||||||
|
install_dir,
|
||||||
|
} => Self::SetupRequired {
|
||||||
|
version_name,
|
||||||
|
install_dir,
|
||||||
|
},
|
||||||
|
v1::GameDownloadStatus::Installed {
|
||||||
|
version_name,
|
||||||
|
install_dir,
|
||||||
|
} => Self::Installed {
|
||||||
|
version_name,
|
||||||
|
install_dir,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[serde_as]
|
||||||
|
#[derive(Serialize, Clone, Deserialize, Default)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[native_model(id = 3, version = 2, with = native_model::rmp_serde_1_3::RmpSerde)]
|
||||||
|
pub struct DatabaseApplications {
|
||||||
|
pub install_dirs: Vec<PathBuf>,
|
||||||
|
// Guaranteed to exist if the game also exists in the app state map
|
||||||
|
pub game_statuses: HashMap<String, GameDownloadStatus>,
|
||||||
|
pub game_versions: HashMap<String, HashMap<String, GameVersion>>,
|
||||||
|
pub installed_game_version: HashMap<String, DownloadableMetadata>,
|
||||||
|
|
||||||
|
#[serde(skip)]
|
||||||
|
pub transient_statuses: HashMap<DownloadableMetadata, ApplicationTransientStatus>,
|
||||||
|
}
|
||||||
|
impl From<v1::DatabaseApplications> for DatabaseApplications {
|
||||||
|
fn from(value: v1::DatabaseApplications) -> Self {
|
||||||
|
Self {
|
||||||
|
game_statuses: value
|
||||||
|
.game_statuses
|
||||||
|
.into_iter()
|
||||||
|
.map(|x| (x.0, x.1.into()))
|
||||||
|
.collect::<HashMap<String, GameDownloadStatus>>(),
|
||||||
|
install_dirs: value.install_dirs,
|
||||||
|
game_versions: value.game_versions,
|
||||||
|
installed_game_version: value.installed_game_version,
|
||||||
|
transient_statuses: value.transient_statuses,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mod v3 {
|
||||||
|
use std::{collections::HashMap, path::PathBuf, process::Command};
|
||||||
|
|
||||||
|
use serde_with::serde_as;
|
||||||
|
|
||||||
|
use crate::process::process_manager::UMU_LAUNCHER_EXECUTABLE;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
#[native_model(id = 1, version = 3, with = native_model::rmp_serde_1_3::RmpSerde)]
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Default)]
|
||||||
pub struct Database {
|
pub struct Database {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub settings: Settings,
|
pub settings: Settings,
|
||||||
@ -181,14 +305,20 @@ pub mod data {
|
|||||||
pub cache_dir: PathBuf,
|
pub cache_dir: PathBuf,
|
||||||
pub compat_info: Option<DatabaseCompatInfo>,
|
pub compat_info: Option<DatabaseCompatInfo>,
|
||||||
}
|
}
|
||||||
|
impl From<v2::Database> for Database {
|
||||||
#[native_model(id = 8, version = 2, with = native_model::rmp_serde_1_3::RmpSerde)]
|
fn from(value: v2::Database) -> Self {
|
||||||
#[derive(Serialize, Deserialize, Clone, Default)]
|
Self {
|
||||||
|
settings: value.settings,
|
||||||
pub struct DatabaseCompatInfo {
|
auth: value.auth,
|
||||||
umu_installed: bool,
|
base_url: value.base_url,
|
||||||
|
applications: value.applications.into(),
|
||||||
|
prev_database: value.prev_database,
|
||||||
|
cache_dir: value.cache_dir,
|
||||||
|
compat_info: Database::create_new_compat_info(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Database {
|
impl Database {
|
||||||
fn create_new_compat_info() -> Option<DatabaseCompatInfo> {
|
fn create_new_compat_info() -> Option<DatabaseCompatInfo> {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
@ -222,19 +352,4 @@ pub mod data {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<v1::Database> for Database {
|
|
||||||
fn from(value: v1::Database) -> Self {
|
|
||||||
Self {
|
|
||||||
settings: value.settings,
|
|
||||||
auth: value.auth,
|
|
||||||
base_url: value.base_url,
|
|
||||||
applications: value.applications,
|
|
||||||
prev_database: value.prev_database,
|
|
||||||
cache_dir: value.cache_dir,
|
|
||||||
compat_info: Database::create_new_compat_info(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,13 +37,15 @@ pub fn fetch_game(
|
|||||||
game_id: String,
|
game_id: String,
|
||||||
state: tauri::State<'_, Mutex<AppState>>,
|
state: tauri::State<'_, Mutex<AppState>>,
|
||||||
) -> Result<FetchGameStruct, RemoteAccessError> {
|
) -> Result<FetchGameStruct, RemoteAccessError> {
|
||||||
offline!(
|
let res = offline!(
|
||||||
state,
|
state,
|
||||||
fetch_game_logic,
|
fetch_game_logic,
|
||||||
fetch_game_logic_offline,
|
fetch_game_logic_offline,
|
||||||
game_id,
|
game_id,
|
||||||
state
|
state
|
||||||
)
|
);
|
||||||
|
println!("Res: {:?}", &res);
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
download_manager::{
|
database::db::borrow_db_checked, download_manager::{download_manager::DownloadManagerSignal, downloadable::Downloadable}, error::download_manager_error::DownloadManagerError, AppState
|
||||||
download_manager::DownloadManagerSignal, downloadable::Downloadable,
|
|
||||||
}, error::download_manager_error::DownloadManagerError, AppState
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::download_agent::GameDownloadAgent;
|
use super::download_agent::GameDownloadAgent;
|
||||||
@ -16,7 +14,7 @@ pub fn download_game(
|
|||||||
state: tauri::State<'_, Mutex<AppState>>,
|
state: tauri::State<'_, Mutex<AppState>>,
|
||||||
) -> Result<(), DownloadManagerError<DownloadManagerSignal>> {
|
) -> Result<(), DownloadManagerError<DownloadManagerSignal>> {
|
||||||
let sender = state.lock().unwrap().download_manager.get_sender();
|
let sender = state.lock().unwrap().download_manager.get_sender();
|
||||||
let game_download_agent = Arc::new(Box::new(GameDownloadAgent::new(
|
let game_download_agent = Arc::new(Box::new(GameDownloadAgent::new_from_index(
|
||||||
game_id,
|
game_id,
|
||||||
game_version,
|
game_version,
|
||||||
install_dir,
|
install_dir,
|
||||||
@ -28,3 +26,18 @@ pub fn download_game(
|
|||||||
.download_manager
|
.download_manager
|
||||||
.queue_download(game_download_agent)?)
|
.queue_download(game_download_agent)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn resume_download(
|
||||||
|
game_id: String,
|
||||||
|
version: String,
|
||||||
|
install_dir: String,
|
||||||
|
state: tauri::State<'_, Mutex<AppState>>,
|
||||||
|
) -> Result<(), DownloadManagerError<DownloadManagerSignal>> {
|
||||||
|
let sender = state.lock().unwrap().download_manager.get_sender();
|
||||||
|
let game_download_agent = Arc::new(Box::new(GameDownloadAgent::new(
|
||||||
|
game_id, version, install_dir.into(), sender
|
||||||
|
)) as Box<dyn Downloadable + Send + Sync>);
|
||||||
|
Ok(state.lock().unwrap().download_manager.queue_download(game_download_agent)?)
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::auth::generate_authorization_header;
|
use crate::auth::generate_authorization_header;
|
||||||
use crate::database::db::borrow_db_checked;
|
use crate::database::db::{borrow_db_checked, borrow_db_mut_checked};
|
||||||
use crate::database::models::data::{
|
use crate::database::models::data::{
|
||||||
ApplicationTransientStatus, DownloadType, DownloadableMetadata, GameDownloadStatus,
|
ApplicationTransientStatus, DownloadType, DownloadableMetadata, GameDownloadStatus,
|
||||||
};
|
};
|
||||||
@ -19,11 +19,11 @@ use log::{debug, error, info};
|
|||||||
use rayon::ThreadPoolBuilder;
|
use rayon::ThreadPoolBuilder;
|
||||||
use slice_deque::SliceDeque;
|
use slice_deque::SliceDeque;
|
||||||
use std::fs::{create_dir_all, File, OpenOptions};
|
use std::fs::{create_dir_all, File, OpenOptions};
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use tauri::{AppHandle, Emitter};
|
use tauri::{AppHandle, Emitter, Manager};
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use rustix::fs::{fallocate, FallocateFlags};
|
use rustix::fs::{fallocate, FallocateFlags};
|
||||||
@ -45,19 +45,27 @@ pub struct GameDownloadAgent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GameDownloadAgent {
|
impl GameDownloadAgent {
|
||||||
pub fn new(
|
pub fn new_from_index(
|
||||||
id: String,
|
id: String,
|
||||||
version: String,
|
version: String,
|
||||||
target_download_dir: usize,
|
target_download_dir: usize,
|
||||||
sender: Sender<DownloadManagerSignal>,
|
sender: Sender<DownloadManagerSignal>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// Don't run by default
|
|
||||||
let control_flag = DownloadThreadControl::new(DownloadThreadControlFlag::Stop);
|
|
||||||
|
|
||||||
let db_lock = borrow_db_checked();
|
let db_lock = borrow_db_checked();
|
||||||
let base_dir = db_lock.applications.install_dirs[target_download_dir].clone();
|
let base_dir = db_lock.applications.install_dirs[target_download_dir].clone();
|
||||||
drop(db_lock);
|
drop(db_lock);
|
||||||
|
|
||||||
|
Self::new(id, version, base_dir, sender)
|
||||||
|
}
|
||||||
|
pub fn new(
|
||||||
|
id: String,
|
||||||
|
version: String,
|
||||||
|
base_dir: PathBuf,
|
||||||
|
sender: Sender<DownloadManagerSignal>,
|
||||||
|
) -> Self {
|
||||||
|
// Don't run by default
|
||||||
|
let control_flag = DownloadThreadControl::new(DownloadThreadControlFlag::Stop);
|
||||||
|
|
||||||
let base_dir_path = Path::new(&base_dir);
|
let base_dir_path = Path::new(&base_dir);
|
||||||
let data_base_dir_path = base_dir_path.join(id.clone());
|
let data_base_dir_path = base_dir_path.join(id.clone());
|
||||||
|
|
||||||
@ -204,7 +212,12 @@ impl GameDownloadAgent {
|
|||||||
let container = path.parent().unwrap();
|
let container = path.parent().unwrap();
|
||||||
create_dir_all(container).unwrap();
|
create_dir_all(container).unwrap();
|
||||||
|
|
||||||
let file = OpenOptions::new().read(true).write(true).create(true).open(path.clone()).unwrap();
|
let file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(path.clone())
|
||||||
|
.unwrap();
|
||||||
let mut running_offset = 0;
|
let mut running_offset = 0;
|
||||||
|
|
||||||
for (index, length) in chunk.lengths.iter().enumerate() {
|
for (index, length) in chunk.lengths.iter().enumerate() {
|
||||||
@ -260,7 +273,12 @@ impl GameDownloadAgent {
|
|||||||
let progress_handle = ProgressHandle::new(progress, self.progress.clone());
|
let progress_handle = ProgressHandle::new(progress, self.progress.clone());
|
||||||
|
|
||||||
// If we've done this one already, skip it
|
// If we've done this one already, skip it
|
||||||
if self.completed_contexts.lock().unwrap().contains(&context.checksum) {
|
if self
|
||||||
|
.completed_contexts
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.contains(&context.checksum)
|
||||||
|
{
|
||||||
progress_handle.skip(context.length);
|
progress_handle.skip(context.length);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -384,7 +402,7 @@ impl Downloadable for GameDownloadAgent {
|
|||||||
|
|
||||||
error!("error while managing download: {}", error);
|
error!("error while managing download: {}", error);
|
||||||
|
|
||||||
let mut handle = DB.borrow_data_mut().unwrap();
|
let mut handle = borrow_db_mut_checked();
|
||||||
handle
|
handle
|
||||||
.applications
|
.applications
|
||||||
.transient_statuses
|
.transient_statuses
|
||||||
@ -404,12 +422,41 @@ impl Downloadable for GameDownloadAgent {
|
|||||||
fn on_incomplete(&self, app_handle: &tauri::AppHandle) {
|
fn on_incomplete(&self, app_handle: &tauri::AppHandle) {
|
||||||
let meta = self.metadata();
|
let meta = self.metadata();
|
||||||
*self.status.lock().unwrap() = DownloadStatus::Queued;
|
*self.status.lock().unwrap() = DownloadStatus::Queued;
|
||||||
|
borrow_db_mut_checked().applications.game_statuses.insert(
|
||||||
|
self.id.clone(),
|
||||||
|
GameDownloadStatus::PartiallyInstalled {
|
||||||
|
version_name: self.version.clone(),
|
||||||
|
install_dir: self.stored_manifest.base_path.to_string_lossy().to_string(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
borrow_db_mut_checked()
|
||||||
|
.applications
|
||||||
|
.installed_game_version
|
||||||
|
.insert(self.id.clone(), self.metadata());
|
||||||
|
borrow_db_mut_checked().applications.game_statuses.insert(
|
||||||
|
self.id.clone(),
|
||||||
|
GameDownloadStatus::PartiallyInstalled {
|
||||||
|
version_name: self.version.clone(),
|
||||||
|
install_dir: self.stored_manifest.base_path.to_string_lossy().to_string(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
app_handle
|
app_handle
|
||||||
.emit(
|
.emit(
|
||||||
&format!("update_game/{}", meta.id),
|
&format!("update_game/{}", meta.id),
|
||||||
GameUpdateEvent {
|
GameUpdateEvent {
|
||||||
game_id: meta.id.clone(),
|
game_id: meta.id.clone(),
|
||||||
status: (Some(GameDownloadStatus::Remote {}), None),
|
status: (
|
||||||
|
Some(GameDownloadStatus::PartiallyInstalled {
|
||||||
|
version_name: self.version.clone(),
|
||||||
|
install_dir: self
|
||||||
|
.stored_manifest
|
||||||
|
.base_path
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string(),
|
||||||
|
}),
|
||||||
|
None,
|
||||||
|
),
|
||||||
version: None,
|
version: None,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use tauri::Emitter;
|
use tauri::Emitter;
|
||||||
use tauri::AppHandle;
|
use tauri::AppHandle;
|
||||||
|
|
||||||
use crate::database::db::{borrow_db_checked, borrow_db_mut_checked, save_db};
|
use crate::database::db::{borrow_db_checked, borrow_db_mut_checked};
|
||||||
use crate::database::models::data::{
|
use crate::database::models::data::{
|
||||||
ApplicationTransientStatus, DownloadableMetadata, GameDownloadStatus, GameVersion,
|
ApplicationTransientStatus, DownloadableMetadata, GameDownloadStatus, GameVersion,
|
||||||
};
|
};
|
||||||
@ -18,9 +18,9 @@ use crate::games::state::{GameStatusManager, GameStatusWithTransient};
|
|||||||
use crate::remote::auth::generate_authorization_header;
|
use crate::remote::auth::generate_authorization_header;
|
||||||
use crate::remote::cache::{cache_object, get_cached_object, get_cached_object_db};
|
use crate::remote::cache::{cache_object, get_cached_object, get_cached_object_db};
|
||||||
use crate::remote::requests::make_request;
|
use crate::remote::requests::make_request;
|
||||||
use crate::{AppState, DB};
|
use crate::AppState;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct FetchGameStruct {
|
pub struct FetchGameStruct {
|
||||||
game: Game,
|
game: Game,
|
||||||
status: GameStatusWithTransient,
|
status: GameStatusWithTransient,
|
||||||
@ -144,7 +144,7 @@ pub fn fetch_game_logic(
|
|||||||
) -> Result<FetchGameStruct, RemoteAccessError> {
|
) -> Result<FetchGameStruct, RemoteAccessError> {
|
||||||
let mut state_handle = state.lock().unwrap();
|
let mut state_handle = state.lock().unwrap();
|
||||||
|
|
||||||
let handle = DB.borrow_data().unwrap();
|
let handle = borrow_db_checked();
|
||||||
|
|
||||||
let metadata_option = handle.applications.installed_game_version.get(&id);
|
let metadata_option = handle.applications.installed_game_version.get(&id);
|
||||||
let version = match metadata_option {
|
let version = match metadata_option {
|
||||||
@ -220,7 +220,7 @@ pub fn fetch_game_logic_offline(
|
|||||||
id: String,
|
id: String,
|
||||||
_state: tauri::State<'_, Mutex<AppState>>,
|
_state: tauri::State<'_, Mutex<AppState>>,
|
||||||
) -> Result<FetchGameStruct, RemoteAccessError> {
|
) -> Result<FetchGameStruct, RemoteAccessError> {
|
||||||
let handle = DB.borrow_data().unwrap();
|
let handle = borrow_db_checked();
|
||||||
let metadata_option = handle.applications.installed_game_version.get(&id);
|
let metadata_option = handle.applications.installed_game_version.get(&id);
|
||||||
let version = match metadata_option {
|
let version = match metadata_option {
|
||||||
None => None,
|
None => None,
|
||||||
@ -341,7 +341,6 @@ pub fn uninstall_game_logic(meta: DownloadableMetadata, app_handle: &AppHandle)
|
|||||||
.entry(meta.id.clone())
|
.entry(meta.id.clone())
|
||||||
.and_modify(|e| *e = GameDownloadStatus::Remote {});
|
.and_modify(|e| *e = GameDownloadStatus::Remote {});
|
||||||
drop(db_handle);
|
drop(db_handle);
|
||||||
save_db();
|
|
||||||
|
|
||||||
debug!("uninstalled game id {}", &meta.id);
|
debug!("uninstalled game id {}", &meta.id);
|
||||||
app_handle.emit("update_library", {}).unwrap();
|
app_handle.emit("update_library", {}).unwrap();
|
||||||
@ -404,7 +403,6 @@ pub fn on_game_complete(
|
|||||||
.insert(meta.id.clone(), meta.clone());
|
.insert(meta.id.clone(), meta.clone());
|
||||||
|
|
||||||
drop(handle);
|
drop(handle);
|
||||||
save_db();
|
|
||||||
|
|
||||||
let status = if game_version.setup_command.is_empty() {
|
let status = if game_version.setup_command.is_empty() {
|
||||||
GameDownloadStatus::Installed {
|
GameDownloadStatus::Installed {
|
||||||
@ -424,7 +422,6 @@ pub fn on_game_complete(
|
|||||||
.game_statuses
|
.game_statuses
|
||||||
.insert(meta.id.clone(), status.clone());
|
.insert(meta.id.clone(), status.clone());
|
||||||
drop(db_handle);
|
drop(db_handle);
|
||||||
save_db();
|
|
||||||
app_handle
|
app_handle
|
||||||
.emit(
|
.emit(
|
||||||
&format!("update_game/{}", meta.id),
|
&format!("update_game/{}", meta.id),
|
||||||
@ -468,7 +465,7 @@ pub fn update_game_configuration(
|
|||||||
game_id: String,
|
game_id: String,
|
||||||
options: FrontendGameOptions,
|
options: FrontendGameOptions,
|
||||||
) -> Result<(), LibraryError> {
|
) -> Result<(), LibraryError> {
|
||||||
let mut handle = DB.borrow_data_mut().unwrap();
|
let mut handle = borrow_db_mut_checked();
|
||||||
let installed_version = handle
|
let installed_version = handle
|
||||||
.applications
|
.applications
|
||||||
.installed_game_version
|
.installed_game_version
|
||||||
@ -499,8 +496,6 @@ pub fn update_game_configuration(
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(version.to_string(), existing_configuration);
|
.insert(version.to_string(), existing_configuration);
|
||||||
|
|
||||||
drop(handle);
|
|
||||||
save_db();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ mod error;
|
|||||||
mod process;
|
mod process;
|
||||||
mod remote;
|
mod remote;
|
||||||
|
|
||||||
use crate::database::db::DatabaseImpls;
|
use crate::{database::db::DatabaseImpls, games::downloads::commands::resume_download};
|
||||||
use client::{
|
use client::{
|
||||||
autostart::{get_autostart_enabled, sync_autostart_on_startup, toggle_autostart},
|
autostart::{get_autostart_enabled, sync_autostart_on_startup, toggle_autostart},
|
||||||
cleanup::{cleanup_and_exit, quit},
|
cleanup::{cleanup_and_exit, quit},
|
||||||
@ -156,6 +156,7 @@ fn setup(handle: AppHandle) -> AppState<'static> {
|
|||||||
for (game_id, status) in statuses.into_iter() {
|
for (game_id, status) in statuses.into_iter() {
|
||||||
match status {
|
match status {
|
||||||
GameDownloadStatus::Remote {} => {}
|
GameDownloadStatus::Remote {} => {}
|
||||||
|
GameDownloadStatus::PartiallyInstalled { .. } => {},
|
||||||
GameDownloadStatus::SetupRequired {
|
GameDownloadStatus::SetupRequired {
|
||||||
version_name: _,
|
version_name: _,
|
||||||
install_dir,
|
install_dir,
|
||||||
@ -173,7 +174,7 @@ fn setup(handle: AppHandle) -> AppState<'static> {
|
|||||||
if !install_dir_path.exists() {
|
if !install_dir_path.exists() {
|
||||||
missing_games.push(game_id);
|
missing_games.push(game_id);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,6 +260,7 @@ pub fn run() {
|
|||||||
delete_game_in_collection,
|
delete_game_in_collection,
|
||||||
// Downloads
|
// Downloads
|
||||||
download_game,
|
download_game,
|
||||||
|
resume_download,
|
||||||
move_download_in_queue,
|
move_download_in_queue,
|
||||||
pause_downloads,
|
pause_downloads,
|
||||||
resume_downloads,
|
resume_downloads,
|
||||||
|
|||||||
@ -193,6 +193,9 @@ impl ProcessManager<'_> {
|
|||||||
version_name,
|
version_name,
|
||||||
install_dir,
|
install_dir,
|
||||||
} => (version_name, install_dir),
|
} => (version_name, install_dir),
|
||||||
|
GameDownloadStatus::PartiallyInstalled {
|
||||||
|
version_name, install_dir
|
||||||
|
} => (version_name, install_dir),
|
||||||
_ => return Err(ProcessError::NotDownloaded),
|
_ => return Err(ProcessError::NotDownloaded),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -248,7 +251,11 @@ impl ProcessManager<'_> {
|
|||||||
version_name: _,
|
version_name: _,
|
||||||
install_dir: _,
|
install_dir: _,
|
||||||
} => (&game_version.setup_command, &game_version.setup_args),
|
} => (&game_version.setup_command, &game_version.setup_args),
|
||||||
GameDownloadStatus::Remote {} => unreachable!("nuh uh"),
|
GameDownloadStatus::PartiallyInstalled {
|
||||||
|
version_name,
|
||||||
|
install_dir
|
||||||
|
} => unreachable!("Game registered as 'Partially Installed'"),
|
||||||
|
GameDownloadStatus::Remote {} => unreachable!("Game registered as 'Remote'"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let launch = PathBuf::from_str(&install_dir).unwrap().join(launch);
|
let launch = PathBuf::from_str(&install_dir).unwrap().join(launch);
|
||||||
|
|||||||
@ -10,7 +10,7 @@ use url::Url;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
database::{
|
database::{
|
||||||
db::{borrow_db_checked, borrow_db_mut_checked, save_db},
|
db::{borrow_db_checked, borrow_db_mut_checked},
|
||||||
models::data::DatabaseAuth,
|
models::data::DatabaseAuth,
|
||||||
},
|
},
|
||||||
error::{drop_server_error::DropServerError, remote_access_error::RemoteAccessError},
|
error::{drop_server_error::DropServerError, remote_access_error::RemoteAccessError},
|
||||||
@ -122,8 +122,6 @@ fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), RemoteAc
|
|||||||
client_id: response_struct.id,
|
client_id: response_struct.id,
|
||||||
web_token: None, // gets created later
|
web_token: None, // gets created later
|
||||||
});
|
});
|
||||||
drop(handle);
|
|
||||||
save_db();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let web_token = {
|
let web_token = {
|
||||||
@ -140,8 +138,6 @@ fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), RemoteAc
|
|||||||
let mut handle = borrow_db_mut_checked();
|
let mut handle = borrow_db_mut_checked();
|
||||||
let mut_auth = handle.auth.as_mut().unwrap();
|
let mut_auth = handle.auth.as_mut().unwrap();
|
||||||
mut_auth.web_token = Some(web_token);
|
mut_auth.web_token = Some(web_token);
|
||||||
drop(handle);
|
|
||||||
save_db();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use tauri::{AppHandle, Emitter, Manager};
|
|||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
database::db::{borrow_db_checked, borrow_db_mut_checked, save_db},
|
database::db::{borrow_db_checked, borrow_db_mut_checked},
|
||||||
error::remote_access_error::RemoteAccessError,
|
error::remote_access_error::RemoteAccessError,
|
||||||
remote::{auth::generate_authorization_header, requests::make_request},
|
remote::{auth::generate_authorization_header, requests::make_request},
|
||||||
AppState, AppStatus,
|
AppState, AppStatus,
|
||||||
@ -65,8 +65,6 @@ pub fn sign_out(app: AppHandle) {
|
|||||||
{
|
{
|
||||||
let mut handle = borrow_db_mut_checked();
|
let mut handle = borrow_db_mut_checked();
|
||||||
handle.auth = None;
|
handle.auth = None;
|
||||||
drop(handle);
|
|
||||||
save_db();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update app state
|
// Update app state
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use serde::Deserialize;
|
|||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
database::db::{borrow_db_mut_checked, save_db},
|
database::db::{borrow_db_mut_checked},
|
||||||
error::remote_access_error::RemoteAccessError,
|
error::remote_access_error::RemoteAccessError,
|
||||||
AppState, AppStatus,
|
AppState, AppStatus,
|
||||||
};
|
};
|
||||||
@ -40,9 +40,6 @@ pub fn use_remote_logic(
|
|||||||
|
|
||||||
let mut db_state = borrow_db_mut_checked();
|
let mut db_state = borrow_db_mut_checked();
|
||||||
db_state.base_url = base_url.to_string();
|
db_state.base_url = base_url.to_string();
|
||||||
drop(db_state);
|
|
||||||
|
|
||||||
save_db();
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
2
types.ts
2
types.ts
@ -59,11 +59,13 @@ export enum GameStatusEnum {
|
|||||||
Uninstalling = "Uninstalling",
|
Uninstalling = "Uninstalling",
|
||||||
SetupRequired = "SetupRequired",
|
SetupRequired = "SetupRequired",
|
||||||
Running = "Running",
|
Running = "Running",
|
||||||
|
PartiallyInstalled = "PartiallyInstalled"
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GameStatus = {
|
export type GameStatus = {
|
||||||
type: GameStatusEnum;
|
type: GameStatusEnum;
|
||||||
version_name?: string;
|
version_name?: string;
|
||||||
|
install_dir?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum DownloadableType {
|
export enum DownloadableType {
|
||||||
|
|||||||
Reference in New Issue
Block a user