Fix upload dialog re-trigger + add game size to detail page
Build & Deploy / build-and-deploy (push) Failing after 34s
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:
@@ -243,6 +243,13 @@
|
||||
🪟 Requires Windows 3.1 — may not work in browser
|
||||
{:else}
|
||||
💾 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}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -410,6 +417,10 @@
|
||||
background: #1a3a5c;
|
||||
color: #6ab0ff;
|
||||
}
|
||||
.size-badge {
|
||||
font-weight: 400;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.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-link { cursor: pointer; text-decoration: none; transition: all 0.15s; display: inline-block; }
|
||||
|
||||
@@ -28,9 +28,14 @@
|
||||
|
||||
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(() => {
|
||||
if (uploadTriggered > 0) fileInput?.click();
|
||||
if (uploadTriggered > 0 && uploadTriggered !== prevUploadTrigger) {
|
||||
prevUploadTrigger = uploadTriggered;
|
||||
fileInput?.click();
|
||||
}
|
||||
});
|
||||
|
||||
// Derive filter options from the loaded games
|
||||
|
||||
@@ -23,6 +23,9 @@ public class Game {
|
||||
|
||||
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"). */
|
||||
private String executable;
|
||||
|
||||
@@ -91,6 +94,9 @@ public class Game {
|
||||
public String getSetupExe() { return 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 void setExecutable(String executable) { this.executable = executable; }
|
||||
|
||||
|
||||
@@ -67,8 +67,14 @@ public class GameService {
|
||||
Files.exists(gameDir(id).resolve("cover.png")) ||
|
||||
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. */
|
||||
public void save(Game game) throws IOException {
|
||||
|
||||
Reference in New Issue
Block a user