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) {