Highlight the library row that is open in Output.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+59
-4
@@ -1529,8 +1529,10 @@
|
|||||||
<li
|
<li
|
||||||
v-for="entry in libraryEntries"
|
v-for="entry in libraryEntries"
|
||||||
:key="entry.key"
|
:key="entry.key"
|
||||||
class="rounded-2xl border p-3"
|
class="cursor-pointer rounded-2xl border p-3"
|
||||||
:class="selectedKeys.includes(entry.key) ? 'border-amber-300/30 bg-amber-400/5' : 'border-white/5 bg-zinc-950/40'"
|
:class="libraryEntryClass(entry)"
|
||||||
|
:aria-current="isLibraryEntryFocused(entry) ? 'true' : undefined"
|
||||||
|
@click="onLibraryCardClick(entry, $event)"
|
||||||
>
|
>
|
||||||
<template v-if="entry.kind === 'clip'">
|
<template v-if="entry.kind === 'clip'">
|
||||||
<div class="flex gap-3">
|
<div class="flex gap-3">
|
||||||
@@ -1632,7 +1634,10 @@
|
|||||||
<li
|
<li
|
||||||
v-for="(item, partIndex) in chronologicalParts(entry.group.parts)"
|
v-for="(item, partIndex) in chronologicalParts(entry.group.parts)"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
class="flex flex-wrap items-start gap-3 rounded-xl border border-white/5 bg-black/20 p-2"
|
class="flex cursor-pointer flex-wrap items-start gap-3 rounded-xl border p-2"
|
||||||
|
:class="item.id === reviewingClipId ? 'border-amber-300/80 bg-amber-400/15 ring-1 ring-amber-300/60' : 'border-white/5 bg-black/20'"
|
||||||
|
:aria-current="item.id === reviewingClipId ? 'true' : undefined"
|
||||||
|
@click="onLibraryClipPartClick(item, $event)"
|
||||||
>
|
>
|
||||||
<ClipFrameThumbs
|
<ClipFrameThumbs
|
||||||
:hidden="item.hideThumbnail"
|
:hidden="item.hideThumbnail"
|
||||||
@@ -1794,7 +1799,10 @@
|
|||||||
<li
|
<li
|
||||||
v-for="item in chronologicalStills(entry.stillGroup.parts)"
|
v-for="item in chronologicalStills(entry.stillGroup.parts)"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
class="flex gap-3 rounded-xl border border-white/5 bg-black/20 p-2"
|
class="flex cursor-pointer gap-3 rounded-xl border p-2"
|
||||||
|
:class="item.id === reviewingStillId ? 'border-amber-300/80 bg-amber-400/15 ring-1 ring-amber-300/60' : 'border-white/5 bg-black/20'"
|
||||||
|
:aria-current="item.id === reviewingStillId ? 'true' : undefined"
|
||||||
|
@click="onLibraryStillPartClick(item, $event)"
|
||||||
>
|
>
|
||||||
<button type="button" class="relative h-12 w-12 shrink-0 overflow-hidden rounded-lg bg-zinc-900" @click="openStill(item)">
|
<button type="button" class="relative h-12 w-12 shrink-0 overflow-hidden rounded-lg bg-zinc-900" @click="openStill(item)">
|
||||||
<span v-if="item.hideInput" class="sensitive-glow block h-full w-full" />
|
<span v-if="item.hideInput" class="sensitive-glow block h-full w-full" />
|
||||||
@@ -2962,6 +2970,53 @@ const libraryEntries = computed(() => {
|
|||||||
}))
|
}))
|
||||||
return [...videos, ...images].sort((a, b) => b.createdAt - a.createdAt)
|
return [...videos, ...images].sort((a, b) => b.createdAt - a.createdAt)
|
||||||
})
|
})
|
||||||
|
const reviewingClipId = computed(() => {
|
||||||
|
if (outputPreviewKind.value !== 'video' || lockedSave.value) return ''
|
||||||
|
const fromUrl = String(videoUrl.value || '').match(/\/api\/library\/clips\/([^/?#]+)\/video/)
|
||||||
|
return currentClipId.value || fromUrl?.[1] || ''
|
||||||
|
})
|
||||||
|
const reviewingStillId = computed(() => {
|
||||||
|
if (outputPreviewKind.value !== 'edit' || editLockedSave.value) return ''
|
||||||
|
return stillIdFromLibraryUrl(editResultUrl.value)
|
||||||
|
})
|
||||||
|
type LibraryEntry = (typeof libraryEntries.value)[number]
|
||||||
|
function isLibraryEntryFocused(entry: LibraryEntry) {
|
||||||
|
if (entry.kind === 'clip' && reviewingClipId.value) {
|
||||||
|
return entry.group.parts.some(part => part.id === reviewingClipId.value)
|
||||||
|
}
|
||||||
|
if (entry.kind === 'still' && reviewingStillId.value && entry.stillGroup) {
|
||||||
|
return entry.stillGroup.parts.some(part => part.id === reviewingStillId.value)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
function libraryEntryClass(entry: LibraryEntry) {
|
||||||
|
if (isLibraryEntryFocused(entry)) {
|
||||||
|
return 'border-amber-300 bg-amber-400/15 ring-2 ring-amber-300/70'
|
||||||
|
}
|
||||||
|
if (selectedKeys.value.includes(entry.key)) {
|
||||||
|
return 'border-amber-300/30 bg-amber-400/5'
|
||||||
|
}
|
||||||
|
return 'border-white/5 bg-zinc-950/40'
|
||||||
|
}
|
||||||
|
function libraryClickIgnored(event: MouseEvent) {
|
||||||
|
const target = event.target as HTMLElement | null
|
||||||
|
return Boolean(target?.closest('button, a, input, select, textarea, label'))
|
||||||
|
}
|
||||||
|
function onLibraryCardClick(entry: LibraryEntry, event: MouseEvent) {
|
||||||
|
if (libraryClickIgnored(event)) return
|
||||||
|
if (entry.kind === 'clip') openClip(entry.group.head)
|
||||||
|
else if (entry.stillGroup) openStill(entry.stillGroup.head)
|
||||||
|
}
|
||||||
|
function onLibraryClipPartClick(item: LibraryClip, event: MouseEvent) {
|
||||||
|
event.stopPropagation()
|
||||||
|
if (libraryClickIgnored(event)) return
|
||||||
|
openClip(item)
|
||||||
|
}
|
||||||
|
function onLibraryStillPartClick(item: LibraryStill, event: MouseEvent) {
|
||||||
|
event.stopPropagation()
|
||||||
|
if (libraryClickIgnored(event)) return
|
||||||
|
openStill(item)
|
||||||
|
}
|
||||||
const libraryEmptyLabel = computed(() => {
|
const libraryEmptyLabel = computed(() => {
|
||||||
if (libraryFilter.value === 'images') return 'No generated stills in this folder yet.'
|
if (libraryFilter.value === 'images') return 'No generated stills in this folder yet.'
|
||||||
if (libraryFilter.value === 'videos') return 'No generated clips in this folder yet.'
|
if (libraryFilter.value === 'videos') return 'No generated clips in this folder yet.'
|
||||||
|
|||||||
Reference in New Issue
Block a user