Keep the Extend panel put and name sibling clips as branches.

A finished job no longer closes a draft or jumps the page, and a second extend from the same part saves as p8b instead of another p8.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-02 15:16:30 -05:00
co-authored by Cursor
parent 4546aa5f61
commit 1be9bcb23f
9 changed files with 274 additions and 119 deletions
+7 -12
View File
@@ -18,6 +18,9 @@ import {
type KeepPromptKind,
type KeepPromptLists
} from '~/utils/keepPrompts'
import { familyBaseName, nextClipPartName, clipPartLabel } from '~/utils/libraryBrowse'
export { familyBaseName, nextClipPartName, clipPartLabel }
const scryptAsync = promisify(scrypt)
@@ -327,18 +330,10 @@ export function clipTitle(clip: Pick<LibraryClip, 'name' | 'prompt'>) {
return fromPrompt || 'Untitled clip'
}
export function familyBaseName(name: string) {
return String(name || '').trim().replace(/\s+p\d+$/i, '')
}
export function nextClipPartName(name: string) {
const trimmed = (name || '').trim()
if (!trimmed) return ''
const match = trimmed.match(/^(.*)\s+p(\d+)$/i)
const base = (match ? match[1] : trimmed).trim() || trimmed
const part = match ? Number(match[2]) + 1 : 2
const suffix = ` p${part}`
return `${base.slice(0, Math.max(1, 80 - suffix.length))}${suffix}`
export function nextFamilyPartName(owner: string, source: LibraryClip, extraNames: string[] = []) {
const catalog = readCatalog(owner)
const family = clipsInSameFamily(catalog, source)
return nextClipPartName(clipTitle(source), [...family.map(item => clipTitle(item)), ...extraNames])
}
export function sortFamilyParts(a: LibraryClip, b: LibraryClip) {