From 04e2e42c882f5bc68a035718e2f65fa49edb39d2 Mon Sep 17 00:00:00 2001 From: Min Idzelis Date: Mon, 20 Oct 2025 23:13:49 -0400 Subject: [PATCH] refactor(web): improve date labels in scrubber (#23046) refactor(web): improve timeline scrubber labeling logic Refactor the segment calculation in the timeline scrubber to improve code clarity and fix label positioning. Process months in reverse order for more intuitive label selection, use descriptive variable names, and remove unnecessary index tracking. --- .../lib/components/timeline/Scrubber.svelte | 35 +++++++++++-------- .../timeline-manager.svelte.ts | 1 + 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/web/src/lib/components/timeline/Scrubber.svelte b/web/src/lib/components/timeline/Scrubber.svelte index 069b62002e..827f9df587 100644 --- a/web/src/lib/components/timeline/Scrubber.svelte +++ b/web/src/lib/components/timeline/Scrubber.svelte @@ -141,14 +141,18 @@ }; const calculateSegments = (months: ScrubberMonth[]) => { - let height = 0; - let dotHeight = 0; + let verticalSpanWithoutLabel = 0; + let verticalSpanWithoutDot = 0; let segments: Segment[] = []; let previousLabeledSegment: Segment | undefined; let top = 0; - for (const [i, scrubMonth] of months.entries()) { + + // Process months in reverse order to pick labels, then reverse for display + const reversed = [...months].reverse(); + + for (const scrubMonth of reversed) { const scrollBarPercentage = scrubMonth.height / timelineFullHeight; const segment = { @@ -162,25 +166,26 @@ hasDot: false, }; top += segment.height; - if (i === 0) { - segment.hasDot = true; - segment.hasLabel = true; - previousLabeledSegment = segment; - } else { - if (previousLabeledSegment?.year !== segment.year && height > MIN_YEAR_LABEL_DISTANCE) { - height = 0; + if (previousLabeledSegment) { + if (previousLabeledSegment.year !== segment.year && verticalSpanWithoutLabel > MIN_YEAR_LABEL_DISTANCE) { + verticalSpanWithoutLabel = 0; segment.hasLabel = true; previousLabeledSegment = segment; } - if (segment.height > 5 && dotHeight > MIN_DOT_DISTANCE) { + if (segment.height > 5 && verticalSpanWithoutDot > MIN_DOT_DISTANCE) { segment.hasDot = true; - dotHeight = 0; + verticalSpanWithoutDot = 0; } - height += segment.height; + } else { + segment.hasDot = true; + segment.hasLabel = true; + previousLabeledSegment = segment; } - dotHeight += segment.height; + verticalSpanWithoutLabel += segment.height; + verticalSpanWithoutDot += segment.height; segments.push(segment); } + segments.reverse(); return segments; }; @@ -576,7 +581,7 @@ > {#if !usingMobileDevice} {#if segment.hasLabel} -
+
{segment.year}
{/if} diff --git a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts index 9f879fe1b1..d2340224a2 100644 --- a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts +++ b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts @@ -234,6 +234,7 @@ export class TimelineManager extends VirtualScrollManager { await this.initTask.reset(); await this.#init(options); this.updateViewportGeometry(false); + this.#createScrubberMonths(); } async #init(options: TimelineManagerOptions) {