mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-27 18:24:11 +00:00
feat: Add multi-select support for media assets (#6256)
## Summary
Implements file explorer-style multi-selection functionality for media
assets in the AssetsSidebarTab component.
## Changes
### Multi-Selection Interactions
- **Normal click**: Single selection (clears previous, selects new)
- **Shift + click**: Range selection (from last selected to current)
- **Ctrl/Cmd + click**: Toggle individual selection
### State Management
- Added `assetSelectionStore` to manage selected asset IDs using Set
- Created `useAssetSelection` composable for selection logic and
keyboard state
### UI Enhancements
- Display selection count in footer (output tab only)
- Interactive selection count that shows "Deselect all" on hover
- Added bulk action buttons for download/delete (UI only)
### Translation Keys
Added new keys under `mediaAsset.selection`:
- `selectedCount`: "{count} selected"
- `deselectAll`: "Deselect all"
- `downloadSelected`: "Download"
- `deleteSelected`: "Delete"
## Test Plan
- [x] Open Assets sidebar tab
- [x] Switch to Generated tab
- [x] Test single selection with normal click
- [x] Test range selection with Shift + click
- [x] Test toggle selection with Ctrl/Cmd + click
- [x] Verify selection count updates correctly
- [x] Test hover interaction on selection count
- [x] Click "Deselect all" to clear selection
- [x] Test bulk action buttons (UI only)
## Notes
- Bulk download/delete functionality to be implemented in separate PR
- Selection UI currently only shows in output (Generated) tab
[screen-capture.webm](https://github.com/user-attachments/assets/740315bd-9254-4af3-a0be-10846d810d65)
This commit is contained in:
81
src/platform/assets/composables/useAssetSelectionStore.ts
Normal file
81
src/platform/assets/composables/useAssetSelectionStore.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
export const useAssetSelectionStore = defineStore('assetSelection', () => {
|
||||
// State
|
||||
const selectedAssetIds = ref<Set<string>>(new Set())
|
||||
const lastSelectedIndex = ref<number>(-1)
|
||||
|
||||
// Getters
|
||||
const selectedCount = computed(() => selectedAssetIds.value.size)
|
||||
const hasSelection = computed(() => selectedAssetIds.value.size > 0)
|
||||
const selectedIdsArray = computed(() => Array.from(selectedAssetIds.value))
|
||||
|
||||
// Actions
|
||||
function addToSelection(assetId: string) {
|
||||
selectedAssetIds.value.add(assetId)
|
||||
}
|
||||
|
||||
function removeFromSelection(assetId: string) {
|
||||
selectedAssetIds.value.delete(assetId)
|
||||
}
|
||||
|
||||
function setSelection(assetIds: string[]) {
|
||||
// Only update if there's an actual change to prevent unnecessary re-renders
|
||||
const newSet = new Set(assetIds)
|
||||
if (
|
||||
newSet.size !== selectedAssetIds.value.size ||
|
||||
!assetIds.every((id) => selectedAssetIds.value.has(id))
|
||||
) {
|
||||
selectedAssetIds.value = newSet
|
||||
}
|
||||
}
|
||||
|
||||
function clearSelection() {
|
||||
selectedAssetIds.value.clear()
|
||||
lastSelectedIndex.value = -1
|
||||
}
|
||||
|
||||
function toggleSelection(assetId: string) {
|
||||
if (isSelected(assetId)) {
|
||||
removeFromSelection(assetId)
|
||||
} else {
|
||||
addToSelection(assetId)
|
||||
}
|
||||
}
|
||||
|
||||
function isSelected(assetId: string): boolean {
|
||||
return selectedAssetIds.value.has(assetId)
|
||||
}
|
||||
|
||||
function setLastSelectedIndex(index: number) {
|
||||
lastSelectedIndex.value = index
|
||||
}
|
||||
|
||||
// Reset function for cleanup
|
||||
function reset() {
|
||||
selectedAssetIds.value.clear()
|
||||
lastSelectedIndex.value = -1
|
||||
}
|
||||
|
||||
return {
|
||||
// State
|
||||
selectedAssetIds: computed(() => selectedAssetIds.value),
|
||||
lastSelectedIndex: computed(() => lastSelectedIndex.value),
|
||||
|
||||
// Getters
|
||||
selectedCount,
|
||||
hasSelection,
|
||||
selectedIdsArray,
|
||||
|
||||
// Actions
|
||||
addToSelection,
|
||||
removeFromSelection,
|
||||
setSelection,
|
||||
clearSelection,
|
||||
toggleSelection,
|
||||
isSelected,
|
||||
setLastSelectedIndex,
|
||||
reset
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user