feat(web): wasm justified layout, sync edition (#23194)

* the invisible wasm

use npm version

* deterministic tests

* add todo

* linting

* bump library, add helpers

* use target height for unfilled rows

* update tests
This commit is contained in:
Mert
2025-10-25 01:06:05 -04:00
committed by GitHub
parent 328380cfda
commit 3f03a88767
12 changed files with 93 additions and 117 deletions

View File

@@ -26,12 +26,12 @@ export abstract class VirtualScrollManager {
#suspendTransitions = $state(false);
#resetScrolling = debounce(() => (this.#scrolling = false), 1000);
#resetSuspendTransitions = debounce(() => (this.suspendTransitions = false), 1000);
#justifiedLayoutOptions = $derived.by(() => ({
#justifiedLayoutOptions = $derived({
spacing: 2,
heightTolerance: 0.15,
heightTolerance: 0.5,
rowHeight: this.#rowHeight,
rowWidth: Math.floor(this.viewportWidth),
}));
});
constructor() {
this.setLayoutOptions();

View File

@@ -1,7 +1,7 @@
import { AssetOrder } from '@immich/sdk';
import type { CommonLayoutOptions } from '$lib/utils/layout-utils';
import { getJustifiedLayoutFromAssets, getPosition } from '$lib/utils/layout-utils';
import { getJustifiedLayoutFromAssets } from '$lib/utils/layout-utils';
import { plainDateTimeCompare } from '$lib/utils/timeline-util';
import { SvelteSet } from 'svelte/reactivity';
@@ -148,9 +148,9 @@ export class DayGroup {
const geometry = getJustifiedLayoutFromAssets(assets, options);
this.width = geometry.containerWidth;
this.height = assets.length === 0 ? 0 : geometry.containerHeight;
// TODO: lazily get positions instead of loading them all here
for (let i = 0; i < this.viewerAssets.length; i++) {
const position = getPosition(geometry, i);
this.viewerAssets[i].position = position;
this.viewerAssets[i].position = geometry.getPosition(i);
}
}

View File

@@ -82,15 +82,15 @@ describe('TimelineManager', () => {
expect(plainMonths).toEqual(
expect.arrayContaining([
expect.objectContaining({ year: 2024, month: 3, height: 165.5 }),
expect.objectContaining({ year: 2024, month: 2, height: 11_996 }),
expect.objectContaining({ year: 2024, month: 3, height: 283 }),
expect.objectContaining({ year: 2024, month: 2, height: 7711 }),
expect.objectContaining({ year: 2024, month: 1, height: 286 }),
]),
);
});
it('calculates timeline height', () => {
expect(timelineManager.totalViewerHeight).toBe(12_507.5);
expect(timelineManager.totalViewerHeight).toBe(8340);
});
});

View File

@@ -18,7 +18,7 @@ export class ViewerAsset {
return calculateViewerAssetIntersecting(store, positionTop, this.position.height);
});
position: CommonPosition | undefined = $state();
position: CommonPosition | undefined = $state.raw();
asset: TimelineAsset = <TimelineAsset>$state();
id: string = $derived(this.asset.id);