Fix upload dialog re-trigger + add game size to detail page
Build & Deploy / build-and-deploy (push) Failing after 34s

- Fixed: navigating back to library no longer re-opens file dialog
  (prev-value guard in uploadTriggered effect)
- Added bundleSize field to Game, populated at load time from .jsdos file
- Game detail page shows file size next to DOS badge (e.g. 'DOS · 127 MB')
This commit is contained in:
Hermes Agent
2026-05-29 14:54:13 +02:00
parent 02d0c4f377
commit 2ab6b19598
4 changed files with 31 additions and 3 deletions
+11
View File
@@ -243,6 +243,13 @@
🪟 Requires Windows 3.1 — may not work in browser 🪟 Requires Windows 3.1 — may not work in browser
{:else} {:else}
💾 DOS 💾 DOS
{#if game.bundle_size}
<span class="size-badge">· {game.bundle_size >= 1073741824
? (game.bundle_size / 1073741824).toFixed(1) + ' GB'
: game.bundle_size >= 1048576
? Math.round(game.bundle_size / 1048576) + ' MB'
: Math.round(game.bundle_size / 1024) + ' KB'}</span>
{/if}
{/if} {/if}
</div> </div>
{/if} {/if}
@@ -410,6 +417,10 @@
background: #1a3a5c; background: #1a3a5c;
color: #6ab0ff; color: #6ab0ff;
} }
.size-badge {
font-weight: 400;
opacity: 0.8;
}
.meta { display: flex; gap: 8px; margin-bottom: 8px; } .meta { display: flex; gap: 8px; margin-bottom: 8px; }
.meta-item { background: var(--surface-hover); color: var(--phosphor-dim); padding: 4px 12px; border-radius: 12px; font-size: 0.85rem; } .meta-item { background: var(--surface-hover); color: var(--phosphor-dim); padding: 4px 12px; border-radius: 12px; font-size: 0.85rem; }
.meta-link { cursor: pointer; text-decoration: none; transition: all 0.15s; display: inline-block; } .meta-link { cursor: pointer; text-decoration: none; transition: all 0.15s; display: inline-block; }
+7 -2
View File
@@ -28,9 +28,14 @@
let fileInput; let fileInput;
// When header upload button is clicked, trigger the hidden file input // When header upload button is clicked, trigger the hidden file input.
// Uses a previous-value guard to prevent re-firing on component remount.
let prevUploadTrigger = $state(uploadTriggered);
$effect(() => { $effect(() => {
if (uploadTriggered > 0) fileInput?.click(); if (uploadTriggered > 0 && uploadTriggered !== prevUploadTrigger) {
prevUploadTrigger = uploadTriggered;
fileInput?.click();
}
}); });
// Derive filter options from the loaded games // Derive filter options from the loaded games
+6
View File
@@ -23,6 +23,9 @@ public class Game {
private String setupExe; // relative path to SETUP.EXE (null if none) private String setupExe; // relative path to SETUP.EXE (null if none)
/** Game bundle file size in bytes. Populated dynamically at load time (not persisted). */
private Long bundleSize;
/** Currently selected main executable (relative path inside the bundle, e.g. "FALLOUT.EXE" or "FALLOUT/FALLOUT.EXE"). */ /** Currently selected main executable (relative path inside the bundle, e.g. "FALLOUT.EXE" or "FALLOUT/FALLOUT.EXE"). */
private String executable; private String executable;
@@ -91,6 +94,9 @@ public class Game {
public String getSetupExe() { return setupExe; } public String getSetupExe() { return setupExe; }
public void setSetupExe(String setupExe) { this.setupExe = setupExe; } public void setSetupExe(String setupExe) { this.setupExe = setupExe; }
public Long getBundleSize() { return bundleSize; }
public void setBundleSize(Long bundleSize) { this.bundleSize = bundleSize; }
public String getExecutable() { return executable; } public String getExecutable() { return executable; }
public void setExecutable(String executable) { this.executable = executable; } public void setExecutable(String executable) { this.executable = executable; }
+7 -1
View File
@@ -67,8 +67,14 @@ public class GameService {
Files.exists(gameDir(id).resolve("cover.png")) || Files.exists(gameDir(id).resolve("cover.png")) ||
Files.exists(gameDir(id).resolve("cover.webp")) Files.exists(gameDir(id).resolve("cover.webp"))
); );
return game; // Detect bundle size
try {
Path bundlePath = gamesDir.resolve(game.getBundleFile());
if (bundlePath != null && Files.exists(bundlePath)) {
game.setBundleSize(Files.size(bundlePath));
} }
} catch (IOException ignored) {}
return game;
/** Save game metadata to disk. */ /** Save game metadata to disk. */
public void save(Game game) throws IOException { public void save(Game game) throws IOException {