mirror of
https://github.com/immich-app/immich.git
synced 2026-03-22 23:29:00 +03:00
* feat(web): adaptive progressive image loading for photo viewer Replace ImageManager with a new AdaptiveImageLoader that progressively loads images through quality tiers (thumbnail → preview → original). New components and utilities: - AdaptiveImage: layered image renderer with thumbhash, thumbnail, preview, and original layers with visibility managed by load state - AdaptiveImageLoader: state machine driving the quality progression with per-quality callbacks and error handling - ImageLayer/Image: low-level image elements with load/error lifecycle - PreloadManager: preloads adjacent assets for instant navigation - AlphaBackground/DelayedLoadingSpinner: loading state UI Zoom is handled via a derived CSS transform applied to the content wrapper in AdaptiveImage, with the zoom library (zoomTarget: null) only tracking state without manipulating the DOM directly. Also adds scaleToCover to container-utils and getAssetUrls to utils. * fix: don't partially render images in firefox * add passive loading indicator to asset-viewer --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
48 lines
1.1 KiB
Svelte
48 lines
1.1 KiB
Svelte
<script lang="ts">
|
|
import Image from '$lib/components/Image.svelte';
|
|
import type { AdaptiveImageLoader, ImageQuality } from '$lib/utils/adaptive-image-loader.svelte';
|
|
import type { Snippet } from 'svelte';
|
|
|
|
type Props = {
|
|
adaptiveImageLoader: AdaptiveImageLoader;
|
|
quality: ImageQuality;
|
|
src: string | undefined;
|
|
alt?: string;
|
|
role?: string;
|
|
ref?: HTMLImageElement;
|
|
width: string;
|
|
height: string;
|
|
overlays?: Snippet;
|
|
};
|
|
|
|
let {
|
|
adaptiveImageLoader,
|
|
quality,
|
|
src,
|
|
alt = '',
|
|
role,
|
|
ref = $bindable(),
|
|
width,
|
|
height,
|
|
overlays,
|
|
}: Props = $props();
|
|
</script>
|
|
|
|
{#key adaptiveImageLoader}
|
|
<div class="absolute top-0" style:width style:height>
|
|
<Image
|
|
{src}
|
|
onStart={() => adaptiveImageLoader.onStart(quality)}
|
|
onLoad={() => adaptiveImageLoader.onLoad(quality)}
|
|
onError={() => adaptiveImageLoader.onError(quality)}
|
|
bind:ref
|
|
class="h-full w-full bg-transparent"
|
|
{alt}
|
|
{role}
|
|
draggable={false}
|
|
data-testid={quality}
|
|
/>
|
|
{@render overlays?.()}
|
|
</div>
|
|
{/key}
|