fix(web): refresh people after setting person thumbnail (#31744)
This commit is contained in:
@@ -177,6 +177,14 @@
|
||||
}
|
||||
};
|
||||
|
||||
const onPersonThumbnailReady = async ({ id: personId }: { id: string }) => {
|
||||
if (person && person.id !== personId) {
|
||||
return;
|
||||
}
|
||||
faceManager.clear();
|
||||
await faceManager.getAssetFaces(asset.id);
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
syncAssetViewerOpenClass(true);
|
||||
const slideshowStateUnsubscribe = slideshowState.subscribe((value) => {
|
||||
@@ -345,19 +353,13 @@
|
||||
preAction?.(action);
|
||||
};
|
||||
|
||||
const handleAction = async (action: Action) => {
|
||||
const handleAction = (action: Action) => {
|
||||
switch (action.type) {
|
||||
case AssetAction.DELETE:
|
||||
case AssetAction.TRASH: {
|
||||
eventManager.emit('AssetsDelete', [asset.id]);
|
||||
break;
|
||||
}
|
||||
case AssetAction.SET_PERSON_FEATURED_PHOTO: {
|
||||
const assetInfo = await getAssetInfo({ id: asset.id });
|
||||
cursor.current = { ...asset, people: assetInfo.people };
|
||||
eventManager.emit('AssetUpdate', cursor.current);
|
||||
break;
|
||||
}
|
||||
case AssetAction.RATING: {
|
||||
cursor.current = {
|
||||
...asset,
|
||||
@@ -490,7 +492,14 @@
|
||||
</script>
|
||||
|
||||
<CommandPaletteDefaultProvider name={$t('assets')} actions={[Tag, TagPeople]} />
|
||||
<OnEvents {onAssetUpdate} {onAssetsUndoArchive} {onStackCreate} onStackDelete={() => closeViewer()} {onStackUpdate} />
|
||||
<OnEvents
|
||||
{onAssetUpdate}
|
||||
{onAssetsUndoArchive}
|
||||
{onStackCreate}
|
||||
onStackDelete={() => closeViewer()}
|
||||
{onStackUpdate}
|
||||
{onPersonThumbnailReady}
|
||||
/>
|
||||
|
||||
<svelte:document
|
||||
bind:fullscreenElement
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
import DeleteAction from '$lib/components/asset-viewer/actions/DeleteAction.svelte';
|
||||
import RatingAction from '$lib/components/asset-viewer/actions/RatingAction.svelte';
|
||||
import RestoreAction from '$lib/components/asset-viewer/actions/RestoreAction.svelte';
|
||||
import SetFeaturedPhotoAction from '$lib/components/asset-viewer/actions/SetPersonFeaturedAction.svelte';
|
||||
import SetVisibilityAction from '$lib/components/asset-viewer/actions/SetVisibilityAction.svelte';
|
||||
import LoadingDots from '$lib/components/LoadingDots.svelte';
|
||||
import ButtonContextMenu from '$lib/components/shared-components/context-menu/ButtonContextMenu.svelte';
|
||||
@@ -15,6 +14,7 @@
|
||||
import { getAlbumAssetActions } from '$lib/services/album.service';
|
||||
import { getGlobalActions } from '$lib/services/app.service';
|
||||
import { getAssetActions } from '$lib/services/asset.service';
|
||||
import { getPersonAssetActions } from '$lib/services/person.service';
|
||||
import { getStackActions } from '$lib/services/stack.service';
|
||||
import { getSharedLink, withoutIcons } from '$lib/utils';
|
||||
import type { OnUndoDelete } from '$lib/utils/actions';
|
||||
@@ -152,7 +152,8 @@
|
||||
<ActionMenuItem action={SetCover} />
|
||||
{/if}
|
||||
{#if person}
|
||||
<SetFeaturedPhotoAction {asset} {person} {onAction} />
|
||||
{@const { SetFeaturedPhoto } = getPersonAssetActions($t, person, asset)}
|
||||
<ActionMenuItem action={SetFeaturedPhoto} />
|
||||
{/if}
|
||||
|
||||
<ActionMenuItem action={Actions.SetProfilePicture} />
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { OnAction } from '$lib/components/asset-viewer/actions/action';
|
||||
import MenuOption from '$lib/components/shared-components/context-menu/MenuOption.svelte';
|
||||
import { AssetAction } from '$lib/constants';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { updatePerson, type AssetResponseDto, type PersonResponseDto } from '@immich/sdk';
|
||||
import { toastManager } from '@immich/ui';
|
||||
import { mdiFaceManProfile } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
interface Props {
|
||||
asset: AssetResponseDto;
|
||||
person: PersonResponseDto;
|
||||
onAction?: OnAction;
|
||||
}
|
||||
|
||||
let { asset, person, onAction }: Props = $props();
|
||||
|
||||
const handleSelectFeaturePhoto = async () => {
|
||||
try {
|
||||
const updatedPerson = await updatePerson({
|
||||
id: person.id,
|
||||
personUpdateDto: { featureFaceAssetId: asset.id },
|
||||
});
|
||||
|
||||
person = { ...person, ...updatedPerson };
|
||||
|
||||
onAction?.({
|
||||
type: AssetAction.SET_PERSON_FEATURED_PHOTO,
|
||||
asset,
|
||||
person,
|
||||
});
|
||||
|
||||
toastManager.primary($t('feature_photo_updated'));
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_set_feature_photo'));
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<MenuOption text={$t('set_as_featured_photo')} icon={mdiFaceManProfile} onClick={handleSelectFeaturePhoto} />
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { AssetResponseDto, PersonResponseDto } from '@immich/sdk';
|
||||
import type { AssetAction } from '$lib/constants';
|
||||
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||
|
||||
@@ -10,7 +9,6 @@ type ActionMap = {
|
||||
[AssetAction.RESTORE]: { asset: TimelineAsset };
|
||||
[AssetAction.SET_VISIBILITY_LOCKED]: { asset: TimelineAsset };
|
||||
[AssetAction.SET_VISIBILITY_TIMELINE]: { asset: TimelineAsset };
|
||||
[AssetAction.SET_PERSON_FEATURED_PHOTO]: { asset: AssetResponseDto; person: PersonResponseDto };
|
||||
[AssetAction.RATING]: { asset: TimelineAsset; rating: number | null };
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ export enum AssetAction {
|
||||
RESTORE = 'restore',
|
||||
SET_VISIBILITY_LOCKED = 'set-visibility-locked',
|
||||
SET_VISIBILITY_TIMELINE = 'set-visibility-timeline',
|
||||
SET_PERSON_FEATURED_PHOTO = 'set-person-featured-photo',
|
||||
RATING = 'rating',
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { updatePerson, type PersonResponseDto } from '@immich/sdk';
|
||||
import { updatePerson, type AssetResponseDto, type PersonResponseDto } from '@immich/sdk';
|
||||
import { modalManager, toastManager, type ActionItem } from '@immich/ui';
|
||||
import {
|
||||
mdiCalendarEditOutline,
|
||||
mdiEyeOffOutline,
|
||||
mdiEyeOutline,
|
||||
mdiFaceManProfile,
|
||||
mdiHeartMinusOutline,
|
||||
mdiHeartOutline,
|
||||
} from '@mdi/js';
|
||||
@@ -51,6 +52,16 @@ export const getPersonActions = ($t: MessageFormatter, person: PersonResponseDto
|
||||
return { SetDateOfBirth, Favorite, Unfavorite, HidePerson, ShowPerson };
|
||||
};
|
||||
|
||||
export const getPersonAssetActions = ($t: MessageFormatter, person: PersonResponseDto, asset: AssetResponseDto) => {
|
||||
const SetFeaturedPhoto: ActionItem = {
|
||||
title: $t('set_as_featured_photo'),
|
||||
icon: mdiFaceManProfile,
|
||||
onAction: () => handleSetFeaturedPhoto(person, asset.id),
|
||||
};
|
||||
|
||||
return { SetFeaturedPhoto };
|
||||
};
|
||||
|
||||
const handleFavoritePerson = async (person: { id: string }) => {
|
||||
const $t = await getFormatter();
|
||||
|
||||
@@ -111,3 +122,15 @@ export const handleUpdatePersonBirthDate = async (person: PersonResponseDto, bir
|
||||
handleError(error, $t('errors.unable_to_save_date_of_birth'));
|
||||
}
|
||||
};
|
||||
|
||||
const handleSetFeaturedPhoto = async (person: PersonResponseDto, featureFaceAssetId: string) => {
|
||||
const $t = await getFormatter();
|
||||
|
||||
try {
|
||||
const response = await updatePerson({ id: person.id, personUpdateDto: { featureFaceAssetId } });
|
||||
toastManager.primary($t('feature_photo_updated'));
|
||||
eventManager.emit('PersonUpdate', response);
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_set_feature_photo'));
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user