From 74d9266723334bc12f7111708e864c8c92902d04 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Tue, 19 May 2026 20:49:22 +0200 Subject: [PATCH] fix(ui): show installing for downloaded games The redesigned action hook marked every accepted install command as Checking Peers. That is correct while the launcher is asking peers for file details, but it is wrong for a game that is already downloaded and only needs local archive installation. Track the already-downloaded path separately and optimistically show Installing until the backend install lifecycle event arrives. Peer-backed downloads keep the existing Checking Peers state. Test Plan: - git diff --check Refs: user redesign nitpick about install button state --- .../src/hooks/useGameActions.ts | 15 +++++++++++---- .../lanspread-tauri-deno-ts/src/hooks/useGames.ts | 11 +++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/crates/lanspread-tauri-deno-ts/src/hooks/useGameActions.ts b/crates/lanspread-tauri-deno-ts/src/hooks/useGameActions.ts index 65a369b..df167f3 100644 --- a/crates/lanspread-tauri-deno-ts/src/hooks/useGameActions.ts +++ b/crates/lanspread-tauri-deno-ts/src/hooks/useGameActions.ts @@ -12,9 +12,9 @@ export interface GameActions { /** * Thin wrappers over the backend `run_game` / `install_game` / `update_game` - * / `uninstall_game` commands. For install + update we mark the game as - * "checking peers" up-front through the games hook so the UI doesn't have to - * wait for the first backend event. + * / `uninstall_game` commands. We mark peer-backed downloads as "checking + * peers" and already-downloaded installs as "installing" up-front so the UI + * doesn't have to wait for the first backend event. */ export const useGameActions = (games: UseGamesResult): GameActions => { const play = useCallback(async (id: string) => { @@ -28,7 +28,14 @@ export const useGameActions = (games: UseGamesResult): GameActions => { const install = useCallback(async (id: string) => { try { const success = await invoke('install_game', { id }); - if (success) games.markChecking(id); + if (!success) return; + + const game = games.games.find(item => item.id === id); + if (game?.downloaded && !game.installed) { + games.markInstalling(id); + } else { + games.markChecking(id); + } } catch (err) { console.error('install_game failed:', err); } diff --git a/crates/lanspread-tauri-deno-ts/src/hooks/useGames.ts b/crates/lanspread-tauri-deno-ts/src/hooks/useGames.ts index 7b3b735..e01d9c9 100644 --- a/crates/lanspread-tauri-deno-ts/src/hooks/useGames.ts +++ b/crates/lanspread-tauri-deno-ts/src/hooks/useGames.ts @@ -52,6 +52,7 @@ export interface UseGamesResult { totalPeerCount: number; requestGames: () => Promise; markChecking: (id: string) => void; + markInstalling: (id: string) => void; cancelChecking: (id: string) => void; } @@ -95,6 +96,15 @@ export const useGames = (rescanGameDir: () => void): UseGamesResult => { }, CHECKING_PEERS_TIMEOUT_MS); }, [cancelChecking]); + const markInstalling = useCallback((id: string) => { + cancelChecking(id); + setGames(prev => prev.map(item => + item.id === id + ? applyPatch(item, { install_status: InstallStatus.Installing, clearStatus: true }) + : item, + )); + }, [cancelChecking]); + const requestGames = useCallback(async () => { try { await invoke('request_games'); @@ -247,6 +257,7 @@ export const useGames = (rescanGameDir: () => void): UseGamesResult => { totalPeerCount, requestGames, markChecking, + markInstalling, cancelChecking, }; };