Copy generated stills into Input without loading the current frame.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-08-31 22:57:54 -05:00
co-authored by Cursor
parent 835a7bcd68
commit 5037c4fdeb
5 changed files with 169 additions and 11 deletions
+39 -11
View File
@@ -122,16 +122,30 @@
</svg>
</button>
<span v-else />
<button
type="button"
class="rounded-full bg-amber-400 p-1.5 text-zinc-950 hover:bg-amber-300"
title="Use as input"
@click.stop="pickStill(still)"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" class="h-4 w-4">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</button>
<div class="flex items-center gap-1">
<button
v-if="tab === 'output'"
type="button"
class="rounded-full bg-zinc-950/80 p-1.5 text-amber-100 hover:bg-zinc-900 disabled:opacity-50"
title="Save as input"
:disabled="keepingId === still.id"
@click.stop="keepAsInput(still)"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="h-4 w-4">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v9m0 0l-3.5-3.5M12 13.5l3.5-3.5M5 19.5h14" />
</svg>
</button>
<button
type="button"
class="rounded-full bg-amber-400 p-1.5 text-zinc-950 hover:bg-amber-300"
title="Use as input"
@click.stop="pickStill(still)"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" class="h-4 w-4">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</button>
</div>
</div>
</div>
<div class="flex items-center justify-between gap-2 px-3 py-2">
@@ -195,6 +209,7 @@ const tab = ref<'input' | 'output'>('input')
const revealAll = ref(false)
const revealedIds = ref<string[]>([])
const picking = ref(false)
const keepingId = ref('')
function onKey(event: KeyboardEvent) {
if (!props.open) return
@@ -223,7 +238,7 @@ const pickerHint = computed(() => {
if (props.stillOnly) return 'Pick a still, then type a short name on the strip (or pick a GLOBAL LOCKS key). That name is what the shot prompt inherits.'
return tab.value === 'input'
? 'Uploaded stills only. Generated frames and edits live under Output.'
: 'Generated stills from image edits. Video frames stay with their clips.'
: 'Generated stills. Checkmark loads the current frame. Arrow copies the image into Input for later. Video frames stay with their clips.'
})
const hasHiddenItems = computed(() => visibleStills.value.some(still => stillHidden(still)))
@@ -301,6 +316,19 @@ function onDrop(event: DragEvent) {
if (next) void ingest(next)
}
async function keepAsInput(still: PickerStill) {
if (keepingId.value) return
keepingId.value = still.id
try {
emit('updated', await $fetch(`/api/library/stills/${still.id}/keep-input`, { method: 'POST' }))
tab.value = 'input'
} catch (error: any) {
emit('error', error?.data?.statusMessage || 'Could not save that still as input')
} finally {
keepingId.value = ''
}
}
async function pickStill(still: PickerStill) {
if (picking.value) return
picking.value = true