Skip to content

Commit 76accfe

Browse files
committed
fix: move modifier-click guard to the asset selection consumer
AssetsListItem now always forwards the click event on preview-click instead of swallowing modifier-held clicks itself, so consumers that don't implement selection (JobAssetsList) keep opening the viewer on a modifier-held click. AssetsSidebarListView, which does implement selection, now gates both preview-click and dblclick on the modifier keys itself.
1 parent e25964b commit 76accfe

4 files changed

Lines changed: 60 additions & 29 deletions

File tree

src/components/sidebar/tabs/AssetsSidebarListView.test.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const AssetsListItemStub = defineComponent({
5656
:data-preview-url="previewUrl"
5757
:data-is-video-preview="isVideoPreview"
5858
data-testid="assets-list-item"
59-
><button data-testid="preview-click-trigger" @click="$emit('preview-click')" /><slot /></div>`
59+
><button data-testid="preview-click-trigger" @click="$emit('preview-click', $event)" /><slot /></div>`
6060
})
6161

6262
const buildAsset = (id: string, name: string): AssetItem =>
@@ -173,4 +173,46 @@ describe('AssetsSidebarListView', () => {
173173

174174
expect(onPreviewAsset).toHaveBeenCalledWith(imageAsset)
175175
})
176+
177+
it('does not emit preview-asset when preview is clicked with a selection modifier held', async () => {
178+
const imageAsset = {
179+
...buildAsset('image-asset-mod', 'image.png'),
180+
preview_url: '/api/view/image.png',
181+
user_metadata: {}
182+
} satisfies AssetItem
183+
184+
const onPreviewAsset = vi.fn()
185+
const { container } = renderListView([buildOutputItem(imageAsset)], {
186+
'onPreview-asset': onPreviewAsset
187+
})
188+
189+
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
190+
const trigger = container.querySelector(
191+
'[data-testid="preview-click-trigger"]'
192+
)!
193+
// eslint-disable-next-line testing-library/prefer-user-event
194+
await fireEvent.click(trigger, { ctrlKey: true })
195+
196+
expect(onPreviewAsset).not.toHaveBeenCalled()
197+
})
198+
199+
it('does not emit preview-asset when double-clicked with a selection modifier held', async () => {
200+
const imageAsset = {
201+
...buildAsset('image-asset-dbl-mod', 'image.png'),
202+
preview_url: '/api/view/image.png',
203+
user_metadata: {}
204+
} satisfies AssetItem
205+
206+
const onPreviewAsset = vi.fn()
207+
const { container } = renderListView([buildOutputItem(imageAsset)], {
208+
'onPreview-asset': onPreviewAsset
209+
})
210+
211+
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
212+
const stub = container.querySelector('[data-testid="assets-list-item"]')!
213+
// eslint-disable-next-line testing-library/prefer-user-event
214+
await fireEvent.dblClick(stub, { shiftKey: true })
215+
216+
expect(onPreviewAsset).not.toHaveBeenCalled()
217+
})
176218
})

src/components/sidebar/tabs/AssetsSidebarListView.vue

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
@mouseleave="onAssetLeave(item.asset.id)"
4545
@contextmenu.prevent.stop="emit('context-menu', $event, item.asset)"
4646
@click.stop="emit('select-asset', item.asset, selectableAssets)"
47-
@dblclick.stop="emit('preview-asset', item.asset)"
48-
@preview-click="emit('preview-asset', item.asset)"
47+
@dblclick.stop="openPreview($event, item.asset)"
48+
@preview-click="openPreview($event, item.asset)"
4949
@stack-toggle="void toggleStack(item.asset)"
5050
>
5151
<template v-if="hoveredAssetId === item.asset.id" #actions>
@@ -189,4 +189,11 @@ function onAssetLeave(assetId: string) {
189189
hoveredAssetId.value = null
190190
}
191191
}
192+
193+
function openPreview(event: MouseEvent, asset: AssetItem) {
194+
const hasSelectionModifier = event.shiftKey || event.metaKey || event.ctrlKey
195+
if (hasSelectionModifier) return
196+
197+
emit('preview-asset', asset)
198+
}
192199
</script>

src/platform/assets/components/AssetsListItem.test.ts

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ describe('AssetsListItem', () => {
8383
})
8484

8585
it.for(SELECTION_MODIFIERS)(
86-
'does not emit preview-click when %s is held over the preview',
87-
async ([, heldModifier]) => {
86+
'still emits preview-click with the event when %s is held over the preview',
87+
async ([modifierKey, heldModifier]) => {
8888
const user = userEvent.setup()
8989
const { emitted } = render(AssetsListItem, {
9090
props: {
@@ -96,25 +96,10 @@ describe('AssetsListItem', () => {
9696
await user.keyboard(heldModifier)
9797
await user.click(screen.getByRole('img'))
9898

99-
expect(emitted()['preview-click']).toBeUndefined()
100-
}
101-
)
102-
103-
it.for(SELECTION_MODIFIERS)(
104-
'does not emit preview-click when %s is held over the fallback icon',
105-
async ([, heldModifier]) => {
106-
const user = userEvent.setup()
107-
const { container, emitted } = render(AssetsListItem, {
108-
props: {
109-
iconName: 'icon-[lucide--box]'
110-
}
111-
})
112-
113-
await user.keyboard(heldModifier)
114-
// eslint-disable-next-line testing-library/no-container, testing-library/no-node-access -- aria-hidden icon, no semantic query available
115-
await user.click(container.querySelector('i')!)
116-
117-
expect(emitted()['preview-click']).toBeUndefined()
99+
const events = emitted()['preview-click']
100+
expect(events).toHaveLength(1)
101+
const [event] = events![0] as [MouseEvent]
102+
expect(event[`${modifierKey}Key`]).toBe(true)
118103
}
119104
)
120105
})

src/platform/assets/components/AssetsListItem.vue

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ import VideoPlayOverlay from './VideoPlayOverlay.vue'
143143
144144
const emit = defineEmits<{
145145
'stack-toggle': []
146-
'preview-click': []
146+
'preview-click': [event: MouseEvent]
147147
}>()
148148
149149
const {
@@ -179,10 +179,7 @@ const {
179179
}>()
180180
181181
function onPreviewClick(event: MouseEvent) {
182-
const hasSelectionModifier = event.shiftKey || event.metaKey || event.ctrlKey
183-
if (hasSelectionModifier) return
184-
185-
emit('preview-click')
182+
emit('preview-click', event)
186183
}
187184
188185
const {

0 commit comments

Comments
 (0)