From 9733fa487230c8f70a72b33e88bbb55ac83ff8f8 Mon Sep 17 00:00:00 2001 From: Ben Beckford Date: Sun, 24 May 2026 14:03:46 -0700 Subject: [PATCH] fix(web): timeline stuttering with many assets in 1 day (#28509) * fix(web): timeline stuttering with many assets in 1 day * cache isInOrNearViewport per day * skip inOrNearViewport check on first run --- web/src/lib/components/timeline/AssetLayout.svelte | 6 ++++-- .../managers/timeline-manager/timeline-day.svelte.ts | 11 ++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/web/src/lib/components/timeline/AssetLayout.svelte b/web/src/lib/components/timeline/AssetLayout.svelte index 4ecf71f517..88f03ef46a 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 viewerAssets.slice(firstInOrNearViewport, lastInOrNearViewport + 1) as viewerAsset (viewerAsset.id)} {@const position = viewerAsset.position!} {@const asset = viewerAsset.asset!} diff --git a/web/src/lib/managers/timeline-manager/timeline-day.svelte.ts b/web/src/lib/managers/timeline-manager/timeline-day.svelte.ts index 73b2c259ae..c3d53be67a 100644 --- a/web/src/lib/managers/timeline-manager/timeline-day.svelte.ts +++ b/web/src/lib/managers/timeline-manager/timeline-day.svelte.ts @@ -17,13 +17,13 @@ export class TimelineDay { height = $state(0); width = $state(0); - isInOrNearViewport = $derived.by(() => this.viewerAssets.some((viewAsset) => viewAsset.isInOrNearViewport)); #top: number = $state(0); #start: number = $state(0); #row = $state(0); #col = $state(0); #deferredLayout = false; + #lastInOrNearViewport = -1; constructor(timelineMonth: TimelineMonth, index: number, day: number, groupTitle: string, orderBy: AssetOrderBy) { this.index = index; @@ -154,4 +154,13 @@ export class TimelineDay { get absoluteTimelineDayTop() { return this.timelineMonth.top + this.#top; } + + get isInOrNearViewport() { + if (this.#lastInOrNearViewport !== -1 && this.viewerAssets[this.#lastInOrNearViewport].isInOrNearViewport) { + return true; + } + + this.#lastInOrNearViewport = this.viewerAssets.findIndex((viewAsset) => viewAsset.isInOrNearViewport); + return this.#lastInOrNearViewport !== -1; + } }