Put still actions on the stage and split output vs input hide.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -49,21 +49,33 @@
|
||||
|
||||
<div class="m-stage">
|
||||
<div class="m-stage-chrome" aria-label="Stage controls">
|
||||
<button
|
||||
type="button"
|
||||
class="m-library"
|
||||
:aria-expanded="ctx.libraryOpen ? 'true' : 'false'"
|
||||
@click="ctx.openLibrary()"
|
||||
>Library<span v-if="ctx.familyStillCount" class="m-library-count">{{ ctx.familyStillCount }}</span></button>
|
||||
<button
|
||||
v-if="ctx.selected"
|
||||
type="button"
|
||||
class="m-eye"
|
||||
:aria-label="ctx.isHidden(ctx.selected) ? 'Show preview' : 'Hide preview'"
|
||||
@click.stop="ctx.toggleReveal(ctx.selected.id)"
|
||||
<div class="m-stage-chrome-top">
|
||||
<button
|
||||
type="button"
|
||||
class="m-library"
|
||||
:aria-expanded="ctx.libraryOpen ? 'true' : 'false'"
|
||||
@click="ctx.openLibrary()"
|
||||
>Library<span v-if="ctx.familyStillCount" class="m-library-count">{{ ctx.familyStillCount }}</span></button>
|
||||
<button
|
||||
v-if="ctx.selected"
|
||||
type="button"
|
||||
class="m-eye"
|
||||
:aria-label="ctx.eyeOpen ? 'Hide output' : 'Show output'"
|
||||
@click.stop="ctx.toggleReveal()"
|
||||
>
|
||||
<img :src="ctx.eyeOpen ? '/icons/display/eye.svg' : '/icons/display/eye-off.svg'" alt="" width="20" height="20">
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
v-if="ctx.selected && ctx.selected.kind!=='track'"
|
||||
class="m-stage-actions"
|
||||
aria-label="Selected still actions"
|
||||
>
|
||||
<img :src="ctx.isHidden(ctx.selected) ? '/icons/display/eye-off.svg' : '/icons/display/eye.svg'" alt="" width="20" height="20">
|
||||
</button>
|
||||
<button type="button" @click.stop="ctx.applyUseAsSource">Use as photo</button>
|
||||
<button type="button" @click.stop="ctx.copySelectedPrompt">Copy prompt</button>
|
||||
<button type="button" @click.stop="ctx.loadSelectedJob">Load</button>
|
||||
<button type="button" class="m-danger" @click.stop="ctx.deleteOutput">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
v-if="(ctx.family || []).length > 1"
|
||||
@@ -80,7 +92,7 @@
|
||||
@click.stop="ctx.stepFamily(1)"
|
||||
>›</button>
|
||||
<template v-if="ctx.selected && ctx.isHidden(ctx.selected)">
|
||||
<p class="m-muted">{{ ctx.selected.kind==='track' ? 'Track loaded · preview hidden' : 'Preview hidden' }}</p>
|
||||
<p class="m-muted">{{ ctx.selected.kind==='track' ? 'Track loaded · preview hidden' : 'Output hidden' }}</p>
|
||||
</template>
|
||||
<template v-else-if="ctx.selected?.kind==='track'">
|
||||
<div class="m-audio">
|
||||
@@ -103,13 +115,14 @@
|
||||
:assets="ctx.family || []"
|
||||
:selected="ctx.selected"
|
||||
:folder-id="ctx.form?.folderId"
|
||||
:is-hidden="ctx.isHidden"
|
||||
:preview-hidden="!ctx.eyeOpen"
|
||||
@close="ctx.closeLibrary()"
|
||||
@select="ctx.selectOutput"
|
||||
@use-as-photo="ctx.onLibraryUseAsPhoto"
|
||||
@copy-prompt="ctx.onLibraryCopyPrompt"
|
||||
@load="ctx.onLibraryLoad"
|
||||
@delete="ctx.onLibraryDelete"
|
||||
@toggle-preview="ctx.toggleReveal()"
|
||||
/>
|
||||
|
||||
<div class="m-dock">
|
||||
@@ -133,21 +146,39 @@
|
||||
<p class="m-muted">Continues from last frame</p>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p v-if="!ctx.form.photos?.length && ctx.photosPlanState.emptyHint" class="m-muted">{{ ctx.photosPlanState.emptyHint }}</p>
|
||||
<Studio2AssetSlot
|
||||
v-for="(card, index) in ctx.form.photos"
|
||||
:key="'m-photo-'+index+'-'+card.stillId"
|
||||
:asset="ctx.stillById(card.stillId)"
|
||||
:hidden="ctx.slotHidden(card.stillId)"
|
||||
:role="card.role"
|
||||
:role-options="ctx.photoRoleOptions"
|
||||
@pick="ctx.setPicker('photo:'+index)"
|
||||
@remove="ctx.removePhoto(index)"
|
||||
@mention="ctx.mentionPhoto(index)"
|
||||
@update:role="ctx.setPhotoRole(index, $event)"
|
||||
/>
|
||||
<button v-if="(ctx.form.photos?.length||0) < ctx.photosPlanState.max" type="button" class="m-amber" @click="ctx.addPhoto">+ Add photo</button>
|
||||
<p v-if="ctx.photoRoleWarning" class="m-hint">{{ ctx.photoRoleWarning }}</p>
|
||||
<div class="m-photos-head">
|
||||
<button type="button" class="m-link" @click="ctx.toggleHideInputs()">
|
||||
{{ ctx.hideInputs ? 'Show inputs' : 'Hide inputs' }}
|
||||
</button>
|
||||
</div>
|
||||
<template v-if="ctx.hideInputs">
|
||||
<p class="m-muted">
|
||||
{{ ctx.photoFilledCount || 0 }} photo{{ (ctx.photoFilledCount||0)===1 ? '' : 's' }}
|
||||
<button
|
||||
v-if="(ctx.form.photos?.length||0) < ctx.photosPlanState.max"
|
||||
type="button"
|
||||
class="m-amber"
|
||||
@click="ctx.showInputsAndAddPhoto()"
|
||||
>+ Add photo</button>
|
||||
</p>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p v-if="!ctx.form.photos?.length && ctx.photosPlanState.emptyHint" class="m-muted">{{ ctx.photosPlanState.emptyHint }}</p>
|
||||
<Studio2AssetSlot
|
||||
v-for="(card, index) in ctx.form.photos"
|
||||
:key="'m-photo-'+index+'-'+card.stillId"
|
||||
:asset="ctx.stillById(card.stillId)"
|
||||
:hidden="false"
|
||||
:role="card.role"
|
||||
:role-options="ctx.photoRoleOptions"
|
||||
@pick="ctx.setPicker('photo:'+index)"
|
||||
@remove="ctx.removePhoto(index)"
|
||||
@mention="ctx.mentionPhoto(index)"
|
||||
@update:role="ctx.setPhotoRole(index, $event)"
|
||||
/>
|
||||
<button v-if="(ctx.form.photos?.length||0) < ctx.photosPlanState.max" type="button" class="m-amber" @click="ctx.addPhoto">+ Add photo</button>
|
||||
<p v-if="ctx.photoRoleWarning" class="m-hint">{{ ctx.photoRoleWarning }}</p>
|
||||
</template>
|
||||
<template v-if="ctx.showIdentityLocks">
|
||||
<label class="m-check"><input v-model="ctx.form.lockFace" type="checkbox"> Lock face</label>
|
||||
<label class="m-check"><input v-model="ctx.form.lockOutfit" type="checkbox"> Lock outfit</label>
|
||||
@@ -421,12 +452,20 @@ watch(() => props.ctx.form.mode, () => { sheet.value = '' })
|
||||
left: 8px;
|
||||
z-index: 5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.m-stage-chrome > * { pointer-events: auto; }
|
||||
.m-stage-chrome-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
.m-stage-chrome-top > *,
|
||||
.m-stage-actions {
|
||||
pointer-events: auto;
|
||||
}
|
||||
.m-library {
|
||||
display: inline-flex;
|
||||
min-height: 48px;
|
||||
@@ -454,6 +493,23 @@ watch(() => props.ctx.form.mode, () => { sheet.value = '' })
|
||||
border-radius: 8px;
|
||||
background: #000a;
|
||||
}
|
||||
.m-stage-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
max-width: calc(100% - 56px);
|
||||
}
|
||||
.m-stage-actions button {
|
||||
min-height: 44px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
background: #000a;
|
||||
color: var(--text);
|
||||
padding: 0 10px;
|
||||
font: inherit;
|
||||
font-size: 12px;
|
||||
}
|
||||
.m-stage-actions .m-danger { color: #fca5a5; }
|
||||
.m-nav {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
@@ -472,6 +528,7 @@ watch(() => props.ctx.form.mode, () => { sheet.value = '' })
|
||||
}
|
||||
.m-nav-prev { left: 8px; }
|
||||
.m-nav-next { right: 8px; }
|
||||
.m-photos-head { margin-bottom: 8px; }
|
||||
.m-dock {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr) 120px;
|
||||
|
||||
Reference in New Issue
Block a user