Depot API & executor launch (#173)
* feat: depot api downloads * feat: frontend fixes and experimental webview store * feat: sync downloader * feat: cleanup and fixes * feat: encrypted database and fixed resuming * feat: launch option selector * fix: autostart when no options * fix: clippy * fix: clippy x2 * feat: executor launch * feat: executor launch * feat: not installed error handling * feat: better offline handling * feat: dependency popup * fix: cancelation and resuming issues * feat: dedup by platform * feat: new ui for additional components and fix dl manager clog * feat: auto-queue dependencies * feat: depot scanning and ranking * feat: new library fetching stack * In-app store page (Windows + macOS) (#176) * feat: async store loading * feat: fix overscroll behaviour * fix: query params in server protocol * fix: clippy
This commit is contained in:
@@ -1,26 +1,24 @@
|
||||
pub mod data {
|
||||
use std::{hash::Hash, path::PathBuf};
|
||||
|
||||
use native_model::native_model;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// NOTE: Within each version, you should NEVER use these types.
|
||||
// Declare it using the actual version that it is from, i.e. v1::Settings rather than just Settings from here
|
||||
|
||||
pub type Database = v1::Database;
|
||||
pub type GameVersion = v1::GameVersion;
|
||||
pub type Database = v3::Database;
|
||||
pub type Settings = v1::Settings;
|
||||
pub type DatabaseAuth = v1::DatabaseAuth;
|
||||
|
||||
pub type GameDownloadStatus = v2::GameDownloadStatus;
|
||||
pub type GameDownloadStatus = v1::GameDownloadStatus;
|
||||
pub type ApplicationTransientStatus = v1::ApplicationTransientStatus;
|
||||
/**
|
||||
* Need to be universally accessible by the ID, and the version is just a couple sprinkles on top
|
||||
*/
|
||||
pub type DownloadableMetadata = v1::DownloadableMetadata;
|
||||
pub type DownloadType = v1::DownloadType;
|
||||
pub type DatabaseApplications = v2::DatabaseApplications;
|
||||
// pub type DatabaseCompatInfo = v2::DatabaseCompatInfo;
|
||||
pub type DatabaseApplications = v1::DatabaseApplications;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -36,13 +34,44 @@ pub mod data {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
enum DatabaseVersionEnum {
|
||||
V1 { database: v1::Database },
|
||||
}
|
||||
|
||||
pub struct DatabaseVersionSerializable(pub(crate) Database);
|
||||
|
||||
impl Serialize for DatabaseVersionSerializable {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
// Always serialize to latest version
|
||||
DatabaseVersionEnum::V1 {
|
||||
database: self.0.clone(),
|
||||
}
|
||||
.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for DatabaseVersionSerializable {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Ok(match DatabaseVersionEnum::deserialize(deserializer)? {
|
||||
DatabaseVersionEnum::V1 { database } => DatabaseVersionSerializable(database),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
mod v1 {
|
||||
use serde_with::serde_as;
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use crate::platform::Platform;
|
||||
|
||||
use super::{Deserialize, Serialize, native_model};
|
||||
use super::{Deserialize, Serialize};
|
||||
|
||||
fn default_template() -> String {
|
||||
"{}".to_owned()
|
||||
@@ -50,49 +79,58 @@ pub mod data {
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[native_model(id = 2, version = 1, with = native_model::rmp_serde_1_3::RmpSerde)]
|
||||
pub struct GameVersion {
|
||||
pub game_id: String,
|
||||
pub version_name: String,
|
||||
pub version_id: String,
|
||||
|
||||
pub platform: Platform,
|
||||
|
||||
pub launch_command: String,
|
||||
pub launch_args: Vec<String>,
|
||||
#[serde(default = "default_template")]
|
||||
pub launch_command_template: String,
|
||||
|
||||
pub setup_command: String,
|
||||
pub setup_args: Vec<String>,
|
||||
#[serde(default = "default_template")]
|
||||
pub setup_command_template: String,
|
||||
pub display_name: Option<String>,
|
||||
pub version_path: String,
|
||||
|
||||
pub only_setup: bool,
|
||||
|
||||
pub version_index: usize,
|
||||
pub delta: bool,
|
||||
|
||||
pub umu_id_override: Option<String>,
|
||||
#[serde(default = "default_template")]
|
||||
pub launch_template: String,
|
||||
|
||||
pub launches: Vec<LaunchConfiguration>,
|
||||
pub setups: Vec<SetupConfiguration>,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Clone, Deserialize, Default)]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[native_model(id = 3, version = 1, 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>,
|
||||
pub struct LaunchConfiguration {
|
||||
pub launch_id: String,
|
||||
|
||||
#[serde(skip)]
|
||||
pub transient_statuses: HashMap<DownloadableMetadata, ApplicationTransientStatus>,
|
||||
pub name: String,
|
||||
pub command: String,
|
||||
pub platform: Platform,
|
||||
pub umu_id_override: Option<String>,
|
||||
|
||||
pub executor: Option<LaunchConfigurationExecutor>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
/**
|
||||
* This is intended to be used to look up the actual launch configuration that we store elsewhere
|
||||
*/
|
||||
pub struct LaunchConfigurationExecutor {
|
||||
pub launch_id: String,
|
||||
pub game_id: String,
|
||||
pub version_id: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SetupConfiguration {
|
||||
pub command: String,
|
||||
pub platform: Platform,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[native_model(id = 4, version = 1, with = native_model::rmp_serde_1_3::RmpSerde)]
|
||||
pub struct Settings {
|
||||
pub autostart: bool,
|
||||
pub max_download_threads: usize,
|
||||
@@ -108,129 +146,8 @@ pub mod data {
|
||||
}
|
||||
}
|
||||
|
||||
// Strings are version names for a particular game
|
||||
#[derive(Serialize, Clone, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
#[native_model(id = 5, version = 1, 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,
|
||||
},
|
||||
}
|
||||
|
||||
// Stuff that shouldn't be synced to disk
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub enum ApplicationTransientStatus {
|
||||
Queued { version_name: String },
|
||||
Downloading { version_name: String },
|
||||
Uninstalling {},
|
||||
Updating { version_name: String },
|
||||
Validating { version_name: String },
|
||||
Running {},
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Clone, Deserialize)]
|
||||
#[native_model(id = 6, version = 1, with = native_model::rmp_serde_1_3::RmpSerde)]
|
||||
pub struct DatabaseAuth {
|
||||
pub private: String,
|
||||
pub cert: String,
|
||||
pub client_id: String,
|
||||
pub web_token: Option<String>,
|
||||
}
|
||||
|
||||
#[native_model(id = 8, version = 1)]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Clone, Copy,
|
||||
)]
|
||||
pub enum DownloadType {
|
||||
Game,
|
||||
Tool,
|
||||
Dlc,
|
||||
Mod,
|
||||
}
|
||||
|
||||
#[native_model(id = 7, version = 1, with = native_model::rmp_serde_1_3::RmpSerde)]
|
||||
#[derive(Debug, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DownloadableMetadata {
|
||||
pub id: String,
|
||||
pub version: Option<String>,
|
||||
pub download_type: DownloadType,
|
||||
}
|
||||
impl DownloadableMetadata {
|
||||
pub fn new(id: String, version: Option<String>, download_type: DownloadType) -> Self {
|
||||
Self {
|
||||
id,
|
||||
version,
|
||||
download_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[native_model(id = 1, version = 1)]
|
||||
#[derive(Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Database {
|
||||
#[serde(default)]
|
||||
pub settings: Settings,
|
||||
pub auth: Option<DatabaseAuth>,
|
||||
pub base_url: String,
|
||||
pub applications: DatabaseApplications,
|
||||
pub prev_database: Option<PathBuf>,
|
||||
pub cache_dir: PathBuf,
|
||||
}
|
||||
}
|
||||
|
||||
mod v2 {
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use serde_with::serde_as;
|
||||
|
||||
use super::{Deserialize, Serialize, native_model, v1};
|
||||
|
||||
#[native_model(id = 1, version = 2, with = native_model::rmp_serde_1_3::RmpSerde, from = v1::Database)]
|
||||
#[derive(Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Database {
|
||||
#[serde(default)]
|
||||
pub settings: v1::Settings,
|
||||
pub auth: Option<v1::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 = 9, version = 1, 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: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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, from = v1::GameDownloadStatus)]
|
||||
pub enum GameDownloadStatus {
|
||||
Remote {},
|
||||
SetupRequired {
|
||||
@@ -246,89 +163,84 @@ pub mod data {
|
||||
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,
|
||||
},
|
||||
// Stuff that shouldn't be synced to disk
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub enum ApplicationTransientStatus {
|
||||
Queued { version_id: String },
|
||||
Downloading { version_id: String },
|
||||
Uninstalling {},
|
||||
Updating { version_id: String },
|
||||
Validating { version_id: String },
|
||||
Running {},
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, Clone, Deserialize)]
|
||||
pub struct DatabaseAuth {
|
||||
pub private: String,
|
||||
pub cert: String,
|
||||
pub client_id: String,
|
||||
pub web_token: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Clone, Copy,
|
||||
)]
|
||||
pub enum DownloadType {
|
||||
Game,
|
||||
Tool,
|
||||
Dlc,
|
||||
Mod,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DownloadableMetadata {
|
||||
pub id: String,
|
||||
pub version: String,
|
||||
pub target_platform: Platform,
|
||||
pub download_type: DownloadType,
|
||||
}
|
||||
impl DownloadableMetadata {
|
||||
pub fn new(
|
||||
id: String,
|
||||
version: String,
|
||||
target_platform: Platform,
|
||||
download_type: DownloadType,
|
||||
) -> Self {
|
||||
Self {
|
||||
id,
|
||||
version,
|
||||
target_platform,
|
||||
download_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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, from=v1::DatabaseApplications)]
|
||||
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, v1::GameVersion>>,
|
||||
pub installed_game_version: HashMap<String, v1::DownloadableMetadata>,
|
||||
pub game_versions: HashMap<String, GameVersion>,
|
||||
pub installed_game_version: HashMap<String, DownloadableMetadata>,
|
||||
|
||||
#[serde(skip)]
|
||||
pub transient_statuses:
|
||||
HashMap<v1::DownloadableMetadata, v1::ApplicationTransientStatus>,
|
||||
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::path::PathBuf;
|
||||
|
||||
use super::{Deserialize, Serialize, native_model, v1, v2};
|
||||
#[native_model(id = 1, version = 3, with = native_model::rmp_serde_1_3::RmpSerde, from = v2::Database)]
|
||||
#[derive(Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Database {
|
||||
#[serde(default)]
|
||||
pub settings: v1::Settings,
|
||||
pub auth: Option<v1::DatabaseAuth>,
|
||||
pub settings: Settings,
|
||||
pub auth: Option<DatabaseAuth>,
|
||||
pub base_url: String,
|
||||
pub applications: v2::DatabaseApplications,
|
||||
pub applications: DatabaseApplications,
|
||||
#[serde(skip)]
|
||||
pub prev_database: Option<PathBuf>,
|
||||
pub cache_dir: PathBuf,
|
||||
pub compat_info: Option<v2::DatabaseCompatInfo>,
|
||||
}
|
||||
|
||||
impl From<v2::Database> for Database {
|
||||
fn from(value: v2::Database) -> Self {
|
||||
Self {
|
||||
settings: value.settings,
|
||||
auth: value.auth,
|
||||
base_url: value.base_url,
|
||||
applications: value.applications.into(),
|
||||
prev_database: value.prev_database,
|
||||
cache_dir: value.cache_dir,
|
||||
compat_info: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,7 +263,6 @@ pub mod data {
|
||||
auth: None,
|
||||
settings: Settings::default(),
|
||||
cache_dir,
|
||||
compat_info: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user