diff --git a/web/src/lib/components/search/SearchResults.svelte b/web/src/lib/components/search/SearchResults.svelte
index 8b43e43317..3805ce984c 100644
--- a/web/src/lib/components/search/SearchResults.svelte
+++ b/web/src/lib/components/search/SearchResults.svelte
@@ -9,8 +9,10 @@
import StreamWithViewer from '$lib/components/timeline/StreamWithViewer.svelte';
import Skeleton from '$lib/elements/Skeleton.svelte';
import { SearchResultsManager } from '$lib/managers/searchresults-manager/SearchResultsManager.svelte';
+ import { SearchResultsSegment } from '$lib/managers/searchresults-manager/SearchResultsSegment.svelte';
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
+ import { LoadingSpinner } from '@immich/ui';
import type { Snippet } from 'svelte';
interface Props {
@@ -92,5 +94,12 @@
{/snippet}
{/snippet}
+ {#snippet segmentFooter({ segment })}
+ {#if (segment as SearchResultsSegment).hasNextPage}
+
+
+
+ {/if}
+ {/snippet}
diff --git a/web/src/lib/components/timeline/Photostream.svelte b/web/src/lib/components/timeline/Photostream.svelte
index b71308114a..d1eb7f663d 100644
--- a/web/src/lib/components/timeline/Photostream.svelte
+++ b/web/src/lib/components/timeline/Photostream.svelte
@@ -18,6 +18,13 @@
},
]
>;
+ segmentFooter: Snippet<
+ [
+ {
+ segment: PhotostreamSegment;
+ },
+ ]
+ >;
skeleton: Snippet<
[
{
@@ -59,6 +66,8 @@
let {
segment,
+ segmentFooter,
+ skeleton,
enableRouting,
timelineManager = $bindable(),
@@ -72,7 +81,7 @@
isShowDeleteConfirmation = $bindable(false),
children,
- skeleton,
+
empty,
header,
handleTimelineScroll = () => {},
@@ -89,7 +98,6 @@
let { gridScrollTarget } = assetViewingStore;
let element: HTMLElement | undefined = $state();
- let timelineElement: HTMLElement | undefined = $state();
const maxMd = $derived(mobileDevice.maxMd);
const isEmpty = $derived(timelineManager.isInitialized && timelineManager.months.length === 0);
@@ -97,6 +105,9 @@
$effect(() => {
const layoutOptions = maxMd ? smallHeaderHeight : largeHeaderHeight;
timelineManager.setLayoutOptions(layoutOptions);
+ // this next line is important in order to ensure that the reactive signals of ViewerAsset.#intersecting
+ // are marked as dependencies of timeline.#scrollTop.
+ updateSlidingWindow();
});
const scrollTo = (top: number) => {
@@ -205,7 +216,6 @@
onscroll={() => (handleTimelineScroll(), updateSlidingWindow(), updateIsScrolling())}
>
+ {#if segmentFooter}
+
+ {@render segmentFooter?.({ segment: monthGroup })}
+
+ {/if}
{/each}
viewAsset.id === assetId);
if (viewerAsset) {