Rely on asset IDs for selection state

This commit is contained in:
Benjamin Lu
2026-01-24 07:33:29 -08:00
parent bafb13d55d
commit a908193449
4 changed files with 53 additions and 11 deletions

View File

@@ -264,6 +264,7 @@ const focusAssetInSidebar = async (item: JobListItem) => {
throw new Error('Asset not found in media assets panel')
}
assetSelectionStore.setSelection([assetId])
assetSelectionStore.setLastSelectedAssetId(assetId)
}
const inspectJobAsset = wrapWithErrorHandlingAsync(

View File

@@ -26,11 +26,13 @@ describe('useAssetSelection', () => {
store.setSelection(['a', 'b'])
store.setLastSelectedIndex(1)
store.setLastSelectedAssetId('b')
selection.reconcileSelection([assets[1]])
expect(Array.from(store.selectedAssetIds)).toEqual(['b'])
expect(store.lastSelectedIndex).toBe(-1)
expect(store.lastSelectedIndex).toBe(0)
expect(store.lastSelectedAssetId).toBe('b')
})
it('clears selection when no visible assets remain', () => {
@@ -39,10 +41,30 @@ describe('useAssetSelection', () => {
store.setSelection(['a'])
store.setLastSelectedIndex(0)
store.setLastSelectedAssetId('a')
selection.reconcileSelection([])
expect(store.selectedAssetIds.size).toBe(0)
expect(store.lastSelectedIndex).toBe(-1)
expect(store.lastSelectedAssetId).toBeNull()
})
it('recomputes the anchor index when assets reorder', () => {
const selection = useAssetSelection()
const store = useAssetSelectionStore()
const assets: AssetItem[] = [
{ id: 'a', name: 'a.png', tags: [] },
{ id: 'b', name: 'b.png', tags: [] }
]
store.setSelection(['a'])
store.setLastSelectedIndex(0)
store.setLastSelectedAssetId('a')
selection.reconcileSelection([assets[1], assets[0]])
expect(store.lastSelectedIndex).toBe(1)
expect(store.lastSelectedAssetId).toBe('a')
})
})

View File

@@ -61,6 +61,7 @@ export function useAssetSelection() {
if (cmdOrCtrlKey.value) {
selectionStore.toggleSelection(assetId)
selectionStore.setLastSelectedIndex(index)
selectionStore.setLastSelectedAssetId(assetId)
return
}
@@ -68,6 +69,7 @@ export function useAssetSelection() {
selectionStore.clearSelection()
selectionStore.addToSelection(assetId)
selectionStore.setLastSelectedIndex(index)
selectionStore.setLastSelectedAssetId(assetId)
}
/**
@@ -77,7 +79,9 @@ export function useAssetSelection() {
const allIds = allAssets.map((a) => a.id)
selectionStore.setSelection(allIds)
if (allAssets.length > 0) {
selectionStore.setLastSelectedIndex(allAssets.length - 1)
const lastIndex = allAssets.length - 1
selectionStore.setLastSelectedIndex(lastIndex)
selectionStore.setLastSelectedAssetId(allAssets[lastIndex].id)
}
}
@@ -107,7 +111,18 @@ export function useAssetSelection() {
}
}
const anchorId = selectionStore.lastSelectedAssetId
const anchorIndex = anchorId
? assets.findIndex((asset) => asset.id === anchorId)
: -1
if (nextSelectedIds.length === selectionStore.selectedAssetIds.size) {
if (anchorIndex !== -1) {
selectionStore.setLastSelectedIndex(anchorIndex)
} else {
selectionStore.setLastSelectedIndex(-1)
selectionStore.setLastSelectedAssetId(null)
}
return
}
@@ -117,7 +132,12 @@ export function useAssetSelection() {
}
selectionStore.setSelection(nextSelectedIds)
selectionStore.setLastSelectedIndex(-1)
if (anchorIndex !== -1) {
selectionStore.setLastSelectedIndex(anchorIndex)
} else {
selectionStore.setLastSelectedIndex(-1)
selectionStore.setLastSelectedAssetId(null)
}
}
/**
@@ -149,7 +169,7 @@ export function useAssetSelection() {
function deactivate() {
isActive.value = false
// Reset selection state to ensure clean state when deactivated
selectionStore.reset()
selectionStore.clearSelection()
}
return {
@@ -167,8 +187,6 @@ export function useAssetSelection() {
reconcileSelection,
getOutputCount,
getTotalOutputCount,
reset: () => selectionStore.reset(),
// Lifecycle management
activate,
deactivate,

View File

@@ -5,6 +5,7 @@ export const useAssetSelectionStore = defineStore('assetSelection', () => {
// State
const selectedAssetIds = ref<Set<string>>(new Set())
const lastSelectedIndex = ref<number>(-1)
const lastSelectedAssetId = ref<string | null>(null)
// Getters
const selectedCount = computed(() => selectedAssetIds.value.size)
@@ -34,6 +35,7 @@ export const useAssetSelectionStore = defineStore('assetSelection', () => {
function clearSelection() {
selectedAssetIds.value.clear()
lastSelectedIndex.value = -1
lastSelectedAssetId.value = null
}
function toggleSelection(assetId: string) {
@@ -52,16 +54,15 @@ export const useAssetSelectionStore = defineStore('assetSelection', () => {
lastSelectedIndex.value = index
}
// Reset function for cleanup
function reset() {
selectedAssetIds.value.clear()
lastSelectedIndex.value = -1
function setLastSelectedAssetId(assetId: string | null) {
lastSelectedAssetId.value = assetId
}
return {
// State
selectedAssetIds: computed(() => selectedAssetIds.value),
lastSelectedIndex: computed(() => lastSelectedIndex.value),
lastSelectedAssetId: computed(() => lastSelectedAssetId.value),
// Getters
selectedCount,
@@ -76,6 +77,6 @@ export const useAssetSelectionStore = defineStore('assetSelection', () => {
toggleSelection,
isSelected,
setLastSelectedIndex,
reset
setLastSelectedAssetId
}
})