mirror of
https://github.com/immich-app/immich.git
synced 2025-07-07 09:12:56 +02:00
chore(web): revert wasm new justify layout (#16277)
* Revert "fix(web): justify layout import (#16267) " This reverts commitec58e1065f
. * Revert "fix(web): dynamically import wasm module (#16261)" This reverts commit4376fd72b7
. * Revert "feat(web): use wasm for justified layout calculation (#15524)" This reverts commit3925445de8
. * Revert "fix(web): viewport reactivity, off-screen thumbhashes being rendered (#15435)" This reverts commit52f21fb331
.
This commit is contained in:
parent
16266c9f5a
commit
bbcaee82f0
14 changed files with 201 additions and 330 deletions
web/src/lib/components/photos-page
|
@ -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())}
|
||||
>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue