mirror of
https://github.com/immich-app/immich.git
synced 2026-03-22 10:50:02 +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>
47 lines
884 B
Svelte
47 lines
884 B
Svelte
<script lang="ts">
|
|
import type { ClassValue } from 'svelte/elements';
|
|
|
|
interface Props {
|
|
class?: ClassValue;
|
|
}
|
|
|
|
let { class: className }: Props = $props();
|
|
</script>
|
|
|
|
<div class="delayed inline-flex items-center gap-1 {className}">
|
|
{#each [0, 1, 2] as i (i)}
|
|
<span class="dot block size-1.5 rounded-full bg-white shadow-[0_0_3px_rgba(0,0,0,0.6)]" style:--delay="{i * 0.25}s"
|
|
></span>
|
|
{/each}
|
|
</div>
|
|
|
|
<style>
|
|
.delayed {
|
|
visibility: hidden;
|
|
animation: delayed-visibility 0s linear 0.4s forwards;
|
|
}
|
|
|
|
@keyframes delayed-visibility {
|
|
to {
|
|
visibility: visible;
|
|
}
|
|
}
|
|
|
|
.dot {
|
|
animation: dot-stream 1.6s var(--delay, 0s) ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes dot-stream {
|
|
0%,
|
|
80%,
|
|
100% {
|
|
opacity: 0.3;
|
|
transform: scale(0.8);
|
|
}
|
|
40% {
|
|
opacity: 1;
|
|
transform: scale(1.15);
|
|
}
|
|
}
|
|
</style>
|