Bind Classic model select and Studio engine rail to the same engine ref.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-18 13:10:13 -05:00
co-authored by Cursor
parent 1b29452455
commit d9743dd8c9
+42 -12
View File
@@ -40,6 +40,31 @@
>{{ task }}</button> >{{ task }}</button>
</nav> </nav>
<div v-if="form.mode!=='music'" class="min-w-0">
<label v-if="isClassic" class="block text-sm text-zinc-300">Model
<select v-model="form.engine" class="mt-1 w-full max-w-md rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 outline-none ring-amber-300/40 focus:ring-2">
<option v-for="opt in engineOptions" :key="opt.value" :value="opt.value" :disabled="opt.disabled">{{ opt.label }}{{ opt.hint ? ' — '+opt.hint : '' }}</option>
</select>
</label>
<div v-else class="display-rail" role="group" aria-label="Model">
<button
v-for="opt in engineOptions"
:key="opt.value"
type="button"
class="display-rail__seg"
:aria-pressed="form.engine===opt.value"
:aria-disabled="opt.disabled || undefined"
:disabled="opt.disabled"
:title="opt.hint || undefined"
@click="!opt.disabled && (form.engine=opt.value)"
>
<span class="block">{{ opt.label }}</span>
<span v-if="opt.hint" class="mt-0.5 block text-[11px] font-normal opacity-80">{{ opt.hint }}</span>
</button>
</div>
</div>
<p v-else class="text-sm text-zinc-400">Model · YuE2</p>
<div class="grid min-w-0 gap-6 xl:grid-cols-[minmax(0,3fr)_minmax(24rem,2fr)] 2xl:gap-8"> <div class="grid min-w-0 gap-6 xl:grid-cols-[minmax(0,3fr)_minmax(24rem,2fr)] 2xl:gap-8">
<section class="min-w-0 space-y-4"> <section class="min-w-0 space-y-4">
<div class="relative flex min-h-80 items-center justify-center overflow-hidden rounded-3xl border border-white/10 bg-black"> <div class="relative flex min-h-80 items-center justify-center overflow-hidden rounded-3xl border border-white/10 bg-black">
@@ -208,18 +233,6 @@
<button type="button" class="float-right outline-none ring-amber-300/40 focus-visible:ring-2" @click="settingsOpen=false;detailsOpen=false">Close</button> <button type="button" class="float-right outline-none ring-amber-300/40 focus-visible:ring-2" @click="settingsOpen=false;detailsOpen=false">Close</button>
<template v-if="settingsOpen"> <template v-if="settingsOpen">
<h2 class="mb-6 text-xl font-semibold">Generation settings</h2> <h2 class="mb-6 text-xl font-semibold">Generation settings</h2>
<label class="mb-4 block">Engine
<select v-model="form.engine" class="mt-1 w-full rounded bg-zinc-800 p-2 outline-none ring-amber-300/40 focus:ring-2">
<template v-if="video">
<option value="minimax">MiniMax H3</option>
<option v-if="xaigen" value="ltx">LTX Pink Cherry</option>
</template>
<template v-else>
<option value="flux">Flux Klein 9B Base</option>
<option value="krea" :disabled="['edit','compose','iterate'].includes(form.mode)">Krea 2 (Generate / Refine)</option>
</template>
</select>
</label>
<AspectRatioPick v-model="form.settings.aspect" heading="Aspect" :options="aspectOptions" /> <AspectRatioPick v-model="form.settings.aspect" heading="Aspect" :options="aspectOptions" />
<p class="my-3 text-sm text-zinc-400">{{ resolvedSize.width }} × {{ resolvedSize.height }} · fit with padding, never stretch</p> <p class="my-3 text-sm text-zinc-400">{{ resolvedSize.width }} × {{ resolvedSize.height }} · fit with padding, never stretch</p>
<label v-for="key in ['steps','cfg',...(video?['duration','fps']:[])]" :key="key" class="mb-4 block capitalize">{{ key }} <label v-for="key in ['steps','cfg',...(video?['duration','fps']:[])]" :key="key" class="mb-4 block capitalize">{{ key }}
@@ -296,6 +309,23 @@ const route=useRoute()
const tasks=['generate','edit','compose','refine','video','extend','music'] const tasks=['generate','edit','compose','refine','video','extend','music']
const settingsOpen=ref(false),detailsOpen=ref(false),submitting=ref(false),error=ref(''),batchText=ref('') const settingsOpen=ref(false),detailsOpen=ref(false),submitting=ref(false),error=ref(''),batchText=ref('')
const video=computed(()=>['video','extend'].includes(form.mode)) const video=computed(()=>['video','extend'].includes(form.mode))
const kreaSticky=computed(()=>['edit','compose','iterate'].includes(form.mode))
const engineOptions=computed(()=>{
if(video.value){
return [
{value:'minimax',label:'MiniMax H3',disabled:false,hint:''},
{value:'ltx',label:'LTX',disabled:!xaigen,hint:xaigen?'':'xAIGen only'}
]
}
return [
{value:'flux',label:'Klein',disabled:false,hint:''},
{value:'krea',label:'Krea 2',disabled:kreaSticky.value,hint:kreaSticky.value?'sticky hero = Klein':''}
]
})
watch(engineOptions,opts=>{
const current=opts.find(o=>o.value===form.engine)
if(!current || current.disabled)form.engine=opts.find(o=>!o.disabled)?.value || form.engine
})
const stills=computed(()=>library.value.stills.filter((s:any)=>s.folderId===form.folderId)) const stills=computed(()=>library.value.stills.filter((s:any)=>s.folderId===form.folderId))
const clips=computed(()=>library.value.clips.filter((s:any)=>s.folderId===form.folderId)) const clips=computed(()=>library.value.clips.filter((s:any)=>s.folderId===form.folderId))
const compiled=computed(()=>compilePrompt(form.promptSections,video.value,form)) const compiled=computed(()=>compilePrompt(form.promptSections,video.value,form))