Overhaul Studio controls and add image batch from one still.

Video and Image pickers, thumbwheels, aspect icons, and a Scale to MP paddle; extra prompts default to batch so each run starts from the original image.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-08-30 23:16:19 -05:00
co-authored by Cursor
parent 8df265cbf3
commit 755aaeede8
17 changed files with 791 additions and 233 deletions
+12 -14
View File
@@ -17,17 +17,16 @@
>
<span class="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-xs text-zinc-500">s</span>
</div>
<input
class="aigen-slider mt-3 w-full"
type="range"
:min="SLIDER_MIN"
:max="SLIDER_MAX"
:step="0.1"
:value="slider"
:style="{ background: `linear-gradient(to right, #fbbf24 ${sliderPct}%, #27272a ${sliderPct}%)` }"
:aria-label="label || 'Duration in seconds'"
@input="onSlider"
>
<div class="mt-3">
<Thumbwheel
:model-value="slider"
:min="SLIDER_MIN"
:max="SLIDER_MAX"
:step="0.1"
compact
@update:model-value="onSliderValue"
/>
</div>
<p v-if="hint" class="mt-1 text-[11px] text-zinc-500">{{ hint }}</p>
</div>
</template>
@@ -51,7 +50,6 @@ const draft = ref(formatDuration(model.value))
const scrubbing = ref(false)
const slider = computed(() => Math.min(SLIDER_MAX, Math.max(SLIDER_MIN, model.value)))
const sliderPct = computed(() => ((slider.value - SLIDER_MIN) / (SLIDER_MAX - SLIDER_MIN)) * 100)
watch(model, (value) => {
if (!scrubbing.value) draft.value = formatDuration(value)
@@ -72,8 +70,8 @@ function commit() {
draft.value = formatDuration(model.value)
}
function onSlider(event: Event) {
model.value = clampDuration(Number((event.target as HTMLInputElement).value))
function onSliderValue(value: number) {
model.value = clampDuration(value)
draft.value = formatDuration(model.value)
}