Fix bench draft structuredClone 500 and Prompt Builder button contrast.
Draft snapshots use plain JSON of picked fields with restore try/catch that clears bad storage; Prompt Builder actions use amber primary/secondary styles with 44px tap targets.
This commit is contained in:
+127
-40
@@ -520,6 +520,58 @@ function defaultEngineLook(engine:string):EngineLook{
|
|||||||
if(engine==='qwen21') return {steps:25,cfg:1,aspect:'auto',seed:null,seedMode:'random',loraStack:[]}
|
if(engine==='qwen21') return {steps:25,cfg:1,aspect:'auto',seed:null,seedMode:'random',loraStack:[]}
|
||||||
return {steps:24,cfg:4,aspect:'auto',seed:null,seedMode:'random',loraStack:[]}
|
return {steps:24,cfg:4,aspect:'auto',seed:null,seedMode:'random',loraStack:[]}
|
||||||
}
|
}
|
||||||
|
/** Plain JSON snapshot only — never structuredClone Vue proxies / Files. */
|
||||||
|
function plainJson<T>(value:unknown, fallback:T):T{
|
||||||
|
try{return JSON.parse(JSON.stringify(value)) as T}catch{return fallback}
|
||||||
|
}
|
||||||
|
function plainLoraStack(stack:unknown){
|
||||||
|
if(!Array.isArray(stack)) return [] as any[]
|
||||||
|
return stack.map((item:any)=>{
|
||||||
|
if(!item || typeof item!=='object') return null
|
||||||
|
const name=String(item.name||item.filename||item.lora||'').trim()
|
||||||
|
if(!name) return null
|
||||||
|
const out:any={name}
|
||||||
|
if(item.strength!=null && Number.isFinite(Number(item.strength))) out.strength=Number(item.strength)
|
||||||
|
if(item.strengthModel!=null && Number.isFinite(Number(item.strengthModel))) out.strengthModel=Number(item.strengthModel)
|
||||||
|
if(item.strengthClip!=null && Number.isFinite(Number(item.strengthClip))) out.strengthClip=Number(item.strengthClip)
|
||||||
|
if(item.clipStrength!=null && Number.isFinite(Number(item.clipStrength))) out.clipStrength=Number(item.clipStrength)
|
||||||
|
return out
|
||||||
|
}).filter(Boolean)
|
||||||
|
}
|
||||||
|
function plainPromptSections(sections:any){
|
||||||
|
const src=sections&&typeof sections==='object'?sections:{}
|
||||||
|
return {
|
||||||
|
action:String(src.action||''),
|
||||||
|
camera:String(src.camera||''),
|
||||||
|
soundscape:String(src.soundscape||''),
|
||||||
|
music:String(src.music||''),
|
||||||
|
locks:String(src.locks||''),
|
||||||
|
cameraBeats:plainJson(src.cameraBeats||[], [] as any[]),
|
||||||
|
soundscapeChips:Array.isArray(src.soundscapeChips)?src.soundscapeChips.map((c:any)=>String(c||'')).filter(Boolean):[],
|
||||||
|
soundscapeLevel:String(src.soundscapeLevel||'normal'),
|
||||||
|
musicChip:String(src.musicChip||'N/A'),
|
||||||
|
dialogue:plainJson(src.dialogue||{mode:'none',line:''}, {mode:'none',line:''})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function plainEngineSamplingMap(){
|
||||||
|
const out:Record<string,EngineLook>={}
|
||||||
|
for(const key of ['flux','krea','qwen21'] as const){
|
||||||
|
const row=engineSampling[key]||defaultEngineLook(key)
|
||||||
|
out[key]={
|
||||||
|
steps:Number(row.steps)||defaultEngineLook(key).steps,
|
||||||
|
cfg:Number(row.cfg)||defaultEngineLook(key).cfg,
|
||||||
|
aspect:String(row.aspect||'auto'),
|
||||||
|
seed:row.seed==null || row.seed==='' ? null : Number(row.seed),
|
||||||
|
seedMode:row.seedMode==='locked'?'locked':'random',
|
||||||
|
loraStack:plainLoraStack(row.loraStack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
function clearDraftStores(){
|
||||||
|
try{localStorage.removeItem(BENCH_DRAFT_KEY)}catch{/* ignore */}
|
||||||
|
try{sessionStorage.removeItem(BENCH_DRAFT_SESSION_KEY)}catch{/* ignore */}
|
||||||
|
}
|
||||||
function readStoredNegatives(){
|
function readStoredNegatives(){
|
||||||
if(!import.meta.client)return [...defaultNegatives]
|
if(!import.meta.client)return [...defaultNegatives]
|
||||||
try{
|
try{
|
||||||
@@ -550,36 +602,64 @@ function writeStoredTurbo(on:boolean){
|
|||||||
try{localStorage.setItem(TURBO_STORAGE_KEY,on?'1':'0')}catch{/* ignore */}
|
try{localStorage.setItem(TURBO_STORAGE_KEY,on?'1':'0')}catch{/* ignore */}
|
||||||
}
|
}
|
||||||
function benchDraftPayload(){
|
function benchDraftPayload(){
|
||||||
if(['flux','krea','qwen21'].includes(form.engine)) rememberEngineSampling(form.engine)
|
try{
|
||||||
return {
|
if(['flux','krea','qwen21'].includes(form.engine)) rememberEngineSampling(form.engine)
|
||||||
v:2,
|
const styles=form.imageStyles||{positive:[],negative:[]}
|
||||||
mode:form.mode,
|
return {
|
||||||
engine:form.engine,
|
v:2,
|
||||||
folderId:form.folderId,
|
mode:String(form.mode||'generate'),
|
||||||
enhancePrompt:!!form.enhancePrompt,
|
engine:String(form.engine||'flux'),
|
||||||
turbo:!!form.turbo,
|
folderId:String(form.folderId||''),
|
||||||
lockFace:!!form.lockFace,
|
enhancePrompt:!!form.enhancePrompt,
|
||||||
lockOutfit:!!form.lockOutfit,
|
turbo:!!form.turbo,
|
||||||
promptSections:structuredClone(form.promptSections||{}),
|
lockFace:!!form.lockFace,
|
||||||
photos:(form.photos||[]).filter((p:any)=>p?.stillId).map((p:any)=>({stillId:p.stillId,role:p.role})),
|
lockOutfit:!!form.lockOutfit,
|
||||||
imageStyles:structuredClone(form.imageStyles||{positive:[],negative:[]}),
|
promptSections:plainPromptSections(form.promptSections),
|
||||||
settings:{
|
photos:(form.photos||[])
|
||||||
aspect:form.settings?.aspect||'auto',
|
.filter((p:any)=>p && typeof p.stillId==='string' && p.stillId)
|
||||||
seed:form.settings?.seed ?? null,
|
.map((p:any)=>({stillId:String(p.stillId),role:String(p.role||'change')})),
|
||||||
seedMode:form.settings?.seedMode||'random',
|
imageStyles:{
|
||||||
steps:form.settings?.steps,
|
positive:Array.isArray(styles.positive)?styles.positive.map((s:any)=>String(s||'')).filter(Boolean):[],
|
||||||
cfg:form.settings?.cfg,
|
negative:Array.isArray(styles.negative)?styles.negative.map((s:any)=>String(s||'')).filter(Boolean):[]
|
||||||
duration:form.settings?.duration,
|
},
|
||||||
fps:form.settings?.fps,
|
settings:{
|
||||||
loraStack:structuredClone(form.settings?.loraStack||[])
|
aspect:String(form.settings?.aspect||'auto'),
|
||||||
},
|
seed:form.settings?.seed==null || form.settings?.seed==='' ? null : Number(form.settings.seed),
|
||||||
engineSampling:structuredClone(engineSampling),
|
seedMode:form.settings?.seedMode==='locked'?'locked':'random',
|
||||||
batchMode:!!batchMode.value,
|
steps:Number(form.settings?.steps)||24,
|
||||||
eyeOpen:!!eyeOpen.value,
|
cfg:Number(form.settings?.cfg)||4,
|
||||||
hideInputs:!!hideInputs.value,
|
duration:Number(form.settings?.duration)||5,
|
||||||
queueCollapsed:!!queueCollapsed.value,
|
fps:Number(form.settings?.fps)||24,
|
||||||
selectedId:selected.value?.id||'',
|
loraStack:plainLoraStack(form.settings?.loraStack)
|
||||||
music:structuredClone({tags:music.tags,lyrics:music.lyrics,duration:music.duration,seed:music.seed,name:music.name})
|
},
|
||||||
|
engineSampling:plainEngineSamplingMap(),
|
||||||
|
batchMode:!!batchMode.value,
|
||||||
|
eyeOpen:!!eyeOpen.value,
|
||||||
|
hideInputs:!!hideInputs.value,
|
||||||
|
queueCollapsed:!!queueCollapsed.value,
|
||||||
|
selectedId:typeof selected.value?.id==='string'?selected.value.id:'',
|
||||||
|
music:{
|
||||||
|
tags:String(music.tags||''),
|
||||||
|
lyrics:String(music.lyrics||''),
|
||||||
|
duration:Number(music.duration)||30,
|
||||||
|
seed:String(music.seed||''),
|
||||||
|
name:String(music.name||'')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch{
|
||||||
|
return {
|
||||||
|
v:2,
|
||||||
|
mode:String(form.mode||'generate'),
|
||||||
|
engine:String(form.engine||'flux'),
|
||||||
|
folderId:String(form.folderId||''),
|
||||||
|
promptSections:{action:String(form.promptSections?.action||'')},
|
||||||
|
engineSampling:plainEngineSamplingMap(),
|
||||||
|
settings:{
|
||||||
|
aspect:String(form.settings?.aspect||'auto'),
|
||||||
|
steps:Number(form.settings?.steps)||24,
|
||||||
|
cfg:Number(form.settings?.cfg)||4
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function writeDraftStores(payload:string){
|
function writeDraftStores(payload:string){
|
||||||
@@ -609,18 +689,18 @@ function mergeEngineLook(row:any, fallback:EngineLook):EngineLook{
|
|||||||
aspect:typeof row?.aspect==='string' && row.aspect ? row.aspect : fallback.aspect,
|
aspect:typeof row?.aspect==='string' && row.aspect ? row.aspect : fallback.aspect,
|
||||||
seed:row?.seed==null || row?.seed==='' ? null : Number(row.seed),
|
seed:row?.seed==null || row?.seed==='' ? null : Number(row.seed),
|
||||||
seedMode:row?.seedMode==='locked'?'locked':'random',
|
seedMode:row?.seedMode==='locked'?'locked':'random',
|
||||||
loraStack:Array.isArray(row?.loraStack)?structuredClone(row.loraStack):structuredClone(fallback.loraStack)
|
loraStack:plainLoraStack(row?.loraStack ?? fallback.loraStack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function restoreBenchDraft(){
|
function restoreBenchDraft(){
|
||||||
if(!import.meta.client)return
|
if(!import.meta.client)return
|
||||||
const raw=readDraftRaw()
|
const raw=readDraftRaw()
|
||||||
if(!raw)return
|
if(!raw)return
|
||||||
let draft:any
|
|
||||||
try{draft=JSON.parse(raw)}catch{return}
|
|
||||||
if(!draft|| (draft.v!==1 && draft.v!==2))return
|
|
||||||
restoringDraft=true
|
restoringDraft=true
|
||||||
try{
|
try{
|
||||||
|
let draft:any
|
||||||
|
try{draft=JSON.parse(raw)}catch{clearDraftStores();return}
|
||||||
|
if(!draft|| (draft.v!==1 && draft.v!==2)){clearDraftStores();return}
|
||||||
if(draft.engineSampling && typeof draft.engineSampling==='object'){
|
if(draft.engineSampling && typeof draft.engineSampling==='object'){
|
||||||
for(const key of ['flux','krea','qwen21'] as const){
|
for(const key of ['flux','krea','qwen21'] as const){
|
||||||
const row=draft.engineSampling[key]
|
const row=draft.engineSampling[key]
|
||||||
@@ -636,8 +716,13 @@ function restoreBenchDraft(){
|
|||||||
if(draft.lockFace!=null)form.lockFace=!!draft.lockFace
|
if(draft.lockFace!=null)form.lockFace=!!draft.lockFace
|
||||||
if(draft.lockOutfit!=null)form.lockOutfit=!!draft.lockOutfit
|
if(draft.lockOutfit!=null)form.lockOutfit=!!draft.lockOutfit
|
||||||
if(draft.promptSections)form.promptSections=sectionsFrom(draft.promptSections)
|
if(draft.promptSections)form.promptSections=sectionsFrom(draft.promptSections)
|
||||||
if(Array.isArray(draft.photos))form.photos=draft.photos.filter((p:any)=>p?.stillId).map((p:any)=>({stillId:String(p.stillId),role:String(p.role||'change')}))
|
if(Array.isArray(draft.photos))form.photos=draft.photos
|
||||||
if(draft.imageStyles)form.imageStyles={positive:draft.imageStyles.positive||[],negative:draft.imageStyles.negative||[]}
|
.filter((p:any)=>p && typeof p.stillId==='string' && p.stillId)
|
||||||
|
.map((p:any)=>({stillId:String(p.stillId),role:String(p.role||'change')}))
|
||||||
|
if(draft.imageStyles)form.imageStyles={
|
||||||
|
positive:Array.isArray(draft.imageStyles.positive)?draft.imageStyles.positive.map((s:any)=>String(s||'')).filter(Boolean):[],
|
||||||
|
negative:Array.isArray(draft.imageStyles.negative)?draft.imageStyles.negative.map((s:any)=>String(s||'')).filter(Boolean):[]
|
||||||
|
}
|
||||||
if(draft.settings){
|
if(draft.settings){
|
||||||
Object.assign(form.settings,{
|
Object.assign(form.settings,{
|
||||||
aspect:draft.settings.aspect||form.settings.aspect,
|
aspect:draft.settings.aspect||form.settings.aspect,
|
||||||
@@ -647,7 +732,7 @@ function restoreBenchDraft(){
|
|||||||
cfg:draft.settings.cfg ?? form.settings.cfg,
|
cfg:draft.settings.cfg ?? form.settings.cfg,
|
||||||
duration:draft.settings.duration ?? form.settings.duration,
|
duration:draft.settings.duration ?? form.settings.duration,
|
||||||
fps:draft.settings.fps ?? form.settings.fps,
|
fps:draft.settings.fps ?? form.settings.fps,
|
||||||
loraStack:Array.isArray(draft.settings.loraStack)?draft.settings.loraStack:form.settings.loraStack
|
loraStack:Array.isArray(draft.settings.loraStack)?plainLoraStack(draft.settings.loraStack):form.settings.loraStack
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if(['flux','krea','qwen21'].includes(form.engine)) applyEngineSampling(form.engine)
|
if(['flux','krea','qwen21'].includes(form.engine)) applyEngineSampling(form.engine)
|
||||||
@@ -663,7 +748,9 @@ function restoreBenchDraft(){
|
|||||||
if(draft.music.name!=null)music.name=String(draft.music.name)
|
if(draft.music.name!=null)music.name=String(draft.music.name)
|
||||||
}
|
}
|
||||||
syncPhotosBindings()
|
syncPhotosBindings()
|
||||||
} finally {
|
}catch{
|
||||||
|
clearDraftStores()
|
||||||
|
}finally{
|
||||||
restoringDraft=false
|
restoringDraft=false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -746,7 +833,7 @@ function rememberEngineSampling(engine:string){
|
|||||||
aspect:String(form.settings.aspect||fallback.aspect),
|
aspect:String(form.settings.aspect||fallback.aspect),
|
||||||
seed:form.settings.seed==null || form.settings.seed==='' ? null : Number(form.settings.seed),
|
seed:form.settings.seed==null || form.settings.seed==='' ? null : Number(form.settings.seed),
|
||||||
seedMode:form.settings.seedMode==='locked'?'locked':'random',
|
seedMode:form.settings.seedMode==='locked'?'locked':'random',
|
||||||
loraStack:Array.isArray(form.settings.loraStack)?structuredClone(form.settings.loraStack):[]
|
loraStack:plainLoraStack(form.settings.loraStack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function applyEngineSampling(engine:string){
|
function applyEngineSampling(engine:string){
|
||||||
@@ -758,7 +845,7 @@ function applyEngineSampling(engine:string){
|
|||||||
form.settings.aspect=saved.aspect || form.settings.aspect || 'auto'
|
form.settings.aspect=saved.aspect || form.settings.aspect || 'auto'
|
||||||
form.settings.seed=saved.seed
|
form.settings.seed=saved.seed
|
||||||
form.settings.seedMode=saved.seedMode || 'random'
|
form.settings.seedMode=saved.seedMode || 'random'
|
||||||
form.settings.loraStack=Array.isArray(saved.loraStack)?structuredClone(saved.loraStack):[]
|
form.settings.loraStack=plainLoraStack(saved.loraStack)
|
||||||
}
|
}
|
||||||
function clearPrompt(){
|
function clearPrompt(){
|
||||||
if(form.promptSections) form.promptSections.action=''
|
if(form.promptSections) form.promptSections.action=''
|
||||||
|
|||||||
+876
-876
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user