mirror of
https://github.com/immich-app/immich.git
synced 2025-01-17 01:06:46 +01: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:
parent
52d0c5fc73
commit
bf3b38a7f2
2 changed files with 24 additions and 5 deletions
|
@ -6,12 +6,14 @@
|
|||
import { notificationController, NotificationType } from '../shared-components/notification/notification';
|
||||
import { useZoomImageWheel } from '@zoom-image/svelte';
|
||||
import { photoZoomState } from '$lib/stores/zoom-image.store';
|
||||
import { isWebCompatibleImage } from '$lib/utils/asset-utils';
|
||||
|
||||
export let asset: AssetResponseDto;
|
||||
export let element: HTMLDivElement | undefined = undefined;
|
||||
|
||||
let imgElement: HTMLDivElement;
|
||||
let assetData: string;
|
||||
let hasZoomed = false;
|
||||
let copyImageToClipboard: (src: string) => Promise<Blob>;
|
||||
let canCopyImagesToClipboard: () => boolean;
|
||||
|
||||
|
@ -23,10 +25,10 @@
|
|||
canCopyImagesToClipboard = module.canCopyImagesToClipboard;
|
||||
});
|
||||
|
||||
const loadAssetData = async () => {
|
||||
const loadAssetData = async ({ loadOriginal }: { loadOriginal: boolean }) => {
|
||||
try {
|
||||
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',
|
||||
},
|
||||
|
@ -37,7 +39,6 @@
|
|||
}
|
||||
|
||||
assetData = URL.createObjectURL(data);
|
||||
return assetData;
|
||||
} catch {
|
||||
// Do nothing
|
||||
}
|
||||
|
@ -87,10 +88,16 @@
|
|||
|
||||
zoomImageWheelState.subscribe((state) => {
|
||||
photoZoomState.set(state);
|
||||
|
||||
if (state.currentZoom > 1 && isWebCompatibleImage(asset) && !hasZoomed) {
|
||||
hasZoomed = true;
|
||||
loadAssetData({ loadOriginal: true });
|
||||
}
|
||||
});
|
||||
|
||||
$: if (imgElement) {
|
||||
createZoomImageWheel(imgElement, {
|
||||
maxZoom: 10,
|
||||
wheelZoomRatio: 0.2,
|
||||
});
|
||||
}
|
||||
|
@ -103,9 +110,9 @@
|
|||
transition:fade={{ duration: 150 }}
|
||||
class="flex h-full select-none place-content-center place-items-center"
|
||||
>
|
||||
{#await loadAssetData()}
|
||||
{#await loadAssetData({ loadOriginal: false })}
|
||||
<LoadingSpinner />
|
||||
{:then assetData}
|
||||
{:then}
|
||||
<div bind:this={imgElement} class="h-full w-full">
|
||||
<img
|
||||
transition:fade={{ duration: 150 }}
|
||||
|
|
|
@ -173,3 +173,15 @@ export function getAssetRatio(asset: AssetResponseDto) {
|
|||
}
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue