feat(web): Implement keep this delete others for asset stacks (#14217)

This commit is contained in:
Braydon Davis 2024-11-19 09:54:35 -07:00 committed by GitHub
parent bcd17c2ebe
commit 1737013e66
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 65 additions and 0 deletions

View file

@ -12,6 +12,7 @@ type ActionMap = {
[AssetAction.ADD]: { asset: AssetResponseDto };
[AssetAction.ADD_TO_ALBUM]: { asset: AssetResponseDto; album: AlbumResponseDto };
[AssetAction.UNSTACK]: { assets: AssetResponseDto[] };
[AssetAction.KEEP_THIS_DELETE_OTHERS]: { asset: AssetResponseDto };
};
export type Action = {

View file

@ -0,0 +1,33 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { AssetAction } from '$lib/constants';
import { keepThisDeleteOthers } from '$lib/utils/asset-utils';
import type { AssetResponseDto, StackResponseDto } from '@immich/sdk';
import { mdiPinOutline } from '@mdi/js';
import type { OnAction } from './action';
import { t } from 'svelte-i18n';
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
export let stack: StackResponseDto;
export let asset: AssetResponseDto;
export let onAction: OnAction;
const handleKeepThisDeleteOthers = async () => {
const isConfirmed = await dialogController.show({
title: $t('keep_this_delete_others'),
prompt: $t('confirm_keep_this_delete_others'),
confirmText: $t('delete_others'),
});
if (!isConfirmed) {
return;
}
const keptAsset = await keepThisDeleteOthers(asset, stack);
if (keptAsset) {
onAction({ type: AssetAction.UNSTACK, assets: [keptAsset] });
}
};
</script>
<MenuOption icon={mdiPinOutline} onClick={handleKeepThisDeleteOthers} text={$t('keep_this_delete_others')} />

View file

@ -13,6 +13,7 @@
import ShareAction from '$lib/components/asset-viewer/actions/share-action.svelte';
import ShowDetailAction from '$lib/components/asset-viewer/actions/show-detail-action.svelte';
import UnstackAction from '$lib/components/asset-viewer/actions/unstack-action.svelte';
import KeepThisDeleteOthersAction from '$lib/components/asset-viewer/actions/keep-this-delete-others.svelte';
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
@ -166,6 +167,7 @@
{#if isOwner}
{#if stack}
<UnstackAction {stack} {onAction} />
<KeepThisDeleteOthersAction {stack} {asset} {onAction} />
{/if}
{#if album}
<SetAlbumCoverAction {asset} {album} />

View file

@ -379,6 +379,7 @@
break;
}
case AssetAction.KEEP_THIS_DELETE_OTHERS:
case AssetAction.UNSTACK: {
closeViewer();
}

View file

@ -9,6 +9,7 @@ export enum AssetAction {
ADD = 'add',
ADD_TO_ALBUM = 'add-to-album',
UNSTACK = 'unstack',
KEEP_THIS_DELETE_OTHERS = 'keep-this-delete-others',
}
export enum AppRoute {

View file

@ -14,6 +14,7 @@ import { getFormatter } from '$lib/utils/i18n';
import {
addAssetsToAlbum as addAssets,
createStack,
deleteAssets,
deleteStacks,
getAssetInfo,
getBaseUrl,
@ -27,6 +28,7 @@ import {
type AssetResponseDto,
type AssetTypeEnum,
type DownloadInfoDto,
type StackResponseDto,
type UserPreferencesResponseDto,
type UserResponseDto,
} from '@immich/sdk';
@ -438,6 +440,26 @@ export const deleteStack = async (stackIds: string[]) => {
}
};
export const keepThisDeleteOthers = async (keepAsset: AssetResponseDto, stack: StackResponseDto) => {
const $t = get(t);
try {
const assetsToDeleteIds = stack.assets.filter((asset) => asset.id !== keepAsset.id).map((asset) => asset.id);
await deleteAssets({ assetBulkDeleteDto: { ids: assetsToDeleteIds } });
await deleteStacks({ bulkIdsDto: { ids: [stack.id] } });
notificationController.show({
type: NotificationType.Info,
message: $t('kept_this_deleted_others', { values: { count: assetsToDeleteIds.length } }),
});
keepAsset.stack = null;
return keepAsset;
} catch (error) {
handleError(error, $t('errors.failed_to_keep_this_delete_others'));
}
};
export const selectAllAssets = async (assetStore: AssetStore, assetInteractionStore: AssetInteractionStore) => {
if (get(isSelectingAllAssets)) {
// Selection is already ongoing