feat(web): face overlay hover UX and face editor zoom preservation

Change-Id: I7164305d7764bec54fa06b8738cd97fd6a6a6964

refactor(web): use asset metadata for face editor image dimensions instead of DOM

The face editor previously read naturalWidth/naturalHeight from the DOM
element via a $effect + load event listener. This was fragile on slow
hardware (ARM CI) because imgRef changes as AdaptiveImage progresses
through quality levels, and the DOM element's natural dimensions could
be 0 during transitions.

Now the face editor receives imageSize as a prop from the parent, derived
from the asset's metadata dimensions which are always available immediately.

Change-Id: Id4c3a59110feff4c50f429bbd744eac46a6a6964
Change-Id: I7164305d7764bec54fa06b8738cd97fd6a6a6964
This commit is contained in:
midzelis
2026-03-19 13:02:46 +00:00
parent ed04d87273
commit 590a9df7ec
21 changed files with 1147 additions and 208 deletions

View File

@@ -11,14 +11,16 @@
videoViewerVolume,
} from '$lib/stores/preferences.store';
import { getAssetMediaUrl, getAssetPlaybackUrl } from '$lib/utils';
import type { Size } from '$lib/utils/container-utils';
import { AssetMediaSize } from '@immich/sdk';
import { LoadingSpinner } from '@immich/ui';
import { onDestroy, onMount } from 'svelte';
import { useSwipe, type SwipeCustomEvent } from 'svelte-gestures';
import { fade } from 'svelte/transition';
interface Props {
type Props = {
assetId: string;
imageSize: Size;
loopVideo: boolean;
cacheKey: string | null;
playOriginalVideo: boolean;
@@ -27,10 +29,11 @@
onVideoEnded?: () => void;
onVideoStarted?: () => void;
onClose?: () => void;
}
};
let {
assetId,
imageSize,
loopVideo,
cacheKey,
playOriginalVideo,
@@ -173,7 +176,7 @@
{/if}
{#if isFaceEditMode.value}
<FaceEditor htmlElement={videoPlayer} {containerWidth} {containerHeight} {assetId} />
<FaceEditor {imageSize} {containerWidth} {containerHeight} {assetId} />
{/if}
{/if}
</div>