fix(web): limit max height of search results (#20727)

The height of the search results element was unrestricted, which meant that the
asset visibility calculations were completely incorrect. The consequence of
this is that assets which should not have been visible, were. In practical
terms, all assets below the viewport were rendered when they shouldn't have
been which is terrible for performance. Limiting the height of the viewport
fixes that calculation and assets are correctly hidden.

The consequence of limiting the height of the viewport is that the intersector
then incorrectly thought the scroll position was always at the end. This has
been fixed by calculating the position of sliding window against the calculated
asset layout container height.

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Thomas 2025-08-06 23:05:23 +01:00 committed by GitHub
parent f36efd128b
commit 746252fe39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 7 additions and 6 deletions

View File

@ -145,12 +145,13 @@
let lastIntersectedHeight = 0;
$effect(() => {
// notify we got to (near) the end of scroll
const scrollPercentage =
((slidingWindow.bottom - viewport.height) / (viewport.height - (document.scrollingElement?.clientHeight || 0))) *
100;
const scrollRatio = slidingWindow.bottom / assetLayouts.containerHeight;
if (scrollPercentage > 90) {
// TODO: We may want to limit to an absolute value as the ratio scaling will
// get weird with lots of assets. The page may be nowhere near the bottom in
// absolute terms, and yet the intersection will still be triggered.
if (scrollRatio > 0.9) {
// Notify we got to (near) the end of scroll.
const intersectedHeight = geometry?.containerHeight || 0;
if (lastIntersectedHeight !== intersectedHeight) {
debouncedOnIntersected();

View File

@ -360,7 +360,7 @@
{/if}
<section
class="mb-12 bg-immich-bg dark:bg-immich-dark-bg m-4"
class="mb-12 bg-immich-bg dark:bg-immich-dark-bg m-4 max-h-screen"
bind:clientHeight={viewport.height}
bind:clientWidth={viewport.width}
bind:this={searchResultsElement}