Handle bulk deletes

This commit is contained in:
pythongosssss
2026-01-09 16:19:52 +00:00
parent 2178cdc2dc
commit 0fb208aa05
3 changed files with 41 additions and 7 deletions

View File

@@ -116,10 +116,12 @@
:open-context-menu-id="openContextMenuId"
:selected-assets="getSelectedAssets(displayAssets)"
:has-selection="hasSelection"
:is-deleting="deletingAssetIds.has(item.id)"
@click="handleAssetSelect(item)"
@zoom="handleZoomClick(item)"
@output-count-click="enterFolderView(item)"
@asset-deleted="refreshAssets"
@asset-deleting="handleAssetDeleting(item.id, $event)"
@context-menu-opened="openContextMenuId = item.id"
@bulk-download="handleBulkDownload"
@bulk-delete="handleBulkDelete"
@@ -239,6 +241,9 @@ const isQueuePanelV2Enabled = computed(() =>
// Track which asset's context menu is open (for single-instance context menu management)
const openContextMenuId = ref<string | null>(null)
// Track which assets are currently being deleted (for showing loading state)
const deletingAssetIds = ref(new Set<string>())
// Determine if delete button should be shown
// Hide delete button when in input tab and not in cloud (OSS mode - files are from local folders)
const shouldShowDeleteButton = computed(() => {
@@ -531,9 +536,21 @@ const handleDownloadSelected = () => {
clearSelection()
}
const setAssetsDeletingState = (assetIds: string[], isDeleting: boolean) => {
assetIds.forEach((id) =>
isDeleting
? deletingAssetIds.value.add(id)
: deletingAssetIds.value.delete(id)
)
}
const handleDeleteSelected = async () => {
const selectedAssets = getSelectedAssets(displayAssets.value)
await deleteMultipleAssets(selectedAssets)
const assetIds = selectedAssets.map((a) => a.id)
await deleteMultipleAssets(selectedAssets, (isDeleting) =>
setAssetsDeletingState(assetIds, isDeleting)
)
clearSelection()
}
@@ -542,8 +559,16 @@ const handleBulkDownload = (assets: AssetItem[]) => {
clearSelection()
}
const handleAssetDeleting = (assetId: string, isDeleting: boolean) => {
setAssetsDeletingState([assetId], isDeleting)
}
const handleBulkDelete = async (assets: AssetItem[]) => {
await deleteMultipleAssets(assets)
const assetIds = assets.map((a) => a.id)
await deleteMultipleAssets(assets, (isDeleting) =>
setAssetsDeletingState(assetIds, isDeleting)
)
clearSelection()
}

View File

@@ -143,7 +143,7 @@
:is-bulk-mode="hasSelection && (selectedAssets?.length ?? 0) > 1"
@zoom="handleZoomClick"
@asset-deleted="emit('asset-deleted')"
@asset-deleting="isDeleting = $event"
@asset-deleting="emit('asset-deleting', $event)"
@bulk-download="emit('bulk-download', $event)"
@bulk-delete="emit('bulk-delete', $event)"
/>
@@ -193,7 +193,8 @@ const {
showDeleteButton,
openContextMenuId,
selectedAssets,
hasSelection
hasSelection,
isDeleting
} = defineProps<{
asset?: AssetItem
loading?: boolean
@@ -204,6 +205,7 @@ const {
openContextMenuId?: string | null
selectedAssets?: AssetItem[]
hasSelection?: boolean
isDeleting?: boolean
}>()
const emit = defineEmits<{
@@ -211,6 +213,7 @@ const emit = defineEmits<{
zoom: [asset: AssetItem]
'output-count-click': []
'asset-deleted': []
'asset-deleting': [isDeleting: boolean]
'context-menu-opened': []
'bulk-download': [assets: AssetItem[]]
'bulk-delete': [assets: AssetItem[]]
@@ -221,7 +224,6 @@ const contextMenu = ref<InstanceType<typeof MediaAssetContextMenu>>()
const isVideoPlaying = ref(false)
const showVideoControls = ref(false)
const isDeleting = ref(false)
// Store actual image dimensions
const imageDimensions = ref<{ width: number; height: number } | undefined>()
@@ -296,7 +298,7 @@ const metaInfo = computed(() => {
})
const showActionsOverlay = computed(() => {
if (loading || !asset || isDeleting.value) return false
if (loading || !asset || isDeleting) return false
return isHovered.value || selected || isVideoPlaying.value
})

View File

@@ -376,8 +376,12 @@ export function useMediaAssetActions() {
/**
* Delete multiple assets with confirmation dialog
* @param assets Array of assets to delete
* @param onDeleting Optional callback called with true when deletion starts (after confirmation) and false when complete
*/
const deleteMultipleAssets = async (assets: AssetItem[]) => {
const deleteMultipleAssets = async (
assets: AssetItem[],
onDeleting?: (deleting: boolean) => void
) => {
if (!assets || assets.length === 0) return
const assetsStore = useAssetsStore()
@@ -394,6 +398,7 @@ export function useMediaAssetActions() {
type: 'delete',
itemList: assets.map((asset) => asset.name),
onConfirm: async () => {
onDeleting?.(true)
try {
// Delete all assets using Promise.allSettled to track individual results
const results = await Promise.allSettled(
@@ -470,6 +475,8 @@ export function useMediaAssetActions() {
detail: t('mediaAsset.selection.failedToDeleteAssets'),
life: 3000
})
} finally {
onDeleting?.(false)
}
resolve()