Skip to content

fix(inpaint): preview the picked candidate on the canvas - #33

Merged
provos merged 2 commits into
mainfrom
fix/candidate-preview
Sep 26, 2026
Merged

provos merged 2 commits into
mainfrom
fix/candidate-preview

Conversation

@provos

@provos provos commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Regression from the redesign's phase 3 (view modes).

Bug: picking an inpainting candidate didn't change the canvas. The slice and its painted mask stayed visible, so the candidates couldn't be compared.

Cause: selecting a candidate sets the server's display image (main) to that candidate. Since phase 3, main is only drawn in the Input and Parallax views. The Inpaint step opens on the Slice view, which draws the saved slice image client-side.

Fix:

  • The Slice and Composite views draw the picked candidate in place of its slice. It must be a candidate of the selected slice: lib/candidatePreview.ts.
  • The painted mask is hidden and ignores strokes while a candidate is previewed, so the filled-in area can be inspected. Clicking the candidate again returns to the mask, and the Inpaint panel says so.

Tests:

  • New UiDriver.visibleCanvasPixel(x, y) screenshots the canvas and samples what the user actually sees. It stays frontend-neutral.
  • The inpainting scenario picks candidate 0 and then 1 and checks the canvas shows each one's colours at a masked pixel. It fails without this fix (colour distance 220 vs ≤ 24).
  • Unit tests cover the Slice / Composite swap and the hidden mask.
  • Checked by hand with real SDXL "Fill" on the lighthouse: each picked candidate appears on the canvas.

vitest 417, svelte-check clean, e2e 46/46 locally.

🤖 Generated with Claude Code

Picking a candidate sets the server's display image, which since the
phase 3 view modes only shows in the Input and Parallax views; the
Inpaint step works in the Slice view, so the canvas kept showing the
slice and its painted mask. The Slice and Composite views now draw the
picked candidate in place of its slice, and the mask steps aside (and
takes no strokes) while a candidate is previewed.

The e2e inpainting scenario now reads the visible canvas after picking
each candidate (new UiDriver.visibleCanvasPixel); it fails without this
fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 26, 2026 19:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

There are two correctness issues found in the new candidate-preview hint logic and the new E2E pixel-sampling helper that can mislead users and/or introduce test flakiness.

Review effort: Lite
Findings: 2 Medium severity

Open (2)
What changed in this PR

This PR fixes a regression in the Svelte UI where selecting an inpainting candidate didn’t visually update the canvas in the Inpaint step (Slice view), preventing side-by-side candidate comparison. It introduces a shared “candidate preview” resolver so Slice/Composite views temporarily render the picked candidate in place of its slice and suppress the mask overlay while previewing.

Changes:

  • Add candidatePreview() helper and use it to swap candidate images into Slice and Composite canvas layers.
  • Hide/disable the painted mask overlay while a candidate is being previewed, and show an in-panel hint explaining the preview state.
  • Extend Playwright E2E coverage with a frontend-neutral UiDriver.visibleCanvasPixel() and assertions that candidate picks change the visible canvas pixels.
File Description
frontend/​src/​lib/​components/​upload/​InputImagePanel.test.ts Adds unit tests verifying slice/composite candidate swapping and mask hiding behavior.
frontend/​src/​lib/​components/​upload/​InputImagePanel.svelte Uses candidatePreview() to render the picked candidate in Slice/Composite in place of the slice asset.
frontend/​src/​lib/​components/​inpainting/​InpaintPanel.svelte Adds a UI hint when a candidate is selected to explain the preview/toggle behavior.
frontend/​src/​lib/​components/​canvas/​MaskCanvas.svelte Disables and hides the mask canvas while a candidate preview is active.
frontend/​src/​lib/​candidatePreview.ts New helper that determines whether/which candidate should be previewed for the selected slice.
e2e/​parallax-maker.spec.ts Adds E2E assertions that picking candidates changes what the user sees on the canvas.
e2e/​drivers/​types.ts Extends UiDriver with visibleCanvasPixel(x, y) for frontend-neutral pixel assertions.
e2e/​drivers/​svelte.ts Implements visibleCanvasPixel() by screenshot-sampling the rendered canvas stack.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread e2e/drivers/svelte.ts
Comment on lines +116 to +121
async visibleCanvasPixel(x: number, y: number): Promise<number[]> {
const [naturalWidth, naturalHeight] = await this.mainImage().evaluate((img: HTMLImageElement) => [
img.naturalWidth,
img.naturalHeight,
]);
const png = await this.canvasImage().screenshot();
Comment on lines +300 to +304
{#if selectedCandidate !== null && hasCandidates}
<p class="faint" data-testid="candidate-preview-hint">
Candidate {selectedCandidate + 1} is shown on the canvas. Click it again to go back to the mask.
</p>
{/if}
…in the pixel helper

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@provos
provos merged commit ba87b05 into main Sep 26, 2026
1 check passed
@provos
provos deleted the fix/candidate-preview branch September 26, 2026 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants