Add generation quality controls and bind them to the MiniMax workflow.
Expose aspect, CFG, FPS, sampler, and scheduler in Generation settings, persist them on clips and held jobs, and inject those values into the Comfy graph. Keep the image picker stills-only and allow renaming library clips. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -65,8 +65,8 @@
|
||||
</div>
|
||||
|
||||
<template v-if="current && (!current.protected || current.unlocked)">
|
||||
<p v-if="!visibleStills.length && !visibleClipThumbs.length" class="mt-6 text-sm text-zinc-500">No uploaded stills in this folder yet.</p>
|
||||
<div v-if="visibleStills.length || visibleClipThumbs.length" class="mt-5 grid grid-cols-2 gap-3 sm:grid-cols-3 md:grid-cols-4">
|
||||
<p v-if="!visibleStills.length" class="mt-6 text-sm text-zinc-500">No uploaded stills in this folder yet.</p>
|
||||
<div v-if="visibleStills.length" class="mt-5 grid grid-cols-2 gap-3 sm:grid-cols-3 md:grid-cols-4">
|
||||
<article
|
||||
v-for="still in visibleStills"
|
||||
:key="still.id"
|
||||
@@ -116,63 +116,6 @@
|
||||
<button type="button" class="text-[10px] text-red-300 hover:text-red-200" @click="removeStill(still)">Delete</button>
|
||||
</div>
|
||||
</article>
|
||||
<article
|
||||
v-for="clip in visibleClipThumbs"
|
||||
:key="'clip-' + clip.id"
|
||||
class="overflow-hidden rounded-2xl border border-white/10 bg-zinc-950"
|
||||
>
|
||||
<div class="relative h-28 overflow-hidden bg-zinc-900">
|
||||
<img
|
||||
v-if="clip.hasThumbnail || clip.hideThumbnail"
|
||||
:src="`/api/library/clips/${clip.id}/thumb`"
|
||||
alt=""
|
||||
class="h-full w-full object-cover"
|
||||
:class="clip.hideThumbnail && !isRevealed('clip-' + clip.id) ? 'scale-110 blur-xl' : ''"
|
||||
>
|
||||
<video
|
||||
v-else
|
||||
:src="`/api/library/clips/${clip.id}/video#t=0.1`"
|
||||
class="h-full w-full object-cover"
|
||||
muted
|
||||
playsinline
|
||||
preload="metadata"
|
||||
/>
|
||||
<span v-if="clip.hideThumbnail && !isRevealed('clip-' + clip.id)" class="sensitive-glow pointer-events-none absolute inset-0 opacity-80" />
|
||||
<div class="absolute inset-x-0 top-0 flex items-start justify-between p-2">
|
||||
<button
|
||||
v-if="clip.hideThumbnail"
|
||||
type="button"
|
||||
class="rounded-full bg-zinc-950/80 p-1.5 text-amber-100 hover:bg-zinc-900"
|
||||
:title="isRevealed('clip-' + clip.id) ? 'Hide thumbnail' : 'Reveal thumbnail'"
|
||||
@click="toggleReveal('clip-' + clip.id)"
|
||||
>
|
||||
<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">
|
||||
<template v-if="isRevealed('clip-' + clip.id)">
|
||||
<path stroke-linecap="round" d="M3 3l18 18M10.6 10.6a2 2 0 102.8 2.8M9.9 5.1A9.8 9.8 0 0121 12a9.8 9.8 0 01-1.7 2.9M6.1 6.1A9.8 9.8 0 003 12a9.8 9.8 0 0012.9 6.1" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12z" />
|
||||
<circle cx="12" cy="12" r="3" />
|
||||
</template>
|
||||
</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="pickClip(clip)"
|
||||
>
|
||||
<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 class="px-3 py-2">
|
||||
<span class="truncate text-xs text-zinc-400">{{ clip.name || 'From a clip' }}</span>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -199,19 +142,9 @@ export interface PickerStill {
|
||||
hideInput?: boolean
|
||||
}
|
||||
|
||||
export interface PickerClip {
|
||||
id: string
|
||||
folderId: string
|
||||
hideThumbnail: boolean
|
||||
hasThumbnail?: boolean
|
||||
name?: string
|
||||
prompt: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
folders: PickerFolder[]
|
||||
stills: PickerStill[]
|
||||
clips: PickerClip[]
|
||||
folderId: string
|
||||
hideInputPreview?: boolean
|
||||
}>()
|
||||
@@ -245,10 +178,7 @@ watch(() => props.folderId, (id) => {
|
||||
|
||||
const current = computed(() => props.folders.find(folder => folder.id === activeFolderId.value) || props.folders[0])
|
||||
const visibleStills = computed(() => props.stills.filter(still => still.folderId === (current.value?.id || activeFolderId.value)))
|
||||
const visibleClipThumbs = computed(() => props.clips.filter(clip => clip.folderId === (current.value?.id || activeFolderId.value)))
|
||||
const hasHiddenItems = computed(() => {
|
||||
return visibleStills.value.some(still => stillHidden(still)) || visibleClipThumbs.value.some(clip => clip.hideThumbnail)
|
||||
})
|
||||
const hasHiddenItems = computed(() => visibleStills.value.some(still => stillHidden(still)))
|
||||
|
||||
function stillHidden(still: PickerStill) {
|
||||
return still.hideInput === true || props.hideInputPreview === true
|
||||
@@ -272,10 +202,7 @@ function toggleReveal(id: string) {
|
||||
}
|
||||
|
||||
function visibleHiddenIds() {
|
||||
return [
|
||||
...visibleStills.value.filter(still => stillHidden(still)).map(still => still.id),
|
||||
...visibleClipThumbs.value.filter(clip => clip.hideThumbnail).map(clip => 'clip-' + clip.id)
|
||||
]
|
||||
return visibleStills.value.filter(still => stillHidden(still)).map(still => still.id)
|
||||
}
|
||||
|
||||
function toggleRevealAll() {
|
||||
@@ -321,16 +248,6 @@ function onDrop(event: DragEvent) {
|
||||
if (next) void ingest(next)
|
||||
}
|
||||
|
||||
async function pickClip(clip: PickerClip) {
|
||||
try {
|
||||
const blob = await $fetch<Blob>(`/api/library/clips/${clip.id}/thumb`, { responseType: 'blob' })
|
||||
const file = new File([blob], `${clip.id}.png`, { type: blob.type || 'image/png' })
|
||||
emit('select', file, clip.hideThumbnail === true)
|
||||
} catch (error: any) {
|
||||
emit('error', error?.data?.statusMessage || 'Could not load that still')
|
||||
}
|
||||
}
|
||||
|
||||
async function pickStill(still: PickerStill) {
|
||||
try {
|
||||
const blob = await $fetch<Blob>(`/api/library/stills/${still.id}`, { responseType: 'blob' })
|
||||
|
||||
Reference in New Issue
Block a user