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:
DecDuck
2026-01-20 11:40:48 +11:00
committed by GitHub
parent 55fdaf51e1
commit fc69ae30ab
72 changed files with 3430 additions and 2732 deletions
+61 -27
View File
@@ -1,6 +1,8 @@
use std::{path::PathBuf, sync::Arc};
use database::{GameDownloadStatus, borrow_db_checked};
use database::{
DownloadType, DownloadableMetadata, GameDownloadStatus, borrow_db_checked, platform::Platform,
};
use download_manager::{
DOWNLOAD_MANAGER, downloadable::Downloadable, error::ApplicationDownloadError,
};
@@ -9,16 +11,37 @@ use games::downloads::download_agent::GameDownloadAgent;
#[tauri::command]
pub async fn download_game(
game_id: String,
game_version: String,
version_id: String,
target_platform: Platform,
install_dir: usize,
) -> Result<(), ApplicationDownloadError> {
{
let db = borrow_db_checked();
let status = db
.applications
.game_statuses
.get(&game_id)
.unwrap_or(&GameDownloadStatus::Remote {});
if matches!(status, GameDownloadStatus::Installed { .. }) {
return Ok(());
}
};
let sender = { DOWNLOAD_MANAGER.get_sender().clone() };
let meta = DownloadableMetadata {
id: game_id,
version: version_id,
target_platform,
download_type: DownloadType::Game,
};
let game_download_agent = GameDownloadAgent::new_from_index(
game_id.clone(),
game_version.clone(),
meta,
install_dir,
sender,
DOWNLOAD_MANAGER.clone_depot_manager(),
)
.await?;
@@ -27,6 +50,7 @@ pub async fn download_game(
DOWNLOAD_MANAGER
.queue_download(game_download_agent.clone())
.await
.unwrap();
Ok(())
@@ -34,43 +58,53 @@ pub async fn download_game(
#[tauri::command]
pub async fn resume_download(game_id: String) -> Result<(), ApplicationDownloadError> {
let s = borrow_db_checked()
.applications
.game_statuses
.get(&game_id)
.unwrap()
.clone();
let (meta, install_dir) = {
let db_lock = borrow_db_checked();
let status = db_lock
.applications
.game_statuses
.get(&game_id)
.ok_or(ApplicationDownloadError::InvalidCommand)?
.clone();
let (version_name, install_dir) = match s {
GameDownloadStatus::Remote {} => unreachable!(),
GameDownloadStatus::SetupRequired { .. } => unreachable!(),
GameDownloadStatus::Installed { .. } => unreachable!(),
GameDownloadStatus::PartiallyInstalled {
version_name,
install_dir,
} => (version_name, install_dir),
let meta = db_lock
.applications
.installed_game_version
.get(&game_id)
.ok_or(ApplicationDownloadError::InvalidCommand)?
.clone();
let install_dir = match status {
GameDownloadStatus::Remote {} => Err(ApplicationDownloadError::InvalidCommand),
GameDownloadStatus::SetupRequired { .. } => {
Err(ApplicationDownloadError::InvalidCommand)
}
GameDownloadStatus::Installed { .. } => Err(ApplicationDownloadError::InvalidCommand),
GameDownloadStatus::PartiallyInstalled { install_dir, .. } => Ok(install_dir),
}?;
(meta, install_dir)
};
let sender = DOWNLOAD_MANAGER.get_sender();
let parent_dir: PathBuf = install_dir.into();
let install_dir = PathBuf::from(install_dir);
let install_dir = install_dir
.parent()
.expect("game somehow installed at root");
let game_download_agent = Arc::new(Box::new(
GameDownloadAgent::new(
game_id,
version_name.clone(),
parent_dir
.parent()
.unwrap_or_else(|| {
panic!("Failed to get parent directry of {}", parent_dir.display())
})
.to_path_buf(),
meta,
install_dir.to_path_buf(),
sender,
DOWNLOAD_MANAGER.clone_depot_manager(),
)
.await?,
) as Box<dyn Downloadable + Send + Sync>);
DOWNLOAD_MANAGER
.queue_download(game_download_agent)
.await
.unwrap();
Ok(())
}