Fix IGDB result selection: use DOM data attributes + pass igdb_id to backend
Build & Deploy / build-and-deploy (push) Successful in 58s

Two issues fixed:

1. Frontend closure bug: IGDB result buttons used Svelte {#each} closure
   with onclick={() => doUpload(result.name)}. When clicking the 3rd
   result, the 1st result's handler sometimes fired. Fixed by reading
   data-name from e.currentTarget.dataset instead of JS closure.

2. Backend scrape mismatch: when user selected 'Blood' from IGDB
   results, backend's autoScrape searched for 'Blood' and could match
   'Captain Blood' first (alphabetical), overwriting metadata.
   Now passes igdb_id along with title so backend uses the EXACT
   IGDB entry the user selected via applyIgdbId() instead of
   auto-searching.
This commit is contained in:
Hermes Agent
2026-05-28 16:00:51 +02:00
parent a4b633ae86
commit ff7b7b446f
3 changed files with 16 additions and 8 deletions
+2 -1
View File
@@ -43,10 +43,11 @@ export async function deleteGame(id) {
}
/** Upload a game ZIP */
export async function uploadGame(file, title) {
export async function uploadGame(file, title, igdbId) {
const form = new FormData();
form.append("file", file);
if (title) form.append("title", title);
if (igdbId) form.append("igdb_id", String(igdbId));
const res = await fetch(`${BASE}/api/upload`, {
method: "POST",
+6 -4
View File
@@ -82,12 +82,12 @@
manualSearched = false;
}
async function doUpload(title) {
async function doUpload(title, igdbId) {
if (!pendingFile) return;
uploading = true;
uploadError = "";
try {
await uploadGame(pendingFile, title || undefined);
await uploadGame(pendingFile, title || undefined, igdbId);
cancelUpload();
await loadGames();
} catch (err) {
@@ -139,10 +139,12 @@
{:else if igdbResults !== null && igdbResults.length > 0}
<p class="match-label">Select a match or enter a custom title:</p>
<div class="upload-igdb-results">
{#each igdbResults as result (result.igdb_id)}
{#each igdbResults as result}
<button
class="igdb-result"
onclick={() => doUpload(result.name)}
data-name={result.name}
data-igdb-id={result.igdb_id}
onclick={(e) => doUpload(e.currentTarget.dataset.name, Number(e.currentTarget.dataset.igdbId))}
disabled={uploading}
>
{#if result.cover_url}
@@ -34,7 +34,8 @@ public class UploadResource {
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response upload(
@RestForm("file") FileUpload upload,
@RestForm("title") String title
@RestForm("title") String title,
@RestForm("igdb_id") Integer igdbId
) throws Exception {
if (upload == null) {
return Response.status(400).entity(Map.of("error", "No file provided")).build();
@@ -103,9 +104,13 @@ public class UploadResource {
game.setReady(true);
svc.save(game);
// Auto-populate from IGDB (non-blocking if credentials are set)
// Auto-populate from IGDB (use provided igdb_id or auto-search)
if (igdb.isConfigured()) {
if (igdbId != null) {
igdb.applyIgdbId(game, igdbId);
} else {
igdb.autoScrape(game);
}
if (game.isHasCover() || game.getYear() != null || game.getGenre() != null
|| (game.getVideos() != null && !game.getVideos().isEmpty())
|| (game.getScreenshots() != null && !game.getScreenshots().isEmpty())) {