chore(web): revert wasm new justify layout ()

* Revert "fix(web): justify layout import () "

This reverts commit ec58e1065f.

* Revert "fix(web): dynamically import wasm module ()"

This reverts commit 4376fd72b7.

* Revert "feat(web): use wasm for justified layout calculation ()"

This reverts commit 3925445de8.

* Revert "fix(web): viewport reactivity, off-screen thumbhashes being rendered ()"

This reverts commit 52f21fb331.
This commit is contained in:
Alex 2025-02-25 09:39:56 -06:00 committed by GitHub
parent 16266c9f5a
commit bbcaee82f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 201 additions and 330 deletions
web/src/lib/components/photos-page

View file

@ -20,7 +20,7 @@
} from '$lib/utils/timeline-util';
import { TUNABLES } from '$lib/utils/tunables';
import type { AlbumResponseDto, AssetResponseDto, PersonResponseDto } from '@immich/sdk';
import { debounce, throttle } from 'lodash-es';
import { throttle } from 'lodash-es';
import { onDestroy, onMount, type Snippet } from 'svelte';
import Portal from '../shared-components/portal/portal.svelte';
import Scrubber from '../shared-components/scrubber/scrubber.svelte';
@ -81,9 +81,8 @@
let { isViewing: showAssetViewer, asset: viewingAsset, preloadAssets, gridScrollTarget } = assetViewingStore;
// this does *not* need to be reactive and making it reactive causes expensive repeated updates
// svelte-ignore non_reactive_update
let safeViewport: ViewportXY = { width: 0, height: 0, x: 0, y: 0 };
const viewport: ViewportXY = $state({ width: 0, height: 0, x: 0, y: 0 });
const safeViewport: ViewportXY = $state({ width: 0, height: 0, x: 0, y: 0 });
const componentId = generateId();
let element: HTMLElement | undefined = $state();
@ -104,7 +103,7 @@
let leadout = $state(false);
const {
ASSET_GRID: { NAVIGATE_ON_ASSET_IN_VIEW, LARGE_BUCKET_THRESHOLD, LARGE_BUCKET_DEBOUNCE_MS },
ASSET_GRID: { NAVIGATE_ON_ASSET_IN_VIEW },
BUCKET: {
INTERSECTION_ROOT_TOP: BUCKET_INTERSECTION_ROOT_TOP,
INTERSECTION_ROOT_BOTTOM: BUCKET_INTERSECTION_ROOT_BOTTOM,
@ -115,6 +114,14 @@
},
} = TUNABLES;
const isViewportOrigin = () => {
return viewport.height === 0 && viewport.width === 0;
};
const isEqual = (a: ViewportXY, b: ViewportXY) => {
return a.height == b.height && a.width == b.width && a.x === b.x && a.y === b.y;
};
const completeNav = () => {
navigating = false;
if (internalScroll) {
@ -228,14 +235,6 @@
};
onMount(() => {
if (element) {
const rect = element.getBoundingClientRect();
safeViewport.height = rect.height;
safeViewport.width = rect.width;
safeViewport.x = rect.x;
safeViewport.y = rect.y;
}
void $assetStore
.init({ bucketListener })
.then(() => ($assetStore.connect(), $assetStore.updateViewport(safeViewport)));
@ -260,6 +259,8 @@
}
return offset;
}
const _updateViewport = () => void $assetStore.updateViewport(safeViewport);
const updateViewport = throttle(_updateViewport, 16);
const getMaxScrollPercent = () =>
($assetStore.timelineHeight + bottomSectionHeight + topSectionHeight - safeViewport.height) /
@ -743,8 +744,23 @@
}
});
let largeBucketMode = false;
let updateViewport = debounce(() => $assetStore.updateViewport(safeViewport), 8);
$effect(() => {
if (element && isViewportOrigin()) {
const rect = element.getBoundingClientRect();
viewport.height = rect.height;
viewport.width = rect.width;
viewport.x = rect.x;
viewport.y = rect.y;
}
if (!isViewportOrigin() && !isEqual(viewport, safeViewport)) {
safeViewport.height = viewport.height;
safeViewport.width = viewport.width;
safeViewport.x = viewport.x;
safeViewport.y = viewport.y;
updateViewport();
}
});
let shortcutList = $derived(
(() => {
if ($isSearchEnabled || $showAssetViewer) {
@ -827,21 +843,7 @@
id="asset-grid"
class="scrollbar-hidden h-full overflow-y-auto outline-none {isEmpty ? 'm-0' : 'ml-4 tall:ml-0 mr-[60px]'}"
tabindex="-1"
use:resizeObserver={({ width, height }) => {
if (!largeBucketMode && assetStore.maxBucketAssets >= LARGE_BUCKET_THRESHOLD) {
largeBucketMode = true;
// Each viewport update causes each asset to re-decode both the thumbhash and the thumbnail.
// This is because the thumbnail components are destroyed and re-mounted, possibly because of the intersection observer.
// For larger buckets, this can lead to freezing and a poor user experience.
// As a mitigation, we aggressively debounce the viewport update to reduce the number of these events.
updateViewport = debounce(() => $assetStore.updateViewport(safeViewport), LARGE_BUCKET_DEBOUNCE_MS, {
leading: false,
trailing: true,
});
}
safeViewport = { width, height, x: safeViewport.x, y: safeViewport.y };
void updateViewport();
}}
use:resizeObserver={({ height, width }) => ((viewport.width = width), (viewport.height = height))}
bind:this={element}
onscroll={() => ((assetStore.lastScrollTime = Date.now()), handleTimelineScroll())}
>