From bc1e636fbffa0470d6e788e593edbbca817c1ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C5=ABdolfs=20O=C5=A1i=C5=86=C5=A1?= Date: Fri, 19 Jun 2026 11:47:18 +0200 Subject: [PATCH] Virtualize the file tree's root entries The file tree was the one list left un-virtualized, so wide directories mounted every entry and re-rendered all rows on selection. Render entries through VirtualList like the other lists. --- src/components/FileTreeFolder.svelte | 12 ++++++++-- src/components/Tree.svelte | 36 ++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/components/FileTreeFolder.svelte b/src/components/FileTreeFolder.svelte index d30370d9f..27682c45f 100644 --- a/src/components/FileTreeFolder.svelte +++ b/src/components/FileTreeFolder.svelte @@ -11,6 +11,10 @@ currentPath: string; name: string; prefix: string; + // Expansion state lives in Tree.svelte so it survives the virtualizer + // unmounting off-screen rows. + isExpanded: (prefix: string) => boolean; + toggleExpanded: (prefix: string) => void; indent?: number; } @@ -19,10 +23,12 @@ fetchBlob, currentPath, prefix, + isExpanded, + toggleExpanded, fetchTree, indent = 0.5, }: Props = $props(); - let expanded = $derived(currentPath.indexOf(prefix) === 0); + const expanded = $derived(isExpanded(prefix)); const treePromise = $derived( expanded ? fetchTree(prefix) : Promise.resolve(undefined), @@ -46,7 +52,7 @@ class="folder" style:padding-left="{indent}rem" style:padding-right="0.5rem" - onclick={() => (expanded = !expanded)}> + onclick={() => toggleExpanded(prefix)}>
@@ -68,6 +74,8 @@ {fetchBlob} name={entry.name} {currentPath} + {isExpanded} + {toggleExpanded} prefix={`${entry.path}/`} indent={indent + 1.5} /> {:else if entry.kind === "blob"} diff --git a/src/components/Tree.svelte b/src/components/Tree.svelte index 085edd33a..3e5d3a331 100644 --- a/src/components/Tree.svelte +++ b/src/components/Tree.svelte @@ -1,8 +1,11 @@ -
- {#each tree.entries as entry (entry.name)} + entry.path} + estimatedItemSize={28}> + {#snippet row(entry)} {#if entry.kind === "tree"} {:else} @@ -29,5 +57,5 @@ fetchBlob={() => fetchBlob(entry.path)} active={entry.path === currentPath} /> {/if} - {/each} -
+ {/snippet} +