mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 03:01:54 +00:00
fix: keep selection consistent with visible assets
This commit is contained in:
@@ -310,6 +310,7 @@ const {
|
|||||||
hasSelection,
|
hasSelection,
|
||||||
clearSelection,
|
clearSelection,
|
||||||
getSelectedAssets,
|
getSelectedAssets,
|
||||||
|
reconcileSelection,
|
||||||
getOutputCount,
|
getOutputCount,
|
||||||
getTotalOutputCount,
|
getTotalOutputCount,
|
||||||
activate: activateSelection,
|
activate: activateSelection,
|
||||||
@@ -406,6 +407,9 @@ const showEmptyState = computed(
|
|||||||
)
|
)
|
||||||
|
|
||||||
watch(visibleAssets, (newAssets) => {
|
watch(visibleAssets, (newAssets) => {
|
||||||
|
// Alternative: keep hidden selections and surface them in UI; for now prune
|
||||||
|
// so selection stays consistent with what this view can act on.
|
||||||
|
reconcileSelection(newAssets)
|
||||||
if (currentGalleryAssetId.value && galleryActiveIndex.value !== -1) {
|
if (currentGalleryAssetId.value && galleryActiveIndex.value !== -1) {
|
||||||
const newIndex = newAssets.findIndex(
|
const newIndex = newAssets.findIndex(
|
||||||
(asset) => asset.id === currentGalleryAssetId.value
|
(asset) => asset.id === currentGalleryAssetId.value
|
||||||
|
|||||||
48
src/platform/assets/composables/useAssetSelection.test.ts
Normal file
48
src/platform/assets/composables/useAssetSelection.test.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { createPinia, setActivePinia } from 'pinia'
|
||||||
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
|
||||||
|
|
||||||
|
import { useAssetSelection } from './useAssetSelection'
|
||||||
|
import { useAssetSelectionStore } from './useAssetSelectionStore'
|
||||||
|
|
||||||
|
vi.mock('@vueuse/core', () => ({
|
||||||
|
useKeyModifier: vi.fn(() => ref(false))
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe('useAssetSelection', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia())
|
||||||
|
})
|
||||||
|
|
||||||
|
it('prunes selection to visible assets', () => {
|
||||||
|
const selection = useAssetSelection()
|
||||||
|
const store = useAssetSelectionStore()
|
||||||
|
const assets: AssetItem[] = [
|
||||||
|
{ id: 'a', name: 'a.png', tags: [] },
|
||||||
|
{ id: 'b', name: 'b.png', tags: [] }
|
||||||
|
]
|
||||||
|
|
||||||
|
store.setSelection(['a', 'b'])
|
||||||
|
store.setLastSelectedIndex(1)
|
||||||
|
|
||||||
|
selection.reconcileSelection([assets[1]])
|
||||||
|
|
||||||
|
expect(Array.from(store.selectedAssetIds)).toEqual(['b'])
|
||||||
|
expect(store.lastSelectedIndex).toBe(-1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clears selection when no visible assets remain', () => {
|
||||||
|
const selection = useAssetSelection()
|
||||||
|
const store = useAssetSelectionStore()
|
||||||
|
|
||||||
|
store.setSelection(['a'])
|
||||||
|
store.setLastSelectedIndex(0)
|
||||||
|
|
||||||
|
selection.reconcileSelection([])
|
||||||
|
|
||||||
|
expect(store.selectedAssetIds.size).toBe(0)
|
||||||
|
expect(store.lastSelectedIndex).toBe(-1)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -88,6 +88,38 @@ export function useAssetSelection() {
|
|||||||
return allAssets.filter((asset) => selectionStore.isSelected(asset.id))
|
return allAssets.filter((asset) => selectionStore.isSelected(asset.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function reconcileSelection(assets: AssetItem[]) {
|
||||||
|
if (selectionStore.selectedAssetIds.size === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assets.length === 0) {
|
||||||
|
selectionStore.clearSelection()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const visibleIds = new Set(assets.map((asset) => asset.id))
|
||||||
|
const nextSelectedIds: string[] = []
|
||||||
|
|
||||||
|
for (const id of selectionStore.selectedAssetIds) {
|
||||||
|
if (visibleIds.has(id)) {
|
||||||
|
nextSelectedIds.push(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextSelectedIds.length === selectionStore.selectedAssetIds.size) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextSelectedIds.length === 0) {
|
||||||
|
selectionStore.clearSelection()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
selectionStore.setSelection(nextSelectedIds)
|
||||||
|
selectionStore.setLastSelectedIndex(-1)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the output count for a single asset
|
* Get the output count for a single asset
|
||||||
* Same logic as in AssetsSidebarTab.vue
|
* Same logic as in AssetsSidebarTab.vue
|
||||||
@@ -132,6 +164,7 @@ export function useAssetSelection() {
|
|||||||
selectAll,
|
selectAll,
|
||||||
clearSelection: () => selectionStore.clearSelection(),
|
clearSelection: () => selectionStore.clearSelection(),
|
||||||
getSelectedAssets,
|
getSelectedAssets,
|
||||||
|
reconcileSelection,
|
||||||
getOutputCount,
|
getOutputCount,
|
||||||
getTotalOutputCount,
|
getTotalOutputCount,
|
||||||
reset: () => selectionStore.reset(),
|
reset: () => selectionStore.reset(),
|
||||||
|
|||||||
Reference in New Issue
Block a user