feat: add commands for clearing candidates and reusing candidate settings, update UI controls

This commit is contained in:
syntaxbullet
2026-07-11 11:23:25 +02:00
parent 556fd685a2
commit 1236b6dd2f
5 changed files with 85 additions and 3 deletions

View File

@@ -53,7 +53,6 @@ export function GenerateActionControls({ settings, generation, dispatch, workflo
}
function CandidatePicker({ generation, dispatch }: { generation: GenerationState; dispatch: AppStore["dispatch"] }) {
if (generation.candidates.length < 2) return null;
return (
<div className="subtle-scrollbar flex max-w-[min(28rem,calc(100vw-2rem))] items-center gap-1 overflow-x-auto rounded-full bg-white/[0.04] px-1.5 py-1 ring-1 ring-white/[0.05]" role="group" aria-label="Generation candidates">
{generation.candidates.map((candidate) => {
@@ -70,6 +69,15 @@ function CandidatePicker({ generation, dispatch }: { generation: GenerationState
</button>
);
})}
<button
type="button"
disabled={generation.candidates.length === 0}
className="h-9 shrink-0 rounded-full px-3 text-xs font-semibold text-white/55 transition hover:bg-white/10 hover:text-white disabled:pointer-events-none disabled:opacity-35"
title="Dismiss every candidate and reset comparison"
onClick={() => dispatch(commandIds.generationClearCandidates, undefined)}
>
Clear all
</button>
</div>
);
}
@@ -97,7 +105,9 @@ function CandidateControls({
return (
<div className="flex flex-wrap items-center justify-center gap-1 rounded-full bg-white/[0.04] px-2 py-1 ring-1 ring-white/[0.05]">
<CandidatePreview candidate={candidate} />
<span className="px-2 text-xs font-medium text-white/55">Seed {candidate.seed}</span>
<span className="px-2 text-xs font-medium text-white/55" title={`${candidate.settings.model} · ${candidate.mode}`}>
Seed {candidate.seed}
</span>
<CandidateCompareControls compareMode={compareMode} disabled={disabled} dispatch={dispatch} />
<CandidateButton disabled={disabled} label="Regenerate" title="Regenerate same mask and crop" onClick={() => rerun("Regenerate", candidate.settings)} />
<CandidateButton
@@ -108,6 +118,12 @@ function CandidateControls({
/>
<CandidateButton disabled={disabled} label="Reuse seed" title="Regenerate with the same seed" onClick={() => rerun("Reuse seed", { ...candidate.settings, seed: candidate.seed })} />
<CandidateButton disabled={disabled} label="New seed" title="Regenerate with a new seed" onClick={() => rerun("New seed", { ...candidate.settings, seed: -1 })} />
<CandidateButton
disabled={disabled}
label="Use settings"
title="Restore this candidate's prompt, model, generation settings, and resolved seed"
onClick={() => dispatch(commandIds.generationReuseCandidateSettings, { candidateId: candidate.id })}
/>
<CandidateButton disabled={disabled} label="Add as layer" title="Add candidate to the document as a layer" onClick={() => workflow.applyCandidateAsLayer(candidate.id)} />
<CandidateButton
disabled={disabled}
@@ -136,7 +152,7 @@ function CandidateControls({
}}
/>
<CandidateButton disabled={disabled} label="Dismiss" title="Remove this candidate" onClick={() => dispatch(commandIds.generationRemoveCandidate, { candidateId: candidate.id })} />
{settings.seed !== candidate.seed ? null : <span className="sr-only">Current settings reuse this seed</span>}
{settings.seed !== candidate.seed ? null : <span className="sr-only">Current settings use this candidate's resolved seed</span>}
</div>
);
}