Restore pre-text and post-text with Use as input and Details.
Library items already stored those fields, but Details showed one blob and Use as input left the form's empty pre/post in place. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+11
-15
@@ -1706,8 +1706,8 @@
|
|||||||
>
|
>
|
||||||
<p v-else class="min-w-0 flex-1 truncate text-sm font-medium">{{ collectionTitle(entry.group) }}</p>
|
<p v-else class="min-w-0 flex-1 truncate text-sm font-medium">{{ collectionTitle(entry.group) }}</p>
|
||||||
<PromptPreviewTip
|
<PromptPreviewTip
|
||||||
v-if="familyScript(entry.group.parts)"
|
v-if="formatPromptParts(entry.group.head, familyScript(entry.group.parts))"
|
||||||
:text="familyScript(entry.group.parts)"
|
:text="formatPromptParts(entry.group.head, familyScript(entry.group.parts))"
|
||||||
:aria-label="'Copy prompt for ' + collectionTitle(entry.group)"
|
:aria-label="'Copy prompt for ' + collectionTitle(entry.group)"
|
||||||
@copy="copyPrompt"
|
@copy="copyPrompt"
|
||||||
/>
|
/>
|
||||||
@@ -1799,8 +1799,8 @@
|
|||||||
>
|
>
|
||||||
<p v-else class="min-w-0 flex-1 truncate text-sm font-medium">{{ item.name || item.prompt }}</p>
|
<p v-else class="min-w-0 flex-1 truncate text-sm font-medium">{{ item.name || item.prompt }}</p>
|
||||||
<PromptPreviewTip
|
<PromptPreviewTip
|
||||||
v-if="item.prompt"
|
v-if="formatPromptParts(item)"
|
||||||
:text="item.prompt"
|
:text="formatPromptParts(item)"
|
||||||
:aria-label="'Copy prompt for ' + (item.name || 'this clip')"
|
:aria-label="'Copy prompt for ' + (item.name || 'this clip')"
|
||||||
@copy="copyPrompt"
|
@copy="copyPrompt"
|
||||||
/>
|
/>
|
||||||
@@ -1906,8 +1906,8 @@
|
|||||||
>
|
>
|
||||||
<p v-else class="min-w-0 flex-1 truncate text-sm font-medium">{{ stillCollectionTitle(entry.stillGroup) }}</p>
|
<p v-else class="min-w-0 flex-1 truncate text-sm font-medium">{{ stillCollectionTitle(entry.stillGroup) }}</p>
|
||||||
<PromptPreviewTip
|
<PromptPreviewTip
|
||||||
v-if="stillFamilyScript(entry.stillGroup.parts)"
|
v-if="formatPromptParts(entry.stillGroup.head, stillFamilyScript(entry.stillGroup.parts))"
|
||||||
:text="stillFamilyScript(entry.stillGroup.parts)"
|
:text="formatPromptParts(entry.stillGroup.head, stillFamilyScript(entry.stillGroup.parts))"
|
||||||
:aria-label="'Copy prompt for ' + stillCollectionTitle(entry.stillGroup)"
|
:aria-label="'Copy prompt for ' + stillCollectionTitle(entry.stillGroup)"
|
||||||
@copy="copyPrompt"
|
@copy="copyPrompt"
|
||||||
/>
|
/>
|
||||||
@@ -1992,8 +1992,8 @@
|
|||||||
>
|
>
|
||||||
<p v-else class="min-w-0 flex-1 truncate text-sm font-medium">{{ stillTitle(item) }}</p>
|
<p v-else class="min-w-0 flex-1 truncate text-sm font-medium">{{ stillTitle(item) }}</p>
|
||||||
<PromptPreviewTip
|
<PromptPreviewTip
|
||||||
v-if="item.prompt"
|
v-if="formatPromptParts(item)"
|
||||||
:text="item.prompt"
|
:text="formatPromptParts(item)"
|
||||||
:aria-label="'Copy prompt for ' + stillTitle(item)"
|
:aria-label="'Copy prompt for ' + stillTitle(item)"
|
||||||
@copy="copyPrompt"
|
@copy="copyPrompt"
|
||||||
/>
|
/>
|
||||||
@@ -2155,7 +2155,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { composePromptParts, restorePromptParts } from '~/utils/promptParts'
|
import { composePromptParts, formatPromptParts, restorePromptParts } from '~/utils/promptParts'
|
||||||
import { parseEditPasses, looksLikeShotScript } from '~/utils/parseRecommend'
|
import { parseEditPasses, looksLikeShotScript } from '~/utils/parseRecommend'
|
||||||
import { parseImageBatchScript, parseShotScript } from '~/utils/parseShots'
|
import { parseImageBatchScript, parseShotScript } from '~/utils/parseShots'
|
||||||
import type { DirectorScript } from '~/utils/directorScripts'
|
import type { DirectorScript } from '~/utils/directorScripts'
|
||||||
@@ -4120,12 +4120,8 @@ function insertKeepPrompt(item: KeepPrompt) {
|
|||||||
function applyPromptRestore(saved: string, stored?: { prompt?: string; promptPre?: string; promptPost?: string } | null) {
|
function applyPromptRestore(saved: string, stored?: { prompt?: string; promptPre?: string; promptPost?: string } | null) {
|
||||||
const parts = restorePromptParts(saved, {
|
const parts = restorePromptParts(saved, {
|
||||||
pre: stored?.promptPre,
|
pre: stored?.promptPre,
|
||||||
prompt: stored?.prompt ?? saved,
|
prompt: saved,
|
||||||
post: stored?.promptPost
|
post: stored?.promptPost
|
||||||
}, {
|
|
||||||
pre: promptPre.value,
|
|
||||||
prompt: prompt.value,
|
|
||||||
post: promptPost.value
|
|
||||||
})
|
})
|
||||||
promptPre.value = parts.pre
|
promptPre.value = parts.pre
|
||||||
prompt.value = parts.prompt
|
prompt.value = parts.prompt
|
||||||
@@ -5902,7 +5898,7 @@ function applyStillSettings(still: LibraryStill) {
|
|||||||
const settings = still.settings
|
const settings = still.settings
|
||||||
folderId.value = still.folderId
|
folderId.value = still.folderId
|
||||||
browseFolderId.value = still.folderId
|
browseFolderId.value = still.folderId
|
||||||
if (still.prompt || still.promptPre || still.promptPost) applyPromptRestore(still.prompt || '', still)
|
applyPromptRestore(still.prompt || '', still)
|
||||||
if (dest === 'imagev2') {
|
if (dest === 'imagev2') {
|
||||||
studioMode.value = 'editv2'
|
studioMode.value = 'editv2'
|
||||||
outputFocus.value = 'edit'
|
outputFocus.value = 'edit'
|
||||||
|
|||||||
+3
-2
@@ -368,6 +368,7 @@ import {
|
|||||||
type LibraryStill
|
type LibraryStill
|
||||||
} from '~/utils/libraryBrowse'
|
} from '~/utils/libraryBrowse'
|
||||||
import { isXaigenStudio } from '~/utils/videoModels'
|
import { isXaigenStudio } from '~/utils/videoModels'
|
||||||
|
import { formatPromptParts } from '~/utils/promptParts'
|
||||||
|
|
||||||
const CARD_MIN = 156
|
const CARD_MIN = 156
|
||||||
const GAP = 10
|
const GAP = 10
|
||||||
@@ -507,10 +508,10 @@ const focusedNavIndex = computed(() => {
|
|||||||
const detailPrompt = computed(() => {
|
const detailPrompt = computed(() => {
|
||||||
if (focused.value?.kind === 'clip' && focused.value.group) {
|
if (focused.value?.kind === 'clip' && focused.value.group) {
|
||||||
const item = focused.value.group.parts.find(part => part.id === focusedPartId.value) || focused.value.group.head
|
const item = focused.value.group.parts.find(part => part.id === focusedPartId.value) || focused.value.group.head
|
||||||
return item.prompt || ''
|
return formatPromptParts(item)
|
||||||
}
|
}
|
||||||
const still = focused.value?.stillGroup?.parts.find(part => part.id === focusedPartId.value) || focused.value?.stillGroup?.head
|
const still = focused.value?.stillGroup?.parts.find(part => part.id === focusedPartId.value) || focused.value?.stillGroup?.head
|
||||||
return still?.prompt || ''
|
return formatPromptParts(still)
|
||||||
})
|
})
|
||||||
const detailMeta = computed(() => {
|
const detailMeta = computed(() => {
|
||||||
const entry = focused.value
|
const entry = focused.value
|
||||||
|
|||||||
@@ -1312,7 +1312,10 @@ export async function keepStillAsInput(owner: string, id: string) {
|
|||||||
height: still.height,
|
height: still.height,
|
||||||
hideInput: still.hideInput,
|
hideInput: still.hideInput,
|
||||||
role: 'input',
|
role: 'input',
|
||||||
name
|
name,
|
||||||
|
prompt: still.prompt,
|
||||||
|
promptPre: still.promptPre,
|
||||||
|
promptPost: still.promptPost
|
||||||
})
|
})
|
||||||
if (!saved) throw createError({ statusCode: 400, statusMessage: 'Could not save that still as input' })
|
if (!saved) throw createError({ statusCode: 400, statusMessage: 'Could not save that still as input' })
|
||||||
return saved
|
return saved
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ export type LibraryStill = {
|
|||||||
role?: 'input' | 'output'
|
role?: 'input' | 'output'
|
||||||
name?: string
|
name?: string
|
||||||
prompt?: string
|
prompt?: string
|
||||||
|
promptPre?: string
|
||||||
|
promptPost?: string
|
||||||
familyId?: string
|
familyId?: string
|
||||||
parentStillId?: string
|
parentStillId?: string
|
||||||
chainIndex?: number
|
chainIndex?: number
|
||||||
@@ -34,6 +36,8 @@ export type LibraryClip = {
|
|||||||
folderId: string
|
folderId: string
|
||||||
name?: string
|
name?: string
|
||||||
prompt: string
|
prompt: string
|
||||||
|
promptPre?: string
|
||||||
|
promptPost?: string
|
||||||
aspect: string
|
aspect: string
|
||||||
width: number
|
width: number
|
||||||
height: number
|
height: number
|
||||||
|
|||||||
@@ -33,6 +33,12 @@ export type StillGenerationSettings = {
|
|||||||
|
|
||||||
export type SettingsRow = { label: string; value: string }
|
export type SettingsRow = { label: string; value: string }
|
||||||
|
|
||||||
|
function pushPromptRows(rows: SettingsRow[], item: { prompt?: string; promptPre?: string; promptPost?: string }) {
|
||||||
|
if (item.promptPre?.trim()) rows.push({ label: 'Pre-text', value: item.promptPre.trim() })
|
||||||
|
if (item.prompt?.trim()) rows.push({ label: 'Prompt', value: item.prompt.trim() })
|
||||||
|
if (item.promptPost?.trim()) rows.push({ label: 'Post-text', value: item.promptPost.trim() })
|
||||||
|
}
|
||||||
|
|
||||||
function finiteNumber(raw: unknown): number | undefined {
|
function finiteNumber(raw: unknown): number | undefined {
|
||||||
const value = Number(raw)
|
const value = Number(raw)
|
||||||
return Number.isFinite(value) ? value : undefined
|
return Number.isFinite(value) ? value : undefined
|
||||||
@@ -141,10 +147,10 @@ export function stillModeLabel(still: { filename?: string; settings?: StillGener
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stillSettingsRows(still: { prompt?: string; width?: number; height?: number; settings?: StillGenerationSettings | null }) {
|
export function stillSettingsRows(still: { prompt?: string; promptPre?: string; promptPost?: string; width?: number; height?: number; settings?: StillGenerationSettings | null }) {
|
||||||
const settings = still.settings
|
const settings = still.settings
|
||||||
const rows: SettingsRow[] = []
|
const rows: SettingsRow[] = []
|
||||||
if (still.prompt?.trim()) rows.push({ label: 'Prompt', value: still.prompt.trim() })
|
pushPromptRows(rows, still)
|
||||||
const mode = stillModeLabel(still)
|
const mode = stillModeLabel(still)
|
||||||
if (mode) rows.push({ label: 'Mode', value: mode })
|
if (mode) rows.push({ label: 'Mode', value: mode })
|
||||||
if (!settings) return rows
|
if (!settings) return rows
|
||||||
@@ -203,6 +209,8 @@ function videoWorkflowLabel(workflow?: string) {
|
|||||||
|
|
||||||
export function clipSettingsRows(clip: {
|
export function clipSettingsRows(clip: {
|
||||||
prompt?: string
|
prompt?: string
|
||||||
|
promptPre?: string
|
||||||
|
promptPost?: string
|
||||||
width?: number
|
width?: number
|
||||||
height?: number
|
height?: number
|
||||||
duration?: number
|
duration?: number
|
||||||
@@ -220,7 +228,7 @@ export function clipSettingsRows(clip: {
|
|||||||
loraStack?: LoraStackItem[]
|
loraStack?: LoraStackItem[]
|
||||||
}) {
|
}) {
|
||||||
const rows: SettingsRow[] = []
|
const rows: SettingsRow[] = []
|
||||||
if (clip.prompt?.trim()) rows.push({ label: 'Prompt', value: clip.prompt.trim() })
|
pushPromptRows(rows, clip)
|
||||||
const workflow = videoWorkflowLabel(clip.workflow)
|
const workflow = videoWorkflowLabel(clip.workflow)
|
||||||
if (workflow) rows.push({ label: 'Workflow', value: workflow })
|
if (workflow) rows.push({ label: 'Workflow', value: workflow })
|
||||||
if (clip.width && clip.height) rows.push({ label: 'Size', value: `${clip.width}×${clip.height}` })
|
if (clip.width && clip.height) rows.push({ label: 'Size', value: `${clip.width}×${clip.height}` })
|
||||||
|
|||||||
+22
-13
@@ -19,24 +19,33 @@ export function applyPromptParts(parts: PromptParts, middle: string) {
|
|||||||
return composePromptParts(parts.pre, middle, parts.post)
|
return composePromptParts(parts.pre, middle, parts.post)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function restorePromptParts(saved: string, stored?: Partial<PromptParts> | null, current?: Partial<PromptParts> | null): PromptParts {
|
function peelPromptWrappers(mid: string, pre: string, post: string) {
|
||||||
|
let next = sanitizePromptPart(mid)
|
||||||
|
if (pre && next.startsWith(pre)) next = next.slice(pre.length).replace(/^\n+/, '')
|
||||||
|
if (post && next.endsWith(post)) next = next.slice(0, Math.max(0, next.length - post.length)).replace(/\n+$/, '')
|
||||||
|
return next.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function restorePromptParts(saved: string, stored?: Partial<PromptParts> | null): PromptParts {
|
||||||
const pre = sanitizePromptPart(stored?.pre ?? '').trim()
|
const pre = sanitizePromptPart(stored?.pre ?? '').trim()
|
||||||
const post = sanitizePromptPart(stored?.post ?? '').trim()
|
const post = sanitizePromptPart(stored?.post ?? '').trim()
|
||||||
if (pre || post) {
|
|
||||||
return {
|
return {
|
||||||
pre,
|
pre,
|
||||||
prompt: sanitizePromptPart(stored?.prompt ?? saved).trim() || sanitizePromptPart(saved).trim(),
|
prompt: peelPromptWrappers(stored?.prompt ?? saved, pre, post),
|
||||||
post
|
post
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mid = sanitizePromptPart(stored?.prompt ?? saved)
|
|
||||||
const curPre = sanitizePromptPart(current?.pre || '').trim()
|
export function formatPromptParts(
|
||||||
const curPost = sanitizePromptPart(current?.post || '').trim()
|
stored?: { prompt?: string; promptPre?: string; promptPost?: string } | null,
|
||||||
if (curPre && mid.startsWith(curPre)) mid = mid.slice(curPre.length).replace(/^\n+/, '')
|
midOverride?: string
|
||||||
if (curPost && mid.endsWith(curPost)) mid = mid.slice(0, Math.max(0, mid.length - curPost.length)).replace(/\n+$/, '')
|
) {
|
||||||
return {
|
const pre = sanitizePromptPart(stored?.promptPre || '').trim()
|
||||||
pre: current?.pre || '',
|
const post = sanitizePromptPart(stored?.promptPost || '').trim()
|
||||||
prompt: mid.trim(),
|
const prompt = peelPromptWrappers(midOverride ?? stored?.prompt ?? '', pre, post)
|
||||||
post: current?.post || ''
|
const blocks: string[] = []
|
||||||
}
|
if (pre) blocks.push(`Pre-text\n${pre}`)
|
||||||
|
if (prompt) blocks.push(pre || post ? `Prompt\n${prompt}` : prompt)
|
||||||
|
if (post) blocks.push(`Post-text\n${post}`)
|
||||||
|
return blocks.join('\n\n')
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user