Skip to content

Commit 5790ff0

Browse files
committed
fix(v2): refetch list rows on gallery context refresh
A list row fetched its rom only in onMounted. A filter / search / sort / scan refresh clears byPosition and repopulates romIdIndex while the row stays mounted at the same position, so it was stranded on skeletons until it scrolled out and remounted. Replace the onMounted fetch with a watch that fires fetchRomAt whenever the position is missing its rom but the store knows its id. Guarding on the id (not just a null rom) also refetches when a resort lands a different rom at the same position. The store still dedupes against in-flight + already-loaded, so re-runs are cheap. Generated-By: PostHog Code Task-Id: fe232494-3d20-4d83-9eaa-3ce341d4e7b5
1 parent 560a75f commit 5790ff0

1 file changed

Lines changed: 32 additions & 15 deletions

File tree

frontend/src/v2/components/Gallery/GameListRow.vue

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
// GameListRow — single row of the list-mode gallery.
33
//
44
// Owns:
5-
// * Per-row lazy fetch: onMount fires `fetchRomAt(position)`; the store
6-
// dedupes against in-flight + already-loaded. onUnmount aborts the
7-
// fetch via `cancelFetchAt(position)` so a fast scroll past mid-flight
8-
// doesn't keep server work queued for invisible rows. Mirror of the
9-
// per-card grid flow, with the same "row mount = entered viewport"
10-
// contract via the shell's RVirtualScroller overscan window.
5+
// * Per-row lazy fetch: a watch fires `fetchRomAt(position)` whenever
6+
// the row is missing its rom but the store knows the id — covering
7+
// both mount ("entered the overscan window") and a context refresh
8+
// that clears `byPosition` under a still-mounted row. onUnmount aborts
9+
// the fetch via `cancelFetchAt(position)` so a fast scroll past
10+
// mid-flight doesn't keep server work queued for invisible rows.
11+
// Mirror of the per-card grid flow, with the same "row mount =
12+
// entered viewport" contract via the shell's RVirtualScroller
13+
// overscan window.
1114
//
1215
// * Skeleton ↔ real swap — when `getRomAt(position)` returns null the
1316
// row paints skeleton placeholders in every column; once the fetch
@@ -26,7 +29,7 @@ import {
2629
RSkeletonBlock,
2730
RTooltip,
2831
} from "@v2/lib";
29-
import { computed, onBeforeUnmount, onMounted } from "vue";
32+
import { computed, onBeforeUnmount, watch } from "vue";
3033
import { useI18n } from "vue-i18n";
3134
import { useRouter } from "vue-router";
3235
import storePlatforms from "@/stores/platforms";
@@ -261,14 +264,28 @@ function onRowPointerEnd() {
261264
selectionInput.handlePointerEnd();
262265
}
263266
264-
onMounted(() => {
265-
// Static mode (rom passed as prop) skips the gallery's per-row fetch
266-
// entirely — the consumer already owns the rom data.
267-
if (isStatic.value || props.position === undefined) return;
268-
// Entered the overscan window — kick the per-row fetch. Store dedupes
269-
// against in-flight + already-loaded.
270-
void galleryRoms.fetchRomAt(props.position);
271-
});
267+
// Kick the per-row fetch whenever this position is missing its rom but
268+
// the store knows its id. This covers both mount ("entered the overscan
269+
// window") and a context refresh: a filter / search / sort / scan clears
270+
// `byPosition` and repopulates `romIdIndex`, but the row can stay mounted
271+
// at the same position — without this watch it would sit on skeletons
272+
// until it scrolled out and remounted. The store dedupes against
273+
// in-flight + already-loaded, so re-runs are cheap. Guarding on the id
274+
// (not just null rom) also re-fetches when a resort lands a different rom
275+
// at the same position.
276+
watch(
277+
() => {
278+
if (isStatic.value || props.position === undefined) return null;
279+
if (galleryRoms.byPosition.has(props.position)) return null;
280+
return galleryRoms.romIdIndex[props.position] ?? null;
281+
},
282+
(romId) => {
283+
if (romId != null && props.position !== undefined) {
284+
void galleryRoms.fetchRomAt(props.position);
285+
}
286+
},
287+
{ immediate: true },
288+
);
272289
273290
onBeforeUnmount(() => {
274291
if (isStatic.value || props.position === undefined) return;

0 commit comments

Comments
 (0)