0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-21 00:52:43 -05:00

feat(web): load original image when zooming (#4040)

* feat(web): change max zoom from 4 to 10

* feat(web): load original image when zooming
This commit is contained in:
Louis-Marie Michelin 2023-09-12 17:42:41 +02:00 committed by GitHub
parent 52d0c5fc73
commit bf3b38a7f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 5 deletions

View file

@ -6,12 +6,14 @@
import { notificationController, NotificationType } from '../shared-components/notification/notification'; import { notificationController, NotificationType } from '../shared-components/notification/notification';
import { useZoomImageWheel } from '@zoom-image/svelte'; import { useZoomImageWheel } from '@zoom-image/svelte';
import { photoZoomState } from '$lib/stores/zoom-image.store'; import { photoZoomState } from '$lib/stores/zoom-image.store';
import { isWebCompatibleImage } from '$lib/utils/asset-utils';
export let asset: AssetResponseDto; export let asset: AssetResponseDto;
export let element: HTMLDivElement | undefined = undefined; export let element: HTMLDivElement | undefined = undefined;
let imgElement: HTMLDivElement; let imgElement: HTMLDivElement;
let assetData: string; let assetData: string;
let hasZoomed = false;
let copyImageToClipboard: (src: string) => Promise<Blob>; let copyImageToClipboard: (src: string) => Promise<Blob>;
let canCopyImagesToClipboard: () => boolean; let canCopyImagesToClipboard: () => boolean;
@ -23,10 +25,10 @@
canCopyImagesToClipboard = module.canCopyImagesToClipboard; canCopyImagesToClipboard = module.canCopyImagesToClipboard;
}); });
const loadAssetData = async () => { const loadAssetData = async ({ loadOriginal }: { loadOriginal: boolean }) => {
try { try {
const { data } = await api.assetApi.serveFile( const { data } = await api.assetApi.serveFile(
{ id: asset.id, isThumb: false, isWeb: true, key: api.getKey() }, { id: asset.id, isThumb: false, isWeb: !loadOriginal, key: api.getKey() },
{ {
responseType: 'blob', responseType: 'blob',
}, },
@ -37,7 +39,6 @@
} }
assetData = URL.createObjectURL(data); assetData = URL.createObjectURL(data);
return assetData;
} catch { } catch {
// Do nothing // Do nothing
} }
@ -87,10 +88,16 @@
zoomImageWheelState.subscribe((state) => { zoomImageWheelState.subscribe((state) => {
photoZoomState.set(state); photoZoomState.set(state);
if (state.currentZoom > 1 && isWebCompatibleImage(asset) && !hasZoomed) {
hasZoomed = true;
loadAssetData({ loadOriginal: true });
}
}); });
$: if (imgElement) { $: if (imgElement) {
createZoomImageWheel(imgElement, { createZoomImageWheel(imgElement, {
maxZoom: 10,
wheelZoomRatio: 0.2, wheelZoomRatio: 0.2,
}); });
} }
@ -103,9 +110,9 @@
transition:fade={{ duration: 150 }} transition:fade={{ duration: 150 }}
class="flex h-full select-none place-content-center place-items-center" class="flex h-full select-none place-content-center place-items-center"
> >
{#await loadAssetData()} {#await loadAssetData({ loadOriginal: false })}
<LoadingSpinner /> <LoadingSpinner />
{:then assetData} {:then}
<div bind:this={imgElement} class="h-full w-full"> <div bind:this={imgElement} class="h-full w-full">
<img <img
transition:fade={{ duration: 150 }} transition:fade={{ duration: 150 }}

View file

@ -173,3 +173,15 @@ export function getAssetRatio(asset: AssetResponseDto) {
} }
return { width, height }; return { width, height };
} }
// list of supported image extensions from https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types excluding svg
const supportedImageExtensions = new Set(['apng', 'avif', 'gif', 'jpg', 'jpeg', 'jfif', 'pjpeg', 'pjp', 'png', 'webp']);
/**
* Returns true if the asset is an image supported by web browsers, false otherwise
*/
export function isWebCompatibleImage(asset: AssetResponseDto): boolean {
const imgExtension = getFilenameExtension(asset.originalPath);
return supportedImageExtensions.has(imgExtension);
}