From 5b10ff0eff24480806597db1810f880b15c6eeed Mon Sep 17 00:00:00 2001 From: midzelis Date: Sun, 24 May 2026 15:45:19 -0400 Subject: [PATCH] refactor(web): switch consumers to use day-tier viewport boundaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TimelineDay.isInOrNearViewport now derives from the firstInOrNearIndex $state added in the previous commit (true iff first index != -1). This replaces the old $derived.by that read every asset's isInOrNearViewport via viewerAssets.some(), removing a per-asset subscription point that filter() in AssetLayout had been creating for every render. AssetLayout switches from filterIsInOrNearViewport(viewerAssets) to viewerAssets.slice(firstInOrNearIndex, lastInOrNearIndex + 1). The slice expression depends only on the two boundary $state values, not on any asset's proximity $derived. Reactive churn during scroll collapses to: boundary indices change → slice recomputes → {#each} reconciles. Month.svelte passes the new boundary props through. filterIsInOrNearViewport is still used at the month tier (to filter days) and stays in utils. Change-Id: If4e30192146f3e987307b1efd7c6d41d6a6a6964 --- .../components/timeline/AssetLayout.svelte | 19 ++++++++++++++++--- web/src/lib/components/timeline/Month.svelte | 2 ++ .../timeline-manager/timeline-day.svelte.ts | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/web/src/lib/components/timeline/AssetLayout.svelte b/web/src/lib/components/timeline/AssetLayout.svelte index 4ecf71f517..c6ee04a21f 100644 --- a/web/src/lib/components/timeline/AssetLayout.svelte +++ b/web/src/lib/components/timeline/AssetLayout.svelte @@ -1,6 +1,5 @@
- {#each filterIsInOrNearViewport(viewerAssets) as viewerAsset (viewerAsset.id)} + {#each visibleViewerAssets as viewerAsset (viewerAsset.id)} {@const position = viewerAsset.position!} {@const asset = viewerAsset.asset!} diff --git a/web/src/lib/components/timeline/Month.svelte b/web/src/lib/components/timeline/Month.svelte index 3f4b9b0661..ccd1d025d9 100644 --- a/web/src/lib/components/timeline/Month.svelte +++ b/web/src/lib/components/timeline/Month.svelte @@ -101,6 +101,8 @@ this.viewerAssets.some((viewAsset) => viewAsset.isInOrNearViewport)); // Indices into viewerAssets bounding the in-or-near range. -1/-1 means no assets are in-or-near. // Updated imperatively by updateAssetBoundaries() from updateViewportProximities() and layout(). firstInOrNearIndex = $state(-1); lastInOrNearIndex = $state(-1); + isInOrNearViewport = $derived(this.firstInOrNearIndex !== -1); #top: number = $state(0); #start: number = $state(0);