mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
fix(web): close edit faces panel on Escape key press (#27519)
Move `showEditFaces` state to `assetViewerManager` so the edit faces panel open/close state is globally accessible. Add Escape key handling to `PersonSidePanel` that closes the assign-face sub-panel first, then the edit faces panel. Guard the asset viewer's global Escape-to-close action so it doesn't fire while either face panel is open. Change-Id: I0c947fe0758aef0eac473f4cc72f6a3b6a6a6964
This commit is contained in:
@@ -91,7 +91,7 @@
|
|||||||
const Close: ActionItem = $derived({
|
const Close: ActionItem = $derived({
|
||||||
title: $t('go_back'),
|
title: $t('go_back'),
|
||||||
icon: languageManager.rtl ? mdiArrowRight : mdiArrowLeft,
|
icon: languageManager.rtl ? mdiArrowRight : mdiArrowLeft,
|
||||||
$if: () => !!onClose && !assetViewerManager.isFaceEditMode,
|
$if: () => !!onClose && !assetViewerManager.isFaceEditMode && !assetViewerManager.isEditFacesPanelOpen,
|
||||||
onAction: () => onClose?.(),
|
onAction: () => onClose?.(),
|
||||||
shortcuts: [{ key: 'Escape' }],
|
shortcuts: [{ key: 'Escape' }],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -173,7 +173,7 @@
|
|||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
activityManager.reset();
|
activityManager.reset();
|
||||||
assetViewerManager.closeEditor();
|
assetViewerManager.resetPanelState();
|
||||||
syncAssetViewerOpenClass(false);
|
syncAssetViewerOpenClass(false);
|
||||||
preloadManager.destroy();
|
preloadManager.destroy();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
let { asset, currentAlbum = null }: Props = $props();
|
let { asset, currentAlbum = null }: Props = $props();
|
||||||
|
|
||||||
let showEditFaces = $state(false);
|
let showEditFaces = $derived(assetViewerManager.isEditFacesPanelOpen);
|
||||||
let isOwner = $derived(authManager.authenticated && authManager.user.id === asset.ownerId);
|
let isOwner = $derived(authManager.authenticated && authManager.user.id === asset.ownerId);
|
||||||
let people = $derived(asset.people || []);
|
let people = $derived(asset.people || []);
|
||||||
let unassignedFaces = $derived(asset.unassignedFaces || []);
|
let unassignedFaces = $derived(asset.unassignedFaces || []);
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
showEditFaces = false;
|
assetViewerManager.closeEditFacesPanel();
|
||||||
previousId = asset.id;
|
previousId = asset.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
|
|
||||||
const handleRefreshPeople = async () => {
|
const handleRefreshPeople = async () => {
|
||||||
asset = await getAssetInfo({ id: asset.id });
|
asset = await getAssetInfo({ id: asset.id });
|
||||||
showEditFaces = false;
|
assetViewerManager.closeEditFacesPanel();
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAssetFolderHref = (asset: AssetResponseDto) => {
|
const getAssetFolderHref = (asset: AssetResponseDto) => {
|
||||||
@@ -214,7 +214,7 @@
|
|||||||
shape="round"
|
shape="round"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
onclick={() => (showEditFaces = true)}
|
onclick={() => assetViewerManager.openEditFacesPanel()}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@@ -572,7 +572,7 @@
|
|||||||
<PersonSidePanel
|
<PersonSidePanel
|
||||||
assetId={asset.id}
|
assetId={asset.id}
|
||||||
assetType={asset.type}
|
assetType={asset.type}
|
||||||
onClose={() => (showEditFaces = false)}
|
onClose={() => assetViewerManager.closeEditFacesPanel()}
|
||||||
onRefresh={handleRefreshPeople}
|
onRefresh={handleRefreshPeople}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { shortcut } from '$lib/actions/shortcut';
|
||||||
import OnEvents from '$lib/components/OnEvents.svelte';
|
import OnEvents from '$lib/components/OnEvents.svelte';
|
||||||
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||||
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
|
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
|
||||||
@@ -187,6 +188,19 @@
|
|||||||
|
|
||||||
<OnEvents {onPersonThumbnailReady} />
|
<OnEvents {onPersonThumbnailReady} />
|
||||||
|
|
||||||
|
<svelte:document
|
||||||
|
use:shortcut={{
|
||||||
|
shortcut: { key: 'Escape' },
|
||||||
|
onShortcut: () => {
|
||||||
|
if (showSelectedFaces) {
|
||||||
|
showSelectedFaces = false;
|
||||||
|
} else {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<section
|
<section
|
||||||
transition:fly={{ x: 360, duration: 100, easing: linear }}
|
transition:fly={{ x: 360, duration: 100, easing: linear }}
|
||||||
class="absolute top-0 h-full w-90 overflow-x-hidden p-2 dark:text-immich-dark-fg bg-light"
|
class="absolute top-0 h-full w-90 overflow-x-hidden p-2 dark:text-immich-dark-fg bg-light"
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class AssetViewerManager extends BaseEventManager<Events> {
|
|||||||
isPlayingMotionPhoto = $state(false);
|
isPlayingMotionPhoto = $state(false);
|
||||||
isShowEditor = $state(false);
|
isShowEditor = $state(false);
|
||||||
#isFaceEditMode = $state(false);
|
#isFaceEditMode = $state(false);
|
||||||
|
#isEditFacesPanelOpen = $state(false);
|
||||||
#viewingAssetStoreState = $state<AssetResponseDto>();
|
#viewingAssetStoreState = $state<AssetResponseDto>();
|
||||||
#viewState = $state<boolean>(false);
|
#viewState = $state<boolean>(false);
|
||||||
gridScrollTarget = $state<AssetGridRouteSearchParams | null | undefined>();
|
gridScrollTarget = $state<AssetGridRouteSearchParams | null | undefined>();
|
||||||
@@ -72,6 +73,10 @@ class AssetViewerManager extends BaseEventManager<Events> {
|
|||||||
return this.#isFaceEditMode;
|
return this.#isFaceEditMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isEditFacesPanelOpen() {
|
||||||
|
return this.#isEditFacesPanelOpen;
|
||||||
|
}
|
||||||
|
|
||||||
get zoomState() {
|
get zoomState() {
|
||||||
return this.#zoomState;
|
return this.#zoomState;
|
||||||
}
|
}
|
||||||
@@ -186,6 +191,20 @@ class AssetViewerManager extends BaseEventManager<Events> {
|
|||||||
this.#isFaceEditMode = false;
|
this.#isFaceEditMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openEditFacesPanel() {
|
||||||
|
this.#isEditFacesPanelOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeEditFacesPanel() {
|
||||||
|
this.#isEditFacesPanelOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPanelState() {
|
||||||
|
this.closeEditor();
|
||||||
|
this.closeFaceEditMode();
|
||||||
|
this.closeEditFacesPanel();
|
||||||
|
}
|
||||||
|
|
||||||
setAsset(asset: AssetResponseDto) {
|
setAsset(asset: AssetResponseDto) {
|
||||||
this.#viewingAssetStoreState = asset;
|
this.#viewingAssetStoreState = asset;
|
||||||
this.#viewState = true;
|
this.#viewState = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user