From b01ba37f7effba036ffb05cea79eff26b249f991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C5=ABdolfs=20O=C5=A1i=C5=86=C5=A1?= Date: Fri, 3 Jul 2026 10:00:35 +0200 Subject: [PATCH] Apply restored scroll position only once --- src/components/VirtualList.svelte | 5 +++++ src/lib/paginatedList.svelte.ts | 20 ++++++++++++++++++-- src/views/repo/Issues.svelte | 1 + src/views/repo/Patches.svelte | 1 + src/views/repo/RepoCommits.svelte | 1 + 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/components/VirtualList.svelte b/src/components/VirtualList.svelte index e2c7d7a5b..ca4b3a8c4 100644 --- a/src/components/VirtualList.svelte +++ b/src/components/VirtualList.svelte @@ -31,6 +31,9 @@ // Restore a previously-captured scroll position (used on history nav). initialCache?: ListCacheSnapshot; initialScrollOffset?: number; + // Called once the restore has been applied, so the provider can stop + // handing out the (now stale) values to later remounts of this list. + onRestored?: () => void; // Reports the current scroll position so callers can persist it. onState?: (state: { scrollOffset: number; @@ -59,6 +62,7 @@ prefetchPx = 800, initialCache = undefined, initialScrollOffset = undefined, + onRestored = undefined, onState = undefined, onScrollState = undefined, }: Props = $props(); @@ -134,6 +138,7 @@ if (initialScrollOffset) { handle.scrollTo(initialScrollOffset); } + onRestored?.(); }); function reportState() { diff --git a/src/lib/paginatedList.svelte.ts b/src/lib/paginatedList.svelte.ts index 153a55c0a..7f791ef5c 100644 --- a/src/lib/paginatedList.svelte.ts +++ b/src/lib/paginatedList.svelte.ts @@ -181,6 +181,15 @@ export function createPaginatedList(opts: PaginatedListOptions) { }); } + // The restore values are handed out once: VirtualList applies them on its + // first mount and reports back via consumeRestoredScroll. A later remount + // of the same list (e.g. the empty-fuzzy-filter branch swapping it out and + // back) must start fresh instead of re-applying a stale offset against + // items that may have changed since. + let restoredScroll = restored + ? { scrollOffset: restored.scrollOffset, cache: restored.cache } + : undefined; + return { get items() { return items; @@ -191,8 +200,15 @@ export function createPaginatedList(opts: PaginatedListOptions) { get loadingMore() { return loadingMore; }, - initialScrollOffset: restored?.scrollOffset, - initialCache: restored?.cache, + get initialScrollOffset() { + return restoredScroll?.scrollOffset; + }, + get initialCache() { + return restoredScroll?.cache; + }, + consumeRestoredScroll() { + restoredScroll = undefined; + }, loadMore, revalidate, persistScroll, diff --git a/src/views/repo/Issues.svelte b/src/views/repo/Issues.svelte index 8253aa3f0..d4428a1f1 100644 --- a/src/views/repo/Issues.svelte +++ b/src/views/repo/Issues.svelte @@ -315,6 +315,7 @@ getKey={result => result.obj.issue.id} initialCache={list.initialCache} initialScrollOffset={list.initialScrollOffset} + onRestored={list.consumeRestoredScroll} onState={list.persistScroll}> {#snippet row(result)}
diff --git a/src/views/repo/Patches.svelte b/src/views/repo/Patches.svelte index 0356d428b..9713c4291 100644 --- a/src/views/repo/Patches.svelte +++ b/src/views/repo/Patches.svelte @@ -343,6 +343,7 @@ getKey={result => result.obj.patch.id} initialCache={list.initialCache} initialScrollOffset={list.initialScrollOffset} + onRestored={list.consumeRestoredScroll} onState={list.persistScroll}> {#snippet row(result)}
diff --git a/src/views/repo/RepoCommits.svelte b/src/views/repo/RepoCommits.svelte index c04643379..5cfa7235d 100644 --- a/src/views/repo/RepoCommits.svelte +++ b/src/views/repo/RepoCommits.svelte @@ -274,6 +274,7 @@ r.type === "header" ? `h:${r.key}` : `c:${r.commit.id}`} initialCache={list.initialCache} initialScrollOffset={list.initialScrollOffset} + onRestored={list.consumeRestoredScroll} onState={list.persistScroll}> {#snippet row(item)} {#if item.type === "header"}