diff --git a/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte b/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte
index 00e845e8ec..29626ea265 100644
--- a/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte
+++ b/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte
@@ -25,7 +25,6 @@
import { Route } from '$lib/route';
import { getGlobalActions } from '$lib/services/app.service';
import { getAssetActions } from '$lib/services/asset.service';
- import { isFaceEditMode } from '$lib/stores/face-edit.svelte';
import { user } from '$lib/stores/user.store';
import { getSharedLink, withoutIcons } from '$lib/utils';
import type { OnUndoDelete } from '$lib/utils/actions';
@@ -93,7 +92,7 @@
title: $t('go_back'),
type: $t('assets'),
icon: languageManager.rtl ? mdiArrowRight : mdiArrowLeft,
- $if: () => !!onClose && !isFaceEditMode.value,
+ $if: () => !!onClose && !assetViewerManager.isFaceEditMode,
onAction: () => onClose?.(),
shortcuts: [{ key: 'Escape' }],
});
diff --git a/web/src/lib/components/asset-viewer/asset-viewer.svelte b/web/src/lib/components/asset-viewer/asset-viewer.svelte
index e2981e2e55..1072104d4d 100644
--- a/web/src/lib/components/asset-viewer/asset-viewer.svelte
+++ b/web/src/lib/components/asset-viewer/asset-viewer.svelte
@@ -14,7 +14,6 @@
import { editManager, EditToolType } from '$lib/managers/edit/edit-manager.svelte';
import { eventManager } from '$lib/managers/event-manager.svelte';
import { getAssetActions } from '$lib/services/asset.service';
- import { isFaceEditMode } from '$lib/stores/face-edit.svelte';
import { ocrManager } from '$lib/stores/ocr.svelte';
import { alwaysLoadOriginalVideo } from '$lib/stores/preferences.store';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
@@ -498,7 +497,7 @@
{/if}
- {#if $slideshowState === SlideshowState.None && showNavigation && !assetViewerManager.isShowEditor && !isFaceEditMode.value && previousAsset}
+ {#if $slideshowState === SlideshowState.None && showNavigation && !assetViewerManager.isShowEditor && !assetViewerManager.isFaceEditMode && previousAsset}
navigateAsset('previous')} />
@@ -571,7 +570,7 @@
{/if}
- {#if $slideshowState === SlideshowState.None && showNavigation && !assetViewerManager.isShowEditor && !isFaceEditMode.value && nextAsset}
+ {#if $slideshowState === SlideshowState.None && showNavigation && !assetViewerManager.isShowEditor && !assetViewerManager.isFaceEditMode && nextAsset}
navigateAsset('next')} />
diff --git a/web/src/lib/components/asset-viewer/detail-panel.svelte b/web/src/lib/components/asset-viewer/detail-panel.svelte
index e80d376f57..ba3ae559dc 100644
--- a/web/src/lib/components/asset-viewer/detail-panel.svelte
+++ b/web/src/lib/components/asset-viewer/detail-panel.svelte
@@ -10,7 +10,6 @@
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
import AssetChangeDateModal from '$lib/modals/AssetChangeDateModal.svelte';
import { Route } from '$lib/route';
- import { isFaceEditMode } from '$lib/stores/face-edit.svelte';
import { boundingBoxesArray } from '$lib/stores/people.store';
import { locale } from '$lib/stores/preferences.store';
import { preferences, user } from '$lib/stores/user.store';
@@ -208,7 +207,7 @@
shape="round"
color="secondary"
variant="ghost"
- onclick={() => (isFaceEditMode.value = !isFaceEditMode.value)}
+ onclick={() => assetViewerManager.toggleFaceEditMode()}
/>
{#if people.length > 0 || unassignedFaces.length > 0}
diff --git a/web/src/lib/components/asset-viewer/face-editor/face-editor.svelte b/web/src/lib/components/asset-viewer/face-editor/face-editor.svelte
index c5b4ab5ce7..ea2babfc11 100644
--- a/web/src/lib/components/asset-viewer/face-editor/face-editor.svelte
+++ b/web/src/lib/components/asset-viewer/face-editor/face-editor.svelte
@@ -2,7 +2,6 @@
import { shortcut } from '$lib/actions/shortcut';
import ImageThumbnail from '$lib/components/assets/thumbnail/image-thumbnail.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
- import { isFaceEditMode } from '$lib/stores/face-edit.svelte';
import { getPeopleThumbnailUrl } from '$lib/utils';
import { getNaturalSize, scaleToFit } from '$lib/utils/container-utils';
import { handleError } from '$lib/utils/handle-error';
@@ -10,7 +9,7 @@
import { Button, Input, modalManager, toastManager } from '@immich/ui';
import { Canvas, InteractiveFabricObject, Rect } from 'fabric';
import { clamp } from 'lodash-es';
- import { onMount, tick } from 'svelte';
+ import { onDestroy, onMount, tick } from 'svelte';
import { t } from 'svelte-i18n';
interface Props {
@@ -139,8 +138,8 @@
);
};
- const cancel = () => {
- isFaceEditMode.value = false;
+ const onClose = () => {
+ assetViewerManager.closeFaceEditMode();
};
const getPeople = async () => {
@@ -291,12 +290,16 @@
} catch (error) {
handleError(error, 'Error tagging face');
} finally {
- isFaceEditMode.value = false;
+ onClose();
}
};
+
+ onDestroy(() => {
+ onClose();
+ });
-
+
-
+
diff --git a/web/src/lib/components/asset-viewer/photo-viewer.svelte b/web/src/lib/components/asset-viewer/photo-viewer.svelte
index 4a6a02cb4a..a26b66b0b6 100644
--- a/web/src/lib/components/asset-viewer/photo-viewer.svelte
+++ b/web/src/lib/components/asset-viewer/photo-viewer.svelte
@@ -8,7 +8,6 @@
import AssetViewerEvents from '$lib/components/AssetViewerEvents.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { castManager } from '$lib/managers/cast-manager.svelte';
- import { isFaceEditMode } from '$lib/stores/face-edit.svelte';
import { ocrManager } from '$lib/stores/ocr.svelte';
import { boundingBoxesArray, type Faces } from '$lib/stores/people.store';
import { SlideshowLook, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
@@ -106,7 +105,7 @@
const onPlaySlideshow = () => ($slideshowState = SlideshowState.PlaySlideshow);
$effect(() => {
- if (isFaceEditMode.value && assetViewerManager.zoom > 1) {
+ if (assetViewerManager.isFaceEditMode && assetViewerManager.zoom > 1) {
onZoom();
}
});
@@ -166,7 +165,7 @@
const handleImageMouseMove = (event: MouseEvent) => {
$boundingBoxesArray = [];
- if (!assetViewerManager.imgRef || !element || isFaceEditMode.value || ocrManager.showOverlay) {
+ if (!assetViewerManager.imgRef || !element || assetViewerManager.isFaceEditMode || ocrManager.showOverlay) {
return;
}
@@ -215,7 +214,7 @@
ondblclick={onZoom}
onmousemove={handleImageMouseMove}
onmouseleave={handleImageMouseLeave}
- use:zoomImageAction={{ disabled: isFaceEditMode.value || ocrManager.showOverlay }}
+ use:zoomImageAction={{ disabled: assetViewerManager.isFaceEditMode || ocrManager.showOverlay }}
{...useSwipe((event) => onSwipe?.(event))}
>
- {#if isFaceEditMode.value && assetViewerManager.imgRef}
+ {#if assetViewerManager.isFaceEditMode && assetViewerManager.imgRef}
{/if}
diff --git a/web/src/lib/components/asset-viewer/video-native-viewer.svelte b/web/src/lib/components/asset-viewer/video-native-viewer.svelte
index e53414be07..915d5ceb58 100644
--- a/web/src/lib/components/asset-viewer/video-native-viewer.svelte
+++ b/web/src/lib/components/asset-viewer/video-native-viewer.svelte
@@ -3,7 +3,7 @@
import VideoRemoteViewer from '$lib/components/asset-viewer/video-remote-viewer.svelte';
import { assetViewerFadeDuration } from '$lib/constants';
import { castManager } from '$lib/managers/cast-manager.svelte';
- import { isFaceEditMode } from '$lib/stores/face-edit.svelte';
+ import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import {
autoPlayVideo,
loopVideo as loopVideoPreference,
@@ -115,7 +115,7 @@
let containerHeight = $state(0);
$effect(() => {
- if (isFaceEditMode.value) {
+ if (assetViewerManager.isFaceEditMode) {
videoPlayer?.pause();
}
});
@@ -172,7 +172,7 @@
{/if}
- {#if isFaceEditMode.value}
+ {#if assetViewerManager.isFaceEditMode}
{/if}
{/if}
diff --git a/web/src/lib/managers/asset-viewer-manager.svelte.ts b/web/src/lib/managers/asset-viewer-manager.svelte.ts
index f46be6b698..157ed31243 100644
--- a/web/src/lib/managers/asset-viewer-manager.svelte.ts
+++ b/web/src/lib/managers/asset-viewer-manager.svelte.ts
@@ -42,7 +42,7 @@ class AssetViewerManager extends BaseEventManager {
isShowActivityPanel = $state(false);
isPlayingMotionPhoto = $state(false);
isShowEditor = $state(false);
-
+ #isFaceEditMode = $state(false);
#viewingAssetStoreState = $state();
#viewState = $state(false);
gridScrollTarget = $state();
@@ -63,6 +63,10 @@ class AssetViewerManager extends BaseEventManager {
return isShowDetailPanel.current;
}
+ get isFaceEditMode() {
+ return this.#isFaceEditMode;
+ }
+
get zoomState() {
return this.#zoomState;
}
@@ -161,6 +165,14 @@ class AssetViewerManager extends BaseEventManager {
this.isShowEditor = false;
}
+ toggleFaceEditMode() {
+ this.#isFaceEditMode = !this.#isFaceEditMode;
+ }
+
+ closeFaceEditMode() {
+ this.#isFaceEditMode = false;
+ }
+
setAsset(asset: AssetResponseDto) {
this.#viewingAssetStoreState = asset;
this.#viewState = true;
diff --git a/web/src/lib/services/asset.service.ts b/web/src/lib/services/asset.service.ts
index bc16b65577..d2d847fc15 100644
--- a/web/src/lib/services/asset.service.ts
+++ b/web/src/lib/services/asset.service.ts
@@ -5,7 +5,6 @@ import { eventManager } from '$lib/managers/event-manager.svelte';
import AssetAddToAlbumModal from '$lib/modals/AssetAddToAlbumModal.svelte';
import AssetTagModal from '$lib/modals/AssetTagModal.svelte';
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
-import { isFaceEditMode } from '$lib/stores/face-edit.svelte';
import { user as authUser, preferences } from '$lib/stores/user.store';
import type { AssetControlContext } from '$lib/types';
import { getAssetMediaUrl, getSharedLink, sleep } from '$lib/utils';
@@ -229,9 +228,7 @@ export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) =
icon: mdiFaceRecognition,
type: $t('assets'),
$if: () => isOwner && asset.type === AssetTypeEnum.Image && !asset.isTrashed,
- onAction: () => {
- isFaceEditMode.value = !isFaceEditMode.value;
- },
+ onAction: () => assetViewerManager.toggleFaceEditMode(),
shortcuts: { key: 'p' },
};
diff --git a/web/src/lib/stores/face-edit.svelte.ts b/web/src/lib/stores/face-edit.svelte.ts
deleted file mode 100644
index 0b2f436099..0000000000
--- a/web/src/lib/stores/face-edit.svelte.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const isFaceEditMode = $state({ value: false });
diff --git a/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte
index 21f51a8f49..462f8fa3b6 100644
--- a/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte
+++ b/web/src/routes/(user)/photos/[[assetId=id]]/+page.svelte
@@ -1,5 +1,4 @@