Mass-select grid and bulk delete for moderators

- Select mode in the filter row (upload.delete permission): tiles
  toggle selection in the capture phase, a floating action bar
  offers select-all and delete with confirmation popover
- New POST /api/uploads/bulk-delete endpoint (validated, deduped,
  max 200 ids) removing rows, files and attachment data
- upload-deleted broadcast on bulk and single delete; other clients
  refresh the grid and drop matching notifications
- Also: skeleton tile grid as loading state, dropzone logic moved
  to the layout-level GlobalDropZone, obsolete ytimg preconnect
  removed

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
2026-10-04 03:06:38 +02:00
co-authored by Devin
parent f57fffb414
commit de0cd6d34f
5 changed files with 188 additions and 61 deletions
+8 -1
View File
@@ -49,10 +49,17 @@ export function useNotifications() {
await $fetch(`/api/notifications/${id}/read`, { method: 'POST' })
}
function removeByUploads(uploadIds: string[]) {
const removed = notifications.value.filter(n => uploadIds.includes(n.uploadId))
if (!removed.length) return
notifications.value = notifications.value.filter(n => !uploadIds.includes(n.uploadId))
unreadCount.value = Math.max(0, unreadCount.value - removed.filter(n => !n.isRead).length)
}
function reset() {
notifications.value = []
unreadCount.value = 0
}
return { notifications, unreadCount, unreadUploadIds, fetchAll, addLive, markAllRead, markRead, reset }
return { notifications, unreadCount, unreadUploadIds, fetchAll, addLive, markAllRead, markRead, removeByUploads, reset }
}