diff --git a/web/src/lib/components/photos-page/asset-grid-without-scrubber.svelte b/web/src/lib/components/photos-page/asset-grid-without-scrubber.svelte
new file mode 100644
index 0000000000..6633b0f27c
--- /dev/null
+++ b/web/src/lib/components/photos-page/asset-grid-without-scrubber.svelte
@@ -0,0 +1,375 @@
+
+
+
+
+
+
+{@render header?.(scrollTop)}
+
+
+
+
+
+ {#if $showAssetViewer}
+
+ {/if}
+
+
+
diff --git a/web/src/lib/components/photos-page/asset-grid.svelte b/web/src/lib/components/photos-page/asset-grid.svelte
index fcb655ee6b..caec698491 100644
--- a/web/src/lib/components/photos-page/asset-grid.svelte
+++ b/web/src/lib/components/photos-page/asset-grid.svelte
@@ -1,26 +1,14 @@
-
-
-
-
-{#if timelineManager.months.length > 0}
-
-{/if}
-
-
-
-
-
- {#if $showAssetViewer}
-
- {/if}
-
-
-
+ {#snippet header(handleScrollTop)}
+ {#if timelineManager.months.length > 0}
+ onScrub({ ...args, handleScrollTop })}
+ bind:scrubberWidth
+ />
+ {/if}
+ {/snippet}
+
diff --git a/web/src/lib/components/shared-components/scrubber/scrubber.svelte b/web/src/lib/components/shared-components/scrubber/scrubber.svelte
index 4e49f9a012..83f9919279 100644
--- a/web/src/lib/components/shared-components/scrubber/scrubber.svelte
+++ b/web/src/lib/components/shared-components/scrubber/scrubber.svelte
@@ -295,12 +295,24 @@
const scrollPercent = toTimelineY(hoverY);
if (wasDragging === false && isDragging) {
- void startScrub?.(segmentDate!, scrollPercent, monthGroupPercentY);
- void onScrub?.(segmentDate!, scrollPercent, monthGroupPercentY);
+ void startScrub?.({
+ scrubberMonth: segmentDate!,
+ overallScrollPercent: scrollPercent,
+ scrubberMonthScrollPercent: monthGroupPercentY,
+ });
+ void onScrub?.({
+ scrubberMonth: segmentDate!,
+ overallScrollPercent: scrollPercent,
+ scrubberMonthScrollPercent: monthGroupPercentY,
+ });
}
if (wasDragging && !isDragging) {
- void stopScrub?.(segmentDate!, scrollPercent, monthGroupPercentY);
+ void stopScrub?.({
+ scrubberMonth: segmentDate!,
+ overallScrollPercent: scrollPercent,
+ scrubberMonthScrollPercent: monthGroupPercentY,
+ });
return;
}
@@ -308,7 +320,11 @@
return;
}
- void onScrub?.(segmentDate!, scrollPercent, monthGroupPercentY);
+ void onScrub?.({
+ scrubberMonth: segmentDate!,
+ overallScrollPercent: scrollPercent,
+ scrubberMonthScrollPercent: monthGroupPercentY,
+ });
};
/* eslint-disable tscompat/tscompat */
const getTouch = (event: TouchEvent) => {
@@ -412,7 +428,11 @@
}
if (next) {
event.preventDefault();
- void onScrub?.({ year: next.year, month: next.month }, -1, 0);
+ void onScrub?.({
+ scrubberMonth: { year: next.year, month: next.month },
+ overallScrollPercent: -1,
+ scrubberMonthScrollPercent: 0,
+ });
return true;
}
}
@@ -422,7 +442,11 @@
const next = segments[idx + 1];
if (next) {
event.preventDefault();
- void onScrub?.({ year: next.year, month: next.month }, -1, 0);
+ void onScrub?.({
+ scrubberMonth: { year: next.year, month: next.month },
+ overallScrollPercent: -1,
+ scrubberMonthScrollPercent: 0,
+ });
return true;
}
}
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 8aacd0a90a..803b6c3dd4 100644
--- a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts
+++ b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts
@@ -41,6 +41,7 @@ export class TimelineManager {
isInitialized = $state(false);
months: MonthGroup[] = $state([]);
topSectionHeight = $state(0);
+ bottomSectionHeight = $state(60);
timelineHeight = $derived(this.months.reduce((accumulator, b) => accumulator + b.height, 0) + this.topSectionHeight);
assetCount = $derived(this.months.reduce((accumulator, b) => accumulator + b.assetsCount, 0));
@@ -540,4 +541,13 @@ export class TimelineManager {
isMismatched(this.#options.isTrashed, asset.isTrashed)
);
}
+
+ getMaxScrollPercent() {
+ const totalHeight = this.timelineHeight + this.bottomSectionHeight + this.topSectionHeight;
+ return (totalHeight - this.viewportHeight) / totalHeight;
+ }
+
+ getMaxScroll() {
+ return this.topSectionHeight + this.bottomSectionHeight + (this.timelineHeight - this.viewportHeight);
+ }
}
diff --git a/web/src/lib/utils/timeline-util.ts b/web/src/lib/utils/timeline-util.ts
index c3e41c01be..cfe9454d26 100644
--- a/web/src/lib/utils/timeline-util.ts
+++ b/web/src/lib/utils/timeline-util.ts
@@ -22,11 +22,12 @@ export type TimelinePlainDateTime = TimelinePlainDate & {
millisecond: number;
};
-export type ScrubberListener = (
- scrubberMonth: { year: number; month: number },
- overallScrollPercent: number,
- scrubberMonthScrollPercent: number,
-) => void | Promise;
+export type ScrubberListener = (args: {
+ scrubberMonth: { year: number; month: number };
+ overallScrollPercent: number;
+ scrubberMonthScrollPercent: number;
+ handleScrollTop?: (top: number) => void;
+}) => void | Promise;
// used for AssetResponseDto.dateTimeOriginal, amongst others
export const fromISODateTime = (isoDateTime: string, timeZone: string): DateTime =>