mirror of
https://github.com/immich-app/immich.git
synced 2026-02-04 08:49:01 +03:00
refactor: delete confirm modal (#25135)
This commit is contained in:
@@ -7,6 +7,13 @@ import DeleteAction from './delete-action.svelte';
|
||||
let asset: AssetResponseDto;
|
||||
|
||||
describe('DeleteAction component', () => {
|
||||
beforeEach(() => {
|
||||
vi.mock(import('$lib/managers/feature-flags-manager.svelte'), () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return { featureFlagsManager: { init: vi.fn(), loadFeatureFlags: vi.fn(), value: { trash: true } } as any };
|
||||
});
|
||||
});
|
||||
|
||||
describe('given an asset which is not trashed yet', () => {
|
||||
beforeEach(() => {
|
||||
asset = assetFactory.build({ isTrashed: false });
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { shortcuts } from '$lib/actions/shortcut';
|
||||
import DeleteAssetDialog from '$lib/components/photos-page/delete-asset-dialog.svelte';
|
||||
import { AssetAction } from '$lib/constants';
|
||||
import Portal from '$lib/elements/Portal.svelte';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import AssetDeleteConfirmModal from '$lib/modals/AssetDeleteConfirmModal.svelte';
|
||||
import { showDeleteModal } from '$lib/stores/preferences.store';
|
||||
import { deleteAssets as deleteAssetsUtil, type OnUndoDelete } from '$lib/utils/actions';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { toTimelineAsset } from '$lib/utils/timeline-util';
|
||||
import { deleteAssets, type AssetResponseDto } from '@immich/sdk';
|
||||
import { IconButton, toastManager } from '@immich/ui';
|
||||
import { IconButton, modalManager, toastManager } from '@immich/ui';
|
||||
import { mdiDeleteForeverOutline, mdiDeleteOutline } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { OnAction, PreAction } from './action';
|
||||
@@ -23,24 +22,32 @@
|
||||
|
||||
let { asset, onAction, preAction, onUndoDelete = undefined }: Props = $props();
|
||||
|
||||
let showConfirmModal = $state(false);
|
||||
const forceDefault = $derived(asset.isTrashed || !featureFlagsManager.value.trash);
|
||||
|
||||
const trashOrDelete = async (force = false) => {
|
||||
if (force || !featureFlagsManager.value.trash) {
|
||||
const trashOrDelete = async (forceRequest?: boolean) => {
|
||||
const timelineAsset = toTimelineAsset(asset);
|
||||
const force = forceDefault || forceRequest;
|
||||
|
||||
if (force) {
|
||||
if ($showDeleteModal) {
|
||||
showConfirmModal = true;
|
||||
return;
|
||||
const confirmed = await modalManager.show(AssetDeleteConfirmModal, { size: 1 });
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
await deleteAsset();
|
||||
|
||||
try {
|
||||
preAction({ type: AssetAction.DELETE, asset: timelineAsset });
|
||||
await deleteAssets({ assetBulkDeleteDto: { ids: [asset.id], force: true } });
|
||||
onAction({ type: AssetAction.DELETE, asset: timelineAsset });
|
||||
toastManager.success($t('permanently_deleted_asset'));
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_delete_asset'));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
await trashAsset();
|
||||
return;
|
||||
};
|
||||
|
||||
const trashAsset = async () => {
|
||||
const timelineAsset = toTimelineAsset(asset);
|
||||
preAction({ type: AssetAction.TRASH, asset: timelineAsset });
|
||||
await deleteAssetsUtil(
|
||||
false,
|
||||
@@ -49,24 +56,11 @@
|
||||
onUndoDelete,
|
||||
);
|
||||
};
|
||||
|
||||
const deleteAsset = async () => {
|
||||
try {
|
||||
preAction({ type: AssetAction.DELETE, asset: toTimelineAsset(asset) });
|
||||
await deleteAssets({ assetBulkDeleteDto: { ids: [asset.id], force: true } });
|
||||
onAction({ type: AssetAction.DELETE, asset: toTimelineAsset(asset) });
|
||||
toastManager.success($t('permanently_deleted_asset'));
|
||||
} catch (error) {
|
||||
handleError(error, $t('errors.unable_to_delete_asset'));
|
||||
} finally {
|
||||
showConfirmModal = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:document
|
||||
use:shortcuts={[
|
||||
{ shortcut: { key: 'Delete' }, onShortcut: () => trashOrDelete(asset.isTrashed) },
|
||||
{ shortcut: { key: 'Delete' }, onShortcut: () => trashOrDelete() },
|
||||
{ shortcut: { key: 'Delete', shift: true }, onShortcut: () => trashOrDelete(true) },
|
||||
]}
|
||||
/>
|
||||
@@ -75,13 +69,7 @@
|
||||
color="secondary"
|
||||
shape="round"
|
||||
variant="ghost"
|
||||
icon={asset.isTrashed ? mdiDeleteForeverOutline : mdiDeleteOutline}
|
||||
aria-label={asset.isTrashed ? $t('permanently_delete') : $t('delete')}
|
||||
onclick={() => trashOrDelete(asset.isTrashed)}
|
||||
icon={forceDefault ? mdiDeleteForeverOutline : mdiDeleteOutline}
|
||||
aria-label={forceDefault ? $t('permanently_delete') : $t('delete')}
|
||||
onclick={() => trashOrDelete()}
|
||||
/>
|
||||
|
||||
{#if showConfirmModal}
|
||||
<Portal target="body">
|
||||
<DeleteAssetDialog size={1} onCancel={() => (showConfirmModal = false)} onConfirm={deleteAsset} />
|
||||
</Portal>
|
||||
{/if}
|
||||
|
||||
@@ -32,8 +32,14 @@ describe('AssetViewerNavBar component', () => {
|
||||
vi.fn(() => ({ observe: vi.fn(), unobserve: vi.fn(), disconnect: vi.fn() })),
|
||||
);
|
||||
vi.mock(import('$lib/managers/feature-flags-manager.svelte'), () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return { featureFlagsManager: { init: vi.fn(), loadFeatureFlags: vi.fn(), value: { smartSearch: true } } as any };
|
||||
return {
|
||||
featureFlagsManager: {
|
||||
init: vi.fn(),
|
||||
loadFeatureFlags: vi.fn(),
|
||||
value: { trash: true, smartSearch: true },
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} as any,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import Portal from '$lib/elements/Portal.svelte';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import type { TimelineAsset, Viewport } from '$lib/managers/timeline-manager/types';
|
||||
import AssetDeleteConfirmModal from '$lib/modals/AssetDeleteConfirmModal.svelte';
|
||||
import ShortcutsModal from '$lib/modals/ShortcutsModal.svelte';
|
||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||
@@ -23,9 +24,8 @@
|
||||
import { modalManager } from '@immich/ui';
|
||||
import { debounce } from 'lodash-es';
|
||||
import { t } from 'svelte-i18n';
|
||||
import DeleteAssetDialog from '../../photos-page/delete-asset-dialog.svelte';
|
||||
|
||||
interface Props {
|
||||
type Props = {
|
||||
initialAssetId?: string;
|
||||
assets: AssetResponseDto[];
|
||||
assetInteraction: AssetInteraction;
|
||||
@@ -34,7 +34,6 @@
|
||||
viewport: Viewport;
|
||||
onIntersected?: (() => void) | undefined;
|
||||
showAssetName?: boolean;
|
||||
isShowDeleteConfirmation?: boolean;
|
||||
onPrevious?: (() => Promise<{ id: string } | undefined>) | undefined;
|
||||
onNext?: (() => Promise<{ id: string } | undefined>) | undefined;
|
||||
onRandom?: (() => Promise<{ id: string } | undefined>) | undefined;
|
||||
@@ -42,7 +41,7 @@
|
||||
pageHeaderOffset?: number;
|
||||
slidingWindowOffset?: number;
|
||||
arrowNavigation?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
let {
|
||||
initialAssetId = undefined,
|
||||
@@ -53,7 +52,6 @@
|
||||
viewport,
|
||||
onIntersected = undefined,
|
||||
showAssetName = false,
|
||||
isShowDeleteConfirmation = $bindable(false),
|
||||
onPrevious = undefined,
|
||||
onNext = undefined,
|
||||
onRandom = undefined,
|
||||
@@ -209,30 +207,27 @@
|
||||
|
||||
const onDelete = () => {
|
||||
const hasTrashedAsset = assetInteraction.selectedAssets.some((asset) => asset.isTrashed);
|
||||
|
||||
if ($showDeleteModal && (!isTrashEnabled || hasTrashedAsset)) {
|
||||
isShowDeleteConfirmation = true;
|
||||
return;
|
||||
}
|
||||
handlePromiseError(trashOrDelete(hasTrashedAsset));
|
||||
};
|
||||
|
||||
const onForceDelete = () => {
|
||||
if ($showDeleteModal) {
|
||||
isShowDeleteConfirmation = true;
|
||||
return;
|
||||
}
|
||||
handlePromiseError(trashOrDelete(true));
|
||||
};
|
||||
|
||||
const trashOrDelete = async (force: boolean = false) => {
|
||||
isShowDeleteConfirmation = false;
|
||||
const forceOrNoTrash = force || !featureFlagsManager.value.trash;
|
||||
const selectedAssets = assetInteraction.selectedAssets;
|
||||
|
||||
if ($showDeleteModal && forceOrNoTrash) {
|
||||
const confirmed = await modalManager.show(AssetDeleteConfirmModal, { size: selectedAssets.length });
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await deleteAssets(
|
||||
!(isTrashEnabled && !force),
|
||||
forceOrNoTrash,
|
||||
(assetIds) => (assets = assets.filter((asset) => !assetIds.includes(asset.id))),
|
||||
assetInteraction.selectedAssets,
|
||||
selectedAssets,
|
||||
onReload,
|
||||
);
|
||||
|
||||
assetInteraction.clearMultiselect();
|
||||
};
|
||||
|
||||
@@ -285,7 +280,7 @@
|
||||
shortcuts.push(
|
||||
{ shortcut: { key: 'Escape' }, onShortcut: deselectAllAssets },
|
||||
{ shortcut: { key: 'Delete' }, onShortcut: onDelete },
|
||||
{ shortcut: { key: 'Delete', shift: true }, onShortcut: onForceDelete },
|
||||
{ shortcut: { key: 'Delete', shift: true }, onShortcut: () => trashOrDelete(true) },
|
||||
{ shortcut: { key: 'D', ctrl: true }, onShortcut: () => deselectAllAssets() },
|
||||
{ shortcut: { key: 'a', shift: true }, onShortcut: toggleArchive },
|
||||
);
|
||||
@@ -405,8 +400,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
let isTrashEnabled = $derived(featureFlagsManager.value.trash);
|
||||
|
||||
$effect(() => {
|
||||
if (!lastAssetMouseEvent) {
|
||||
assetInteraction.clearAssetSelectionCandidates();
|
||||
@@ -440,14 +433,6 @@
|
||||
onscroll={() => updateSlidingWindow()}
|
||||
/>
|
||||
|
||||
{#if isShowDeleteConfirmation}
|
||||
<DeleteAssetDialog
|
||||
size={assetInteraction.selectedAssets.length}
|
||||
onCancel={() => (isShowDeleteConfirmation = false)}
|
||||
onConfirm={() => handlePromiseError(trashOrDelete(true))}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if assets.length > 0}
|
||||
<div
|
||||
style:position="relative"
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
album?: AlbumResponseDto;
|
||||
albumUsers?: UserResponseDto[];
|
||||
person?: PersonResponseDto;
|
||||
isShowDeleteConfirmation?: boolean;
|
||||
onSelect?: (asset: TimelineAsset) => void;
|
||||
onEscape?: () => void;
|
||||
children?: Snippet;
|
||||
@@ -79,7 +78,6 @@
|
||||
album,
|
||||
albumUsers = [],
|
||||
person,
|
||||
isShowDeleteConfirmation = $bindable(false),
|
||||
onSelect = () => {},
|
||||
onEscape = () => {},
|
||||
children,
|
||||
@@ -600,7 +598,6 @@
|
||||
scrollToAsset={(asset) => scrollToAsset(asset) ?? false}
|
||||
{timelineManager}
|
||||
{assetInteraction}
|
||||
bind:isShowDeleteConfirmation
|
||||
{onEscape}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,55 +1,48 @@
|
||||
<script lang="ts">
|
||||
import DeleteAssetDialog from '$lib/components/photos-page/delete-asset-dialog.svelte';
|
||||
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||
import { getAssetControlContext } from '$lib/components/timeline/AssetSelectControlBar.svelte';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import AssetDeleteConfirmModal from '$lib/modals/AssetDeleteConfirmModal.svelte';
|
||||
import { showDeleteModal } from '$lib/stores/preferences.store';
|
||||
import { type OnDelete, type OnUndoDelete, deleteAssets } from '$lib/utils/actions';
|
||||
import { IconButton } from '@immich/ui';
|
||||
import { IconButton, modalManager } from '@immich/ui';
|
||||
import { mdiDeleteForeverOutline, mdiDeleteOutline, mdiTimerSand } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import MenuOption from '../../shared-components/context-menu/menu-option.svelte';
|
||||
|
||||
interface Props {
|
||||
type Props = {
|
||||
onAssetDelete: OnDelete;
|
||||
onUndoDelete?: OnUndoDelete | undefined;
|
||||
menuItem?: boolean;
|
||||
force?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
let {
|
||||
onAssetDelete,
|
||||
onUndoDelete = undefined,
|
||||
menuItem = false,
|
||||
force = !featureFlagsManager.value.trash,
|
||||
}: Props = $props();
|
||||
let { onAssetDelete, onUndoDelete = undefined, menuItem = false, force: forceRequested }: Props = $props();
|
||||
|
||||
const force = $derived(forceRequested || !featureFlagsManager.value.trash);
|
||||
let label = $derived(force ? $t('permanently_delete') : $t('delete'));
|
||||
let loading = $state(false);
|
||||
|
||||
const { clearSelect, getOwnedAssets } = getAssetControlContext();
|
||||
|
||||
let isShowConfirmation = $state(false);
|
||||
let loading = $state(false);
|
||||
const onAction = async () => {
|
||||
const assets = getOwnedAssets();
|
||||
|
||||
let label = $derived(force ? $t('permanently_delete') : $t('delete'));
|
||||
|
||||
const handleTrash = async () => {
|
||||
if (force) {
|
||||
isShowConfirmation = true;
|
||||
return;
|
||||
if (force && $showDeleteModal) {
|
||||
const confirmed = await modalManager.show(AssetDeleteConfirmModal, { size: assets.length });
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await handleDelete();
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
loading = true;
|
||||
const assets = [...getOwnedAssets()];
|
||||
await deleteAssets(force, onAssetDelete, assets, onUndoDelete);
|
||||
clearSelect();
|
||||
isShowConfirmation = false;
|
||||
loading = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if menuItem}
|
||||
<MenuOption text={label} icon={mdiDeleteOutline} onClick={handleTrash} />
|
||||
<MenuOption text={label} icon={mdiDeleteOutline} onClick={onAction} />
|
||||
{:else if loading}
|
||||
<IconButton
|
||||
shape="round"
|
||||
@@ -66,14 +59,6 @@
|
||||
variant="ghost"
|
||||
aria-label={label}
|
||||
icon={mdiDeleteForeverOutline}
|
||||
onclick={handleTrash}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if isShowConfirmation}
|
||||
<DeleteAssetDialog
|
||||
size={getOwnedAssets().length}
|
||||
onConfirm={handleDelete}
|
||||
onCancel={() => (isShowConfirmation = false)}
|
||||
onclick={onAction}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { shortcuts, type ShortcutOptions } from '$lib/actions/shortcut';
|
||||
import DeleteAssetDialog from '$lib/components/photos-page/delete-asset-dialog.svelte';
|
||||
import {
|
||||
setFocusToAsset as setFocusAssetInit,
|
||||
setFocusTo as setFocusToInit,
|
||||
@@ -10,6 +9,7 @@
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||
import AssetDeleteConfirmModal from '$lib/modals/AssetDeleteConfirmModal.svelte';
|
||||
import NavigateToDateModal from '$lib/modals/NavigateToDateModal.svelte';
|
||||
import ShortcutsModal from '$lib/modals/ShortcutsModal.svelte';
|
||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||
@@ -22,53 +22,42 @@
|
||||
import { AssetVisibility } from '@immich/sdk';
|
||||
import { modalManager } from '@immich/ui';
|
||||
|
||||
interface Props {
|
||||
type Props = {
|
||||
timelineManager: TimelineManager;
|
||||
assetInteraction: AssetInteraction;
|
||||
isShowDeleteConfirmation: boolean;
|
||||
onEscape?: () => void;
|
||||
scrollToAsset: (asset: TimelineAsset) => boolean;
|
||||
}
|
||||
};
|
||||
|
||||
let {
|
||||
timelineManager = $bindable(),
|
||||
assetInteraction,
|
||||
isShowDeleteConfirmation = $bindable(false),
|
||||
onEscape,
|
||||
scrollToAsset,
|
||||
}: Props = $props();
|
||||
let { timelineManager = $bindable(), assetInteraction, onEscape, scrollToAsset }: Props = $props();
|
||||
|
||||
const { isViewing: showAssetViewer } = assetViewingStore;
|
||||
|
||||
const trashOrDelete = async (force: boolean = false) => {
|
||||
isShowDeleteConfirmation = false;
|
||||
const trashOrDelete = async (forceRequested?: boolean) => {
|
||||
const force = forceRequested || !featureFlagsManager.value.trash;
|
||||
const selectedAssets = assetInteraction.selectedAssets;
|
||||
|
||||
if ($showDeleteModal && force) {
|
||||
const confirmed = await modalManager.show(AssetDeleteConfirmModal, { size: selectedAssets.length });
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await deleteAssets(
|
||||
!(isTrashEnabled && !force),
|
||||
force,
|
||||
(assetIds) => timelineManager.removeAssets(assetIds),
|
||||
assetInteraction.selectedAssets,
|
||||
!isTrashEnabled || force ? undefined : (assets) => timelineManager.upsertAssets(assets),
|
||||
selectedAssets,
|
||||
force ? undefined : (assets) => timelineManager.upsertAssets(assets),
|
||||
);
|
||||
assetInteraction.clearMultiselect();
|
||||
};
|
||||
|
||||
const onDelete = () => {
|
||||
const hasTrashedAsset = assetInteraction.selectedAssets.some((asset) => asset.isTrashed);
|
||||
|
||||
if ($showDeleteModal && (!isTrashEnabled || hasTrashedAsset)) {
|
||||
isShowDeleteConfirmation = true;
|
||||
return;
|
||||
}
|
||||
handlePromiseError(trashOrDelete(hasTrashedAsset));
|
||||
};
|
||||
|
||||
const onForceDelete = () => {
|
||||
if ($showDeleteModal) {
|
||||
isShowDeleteConfirmation = true;
|
||||
return;
|
||||
}
|
||||
handlePromiseError(trashOrDelete(true));
|
||||
};
|
||||
|
||||
const onStackAssets = async () => {
|
||||
const result = await stackAssets(assetInteraction.selectedAssets);
|
||||
|
||||
@@ -118,9 +107,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
const isTrashEnabled = $derived(featureFlagsManager.value.trash);
|
||||
const isEmpty = $derived(timelineManager.isInitialized && timelineManager.months.length === 0);
|
||||
const idsSelectedAssets = $derived(assetInteraction.selectedAssets.map(({ id }) => id));
|
||||
let isShortcutModalOpen = false;
|
||||
|
||||
const handleOpenShortcutModal = async () => {
|
||||
@@ -176,7 +163,7 @@
|
||||
if (assetInteraction.selectionActive) {
|
||||
shortcuts.push(
|
||||
{ shortcut: { key: 'Delete' }, onShortcut: onDelete },
|
||||
{ shortcut: { key: 'Delete', shift: true }, onShortcut: onForceDelete },
|
||||
{ shortcut: { key: 'Delete', shift: true }, onShortcut: () => trashOrDelete(true) },
|
||||
{ shortcut: { key: 'D', ctrl: true }, onShortcut: () => deselectAllAssets() },
|
||||
{ shortcut: { key: 's' }, onShortcut: () => onStackAssets() },
|
||||
{ shortcut: { key: 'a', shift: true }, onShortcut: toggleArchive },
|
||||
@@ -189,11 +176,3 @@
|
||||
</script>
|
||||
|
||||
<svelte:document onkeydown={onKeyDown} onkeyup={onKeyUp} onselectstart={onSelectStart} use:shortcuts={shortcutList} />
|
||||
|
||||
{#if isShowDeleteConfirmation}
|
||||
<DeleteAssetDialog
|
||||
size={idsSelectedAssets.length}
|
||||
onCancel={() => (isShowDeleteConfirmation = false)}
|
||||
onConfirm={() => handlePromiseError(trashOrDelete(true))}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
import { mdiDeleteForeverOutline } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
interface Props {
|
||||
type Props = {
|
||||
size: number;
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
onClose: (confirmed?: boolean) => void;
|
||||
};
|
||||
|
||||
let { size, onConfirm, onCancel }: Props = $props();
|
||||
let { size, onClose: onCloseParent }: Props = $props();
|
||||
|
||||
let checked = $state(false);
|
||||
|
||||
const handleConfirm = () => {
|
||||
if (checked) {
|
||||
const onClose = (confirmed: boolean) => {
|
||||
if (confirmed && checked) {
|
||||
$showDeleteModal = false;
|
||||
}
|
||||
onConfirm();
|
||||
|
||||
onCloseParent(confirmed);
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
title={$t('permanently_delete_assets_count', { values: { count: size } })}
|
||||
confirmText={$t('delete')}
|
||||
icon={mdiDeleteForeverOutline}
|
||||
onClose={(confirmed) => (confirmed ? handleConfirm() : onCancel())}
|
||||
{onClose}
|
||||
>
|
||||
{#snippet promptSnippet()}
|
||||
<p>
|
||||
Reference in New Issue
Block a user