mirror of
https://github.com/immich-app/immich.git
synced 2025-12-23 09:15:05 +03:00
feat(web): Scroll to asset in gridview; increase gridview perf; reduce memory; scrollbar ticks in fixed position (#10646)
* Squashed * Change strategy - now pre-measure buckets offscreen, so don't need to worry about sub-bucket scroll preservation * Reduce jank on scroll, delay DOM updates until after scroll * css opt, log measure time * Trickle out queue while scrolling, flush when stopped * yay * Cleanup cleanup... * everybody... * everywhere... * Clean up cleanup! * Everybody do their share * CLEANUP! * package-lock ? * dynamic measure, todo * Fix web test * type lint * fix e2e * e2e test * Better scrollbar * Tuning, and more tunables * Tunable tweaks, more tunables * Scrollbar dots and viewport events * lint * Tweaked tunnables, use requestIdleCallback for garbage tasks, bug fixes * New tunables, and don't update url by default * Bug fixes * Bug fix, with debug * Fix flickr, fix graybox bug, reduced debug * Refactor/cleanup * Fix * naming * Final cleanup * review comment * Forgot to update this after naming change * scrubber works, with debug * cleanup * Rename scrollbar to scrubber * rename to * left over rename and change to previous album bar * bugfix addassets, comments * missing destroy(), cleanup --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
89
web/src/lib/components/photos-page/measure-date-group.svelte
Normal file
89
web/src/lib/components/photos-page/measure-date-group.svelte
Normal file
@@ -0,0 +1,89 @@
|
||||
<script lang="ts" context="module">
|
||||
const recentTimes: number[] = [];
|
||||
// TODO: track average time to measure, and use this to populate TUNABLES.ASSETS_STORE.CHECK_INTERVAL_MS
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function adjustTunables(avg: number) {}
|
||||
function addMeasure(time: number) {
|
||||
recentTimes.push(time);
|
||||
if (recentTimes.length > 10) {
|
||||
recentTimes.shift();
|
||||
}
|
||||
const sum = recentTimes.reduce((acc: number, val: number) => {
|
||||
return acc + val;
|
||||
}, 0);
|
||||
const avg = sum / recentTimes.length;
|
||||
adjustTunables(avg);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { resizeObserver } from '$lib/actions/resize-observer';
|
||||
import type { AssetBucket, AssetStore, BucketListener } from '$lib/stores/assets.store';
|
||||
|
||||
export let assetStore: AssetStore;
|
||||
export let bucket: AssetBucket;
|
||||
export let onMeasured: () => void;
|
||||
|
||||
async function _measure(element: Element) {
|
||||
try {
|
||||
await bucket.complete;
|
||||
const t1 = Date.now();
|
||||
let heightPending = bucket.dateGroups.some((group) => !group.heightActual);
|
||||
if (heightPending) {
|
||||
const listener: BucketListener = (event) => {
|
||||
const { type } = event;
|
||||
if (type === 'height') {
|
||||
const { bucket: changedBucket } = event;
|
||||
if (changedBucket === bucket && type === 'height') {
|
||||
heightPending = bucket.dateGroups.some((group) => !group.heightActual);
|
||||
if (!heightPending) {
|
||||
const height = element.getBoundingClientRect().height;
|
||||
if (height !== 0) {
|
||||
$assetStore.updateBucket(bucket.bucketDate, { height: height, measured: true });
|
||||
}
|
||||
|
||||
onMeasured();
|
||||
$assetStore.removeListener(listener);
|
||||
const t2 = Date.now();
|
||||
|
||||
addMeasure((t2 - t1) / bucket.bucketCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
assetStore.addListener(listener);
|
||||
}
|
||||
} catch {
|
||||
// ignore if complete rejects (canceled load)
|
||||
}
|
||||
}
|
||||
function measure(element: Element) {
|
||||
void _measure(element);
|
||||
}
|
||||
</script>
|
||||
|
||||
<section id="measure-asset-group-by-date" class="flex flex-wrap gap-x-12" use:measure>
|
||||
{#each bucket.dateGroups as dateGroup}
|
||||
<div id="date-group" data-date-group={dateGroup.date}>
|
||||
<div
|
||||
use:resizeObserver={({ height }) => $assetStore.updateBucketDateGroup(bucket, dateGroup, { height: height })}
|
||||
>
|
||||
<div
|
||||
class="flex z-[100] sticky top-[-1px] pt-7 pb-5 h-6 place-items-center text-xs font-medium text-immich-fg bg-immich-bg dark:bg-immich-dark-bg dark:text-immich-dark-fg md:text-sm"
|
||||
style:width={dateGroup.geometry.containerWidth + 'px'}
|
||||
>
|
||||
<span class="w-full truncate first-letter:capitalize">
|
||||
{dateGroup.groupTitle}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="relative overflow-clip"
|
||||
style:height={dateGroup.geometry.containerHeight + 'px'}
|
||||
style:width={dateGroup.geometry.containerWidth + 'px'}
|
||||
style:visibility={'hidden'}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</section>
|
||||
Reference in New Issue
Block a user