From cd82fabfac3120179f947fba331025676dc1af7f Mon Sep 17 00:00:00 2001 From: Natsuu Date: Wed, 14 Jan 2026 04:40:03 +0000 Subject: feat: add functionality to retrieve installed game versions --- src-tauri/src/main.rs | 37 +++++++++++++++++++++++++++++++++++++ ui/src/components/BottomBar.svelte | 7 +++++-- ui/src/stores/game.svelte.ts | 30 ++++++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index d7ae9a4..bf7504d 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -586,6 +586,42 @@ async fn get_versions() -> Result, String> { } } +#[tauri::command] +async fn get_installed_versions(app_handle: tauri::AppHandle) -> Result, String> { + let game_dir = app_handle + .path() + .app_data_dir() + .map_err(|e| format!("Failed to get app data dir: {}", e))?; + + let versions_dir = game_dir.join("versions"); + + if !versions_dir.exists() { + return Ok(Vec::new()); + } + + let mut installed_versions = Vec::new(); + + if let Ok(entries) = std::fs::read_dir(versions_dir) { + for entry in entries { + if let Ok(entry) = entry { + if let Ok(file_type) = entry.file_type() { + if file_type.is_dir() { + if let Ok(file_name) = entry.file_name().into_string() { + // Optionally verify if {version_id}.json exists inside + let json_path = entry.path().join(format!("{}.json", file_name)); + if json_path.exists() { + installed_versions.push(file_name); + } + } + } + } + } + } + } + + Ok(installed_versions) +} + #[tauri::command] async fn login_offline( window: Window, @@ -784,6 +820,7 @@ fn main() { .invoke_handler(tauri::generate_handler![ start_game, get_versions, + get_installed_versions, login_offline, get_active_account, logout, diff --git a/ui/src/components/BottomBar.svelte b/ui/src/components/BottomBar.svelte index dcad9e8..a96b086 100644 --- a/ui/src/components/BottomBar.svelte +++ b/ui/src/components/BottomBar.svelte @@ -65,10 +65,13 @@ > {#if gameState.versions.length === 0} + {:else if gameState.installedVersionIds.length === 0} + {:else} {#each gameState.versions as version} - + {#if gameState.installedVersionIds.includes(version.id)} + + {/if} {/each} {/if} diff --git a/ui/src/stores/game.svelte.ts b/ui/src/stores/game.svelte.ts index 0af3daf..3128cc6 100644 --- a/ui/src/stores/game.svelte.ts +++ b/ui/src/stores/game.svelte.ts @@ -5,14 +5,36 @@ import { authState } from "./auth.svelte"; export class GameState { versions = $state([]); + installedVersionIds = $state([]); selectedVersion = $state(""); async loadVersions() { try { - this.versions = await invoke("get_versions"); - if (this.versions.length > 0) { - const latest = this.versions.find((v) => v.type === "release"); - this.selectedVersion = latest ? latest.id : this.versions[0].id; + // Fetch both full version list and installed versions + const [allVersions, installedIds] = await Promise.all([ + invoke("get_versions"), + invoke("get_installed_versions") + ]); + + this.versions = allVersions; + this.installedVersionIds = installedIds; + + if (this.installedVersionIds.length > 0) { + // Find the first installed version that appears in our manifest (preserving order) + // Usually we want the latest release that is installed + const installedVersions = this.versions.filter(v => this.installedVersionIds.includes(v.id)); + + // Try to find latest release among installed + const latestInstalledRelease = installedVersions.find(v => v.type === "release"); + + if (latestInstalledRelease) { + this.selectedVersion = latestInstalledRelease.id; + } else if (installedVersions.length > 0) { + this.selectedVersion = installedVersions[0].id; + } else { + // Fallback to just the first ID if not in manifest + this.selectedVersion = this.installedVersionIds[0]; + } } } catch (e) { console.error("Failed to fetch versions:", e); -- cgit v1.2.3-70-g09d2