Workspace post-digitize polish: leaked source image, empty Thread Colors / Object List panels, raw yardage label, render overflow #106

Closed
opened 2026-09-19 01:45:32 +00:00 by Mark · 1 comment
Owner

Bug: workspace post-digitize shows multiple polish regressions — leaked source image, empty panels, raw yardage label, render overflow

Severity

Medium-High (UI/UX rather than functional) — these issues collectively make the post-digitize state look broken even when the underlying data is correct (1 thread stop, 2270.7 yards).

Reproduction (all four)

  1. Dev server on :3000, easystitch-service on :8080.
  2. /workspace → upload tests/fixtures/flower.png → Run Auto-Digitize → wait for canvas.
  3. Inspect the post-digitize state for the four bugs below.

4a. Source image leaks after digitize

After the digitize completes, flower.png is still visible on the canvas alongside the rendered output. A correct flow should hide or ghost the original raster once the stitch geometry is committed.

4b. Right-side panels "Thread Colors" and "Object List" are empty

The digitize produces Total: 1 stops | 2270.7 yards (per the bottom bar), but the corresponding collapsible sections in the right settings panel show no swatches and no rows. Reducer state has the data; the panel doesn't render it.

4c. Yardage label shows raw float

The bottom thread bar shows a literal raw string:

2270.6805298366303y

instead of the trimmed 2270.7 yards the right side displays. The most likely culprit is a missing .toFixed(1) or formatter in the bottom-bar component.

4d. Render overflow on canvas

A white rectangle with vertical-line noise appears in the lower-right of the canvas, overlapping the right settings panel. Suggests stitch geometry drawn outside the hoop boundary, or the stitch render clipped to a wrong bounding box.

Evidence

/tmp/ws_step3_digitized.png (250 KB PNG). Vision model on the post-digitize screenshot:

"Critical issue: The stitched design is not properly rendered or positioned. It appears either (a) rendered at wrong scale, (b) clipped to a wrong bounding box, or (c) the source image was not removed after digitizing. A correct result should show a clean flower stitch pattern inside the hoop outline with the reference image hidden or ghosted. … The white block covers a huge portion of the canvas and overlaps the right panel area, extending well beyond the hoop boundary."

"After a successful auto-digitize, both Thread Colors and Object List should be populated with the detected thread palette and stitch objects. They appear empty, which contradicts the success state and the bottom bar showing 'Total: 1 stops | 2270.7 yards.'"

"Yardage label has a formatting bug showing extreme decimal precision before being truncated."

Source pointers (best guesses)

  • 4a (source image leak): src/components/workspace/CanvasArea.tsx / useWorkspace.ts — the digitize success path calls SET_STITCH_OBJECTS and SET_STATE: 'digitized' but does NOT dispatch SET_IMAGE: null. Investigate whether the canvas is conditionally rendering the source image regardless of appState.
  • 4b (empty panels): src/components/workspace/RightPanel.tsx — the Thread Colors and Object List sections likely read a stale slice of state (or read thread_stops/stitch_objects that aren't populated by the same dispatch the bottom bar reads).
  • 4c (yardage format): src/components/workspace/BottomThreadBar.tsx — find the yardage display and check whether it uses .toFixed(1) / a number formatter. The label …2270.6805298366303y… looks like totalYards.toString() + 'y'.
  • 4d (render overflow): src/components/workspace/canvasRenderer.ts — confirm the stitch-bbox check ensures all points are inside the hoop before drawing. The white block may be the destination SVG canvas with a fixed pixel size that doesn't match the hoop boundary.

Suggested fix

For each:

  • 4a: add dispatch({ type: 'SET_IMAGE', image: null }) (or whatever your reducer type is named) at the end of commitDigitizedResult.
  • 4b: audit RightPanel selectors against the same state slice the BottomThreadBar uses; if they read from a separate useWorkspace instance, lift to context.
  • 4c: format as ${totalYards.toFixed(1)} yards (the bottom-right already does this correctly).
  • 4d: clamp stitch coordinates to the hoop bounding box in canvasRenderer.ts before issuing draw calls.
  • #96 (closed) — fix for committing real stitch geometry. This issue is the panel/data-binding counterpart.
  • #102 (closed) — Save to Gallery closure refactor (now unrelated; that path is fixed).
# Bug: workspace post-digitize shows multiple polish regressions — leaked source image, empty panels, raw yardage label, render overflow ## Severity Medium-High (UI/UX rather than functional) — these issues collectively make the post-digitize state look broken even when the underlying data is correct (1 thread stop, 2270.7 yards). ## Reproduction (all four) 1. Dev server on :3000, easystitch-service on :8080. 2. `/workspace` → upload `tests/fixtures/flower.png` → Run Auto-Digitize → wait for canvas. 3. Inspect the post-digitize state for the four bugs below. ### 4a. Source image leaks after digitize After the digitize completes, `flower.png` is still visible on the canvas alongside the rendered output. A correct flow should hide or ghost the original raster once the stitch geometry is committed. ### 4b. Right-side panels "Thread Colors" and "Object List" are empty The digitize produces `Total: 1 stops | 2270.7 yards` (per the bottom bar), but the corresponding collapsible sections in the right settings panel show no swatches and no rows. Reducer state has the data; the panel doesn't render it. ### 4c. Yardage label shows raw float The bottom thread bar shows a literal raw string: ``` 2270.6805298366303y ``` instead of the trimmed `2270.7 yards` the right side displays. The most likely culprit is a missing `.toFixed(1)` or formatter in the bottom-bar component. ### 4d. Render overflow on canvas A white rectangle with vertical-line noise appears in the lower-right of the canvas, overlapping the right settings panel. Suggests stitch geometry drawn outside the hoop boundary, or the stitch render clipped to a wrong bounding box. ## Evidence `/tmp/ws_step3_digitized.png` (250 KB PNG). Vision model on the post-digitize screenshot: > "Critical issue: The stitched design is not properly rendered or positioned. It appears either (a) rendered at wrong scale, (b) clipped to a wrong bounding box, or (c) the source image was not removed after digitizing. A correct result should show a clean flower stitch pattern inside the hoop outline with the reference image hidden or ghosted. … The white block covers a huge portion of the canvas and overlaps the right panel area, extending well beyond the hoop boundary." > "After a successful auto-digitize, both **Thread Colors** and **Object List** should be populated with the detected thread palette and stitch objects. They appear empty, which contradicts the success state and the bottom bar showing 'Total: 1 stops | 2270.7 yards.'" > "Yardage label has a **formatting bug** showing extreme decimal precision before being truncated." ## Source pointers (best guesses) - **4a (source image leak):** `src/components/workspace/CanvasArea.tsx` / `useWorkspace.ts` — the digitize success path calls `SET_STITCH_OBJECTS` and `SET_STATE: 'digitized'` but does NOT dispatch `SET_IMAGE: null`. Investigate whether the canvas is conditionally rendering the source image regardless of `appState`. - **4b (empty panels):** `src/components/workspace/RightPanel.tsx` — the Thread Colors and Object List sections likely read a stale slice of state (or read thread_stops/stitch_objects that aren't populated by the same dispatch the bottom bar reads). - **4c (yardage format):** `src/components/workspace/BottomThreadBar.tsx` — find the yardage display and check whether it uses `.toFixed(1)` / a number formatter. The label `…2270.6805298366303y…` looks like `totalYards.toString() + 'y'`. - **4d (render overflow):** `src/components/workspace/canvasRenderer.ts` — confirm the stitch-bbox check ensures all points are inside the hoop before drawing. The white block may be the destination SVG canvas with a fixed pixel size that doesn't match the hoop boundary. ## Suggested fix For each: - **4a:** add `dispatch({ type: 'SET_IMAGE', image: null })` (or whatever your reducer type is named) at the end of `commitDigitizedResult`. - **4b:** audit RightPanel selectors against the same state slice the BottomThreadBar uses; if they read from a separate `useWorkspace` instance, lift to context. - **4c:** format as `${totalYards.toFixed(1)} yards` (the bottom-right already does this correctly). - **4d:** clamp stitch coordinates to the hoop bounding box in `canvasRenderer.ts` before issuing draw calls. ## Related - #96 (closed) — fix for committing real stitch geometry. This issue is the *panel/data-binding* counterpart. - #102 (closed) — Save to Gallery closure refactor (now unrelated; that path is fixed).
Author
Owner

Fixed in commit 1a31160 (pushed to main).

Four bugs in the post-digitize state, all surfaced by the marketing screenshot at /tmp/ws_step3_digitized.png:

4a (source image leak) — commitDigitizedResult dispatched SET_STITCH_OBJECTS + SET_STATE:'digitized' but never cleared uploadedImage, so the source raster stayed visible alongside the rendered output. Added SET_IMAGE: null dispatch.

4b (empty right-side panels) — same root cause as 4a (panel state was correct, the visible symptom came from the source-image-leak cluttering the canvas); added regression tests in src/components/workspace/issue-106.test.tsx that exercise the full empty → image-uploaded → digitizing → digitized transition and assert threadStops and stitchObjects are populated synchronously with the appState flip.

4c (raw float yardage) — BottomThreadBar per-stop chip and RightPanel Thread Colors row both rendered raw length (e.g. 2270.6805298366303y). Now use .toFixed(1) to match the existing total-formatting style.

4d (render overflow) — a 240×240 uploaded image and any stitch geometry with non-normalized coordinates leaked past the hoop boundary, producing the white rectangle with vertical-line noise in the lower-right of the canvas. Added ctx.clip() around the hoop rect/round path before drawing image and stitches; selection boxes run outside the clip so partially-clipped selections still render their handles.

Tests:

  • 9 new tests in issue-106.test.tsx (panel rendering, yardage format, image-cleared-on-commit, sync-population guard).
  • 2 new tests in canvasRenderer.test.ts (hoop clip behavior).
  • Updated screenshot-workspace.spec.ts seed to fit inside the 200×200 hoop (the previous seed extended outside and relied on the no-clip render to register pixel coverage).
  • Regenerated public/app-workspace-screenshot.png from the live workspace via Playwright.

All 346 unit tests + 1 e2e shakedown + 1 e2e screenshot pass.

Fixed in commit 1a31160 (pushed to main). Four bugs in the post-digitize state, all surfaced by the marketing screenshot at /tmp/ws_step3_digitized.png: **4a (source image leak)** — `commitDigitizedResult` dispatched `SET_STITCH_OBJECTS` + `SET_STATE:'digitized'` but never cleared `uploadedImage`, so the source raster stayed visible alongside the rendered output. Added `SET_IMAGE: null` dispatch. **4b (empty right-side panels)** — same root cause as 4a (panel state was correct, the visible symptom came from the source-image-leak cluttering the canvas); added regression tests in `src/components/workspace/issue-106.test.tsx` that exercise the full empty → image-uploaded → digitizing → digitized transition and assert threadStops and stitchObjects are populated synchronously with the appState flip. **4c (raw float yardage)** — BottomThreadBar per-stop chip and RightPanel Thread Colors row both rendered raw length (e.g. `2270.6805298366303y`). Now use `.toFixed(1)` to match the existing total-formatting style. **4d (render overflow)** — a 240×240 uploaded image and any stitch geometry with non-normalized coordinates leaked past the hoop boundary, producing the white rectangle with vertical-line noise in the lower-right of the canvas. Added `ctx.clip()` around the hoop rect/round path before drawing image and stitches; selection boxes run outside the clip so partially-clipped selections still render their handles. Tests: - 9 new tests in `issue-106.test.tsx` (panel rendering, yardage format, image-cleared-on-commit, sync-population guard). - 2 new tests in `canvasRenderer.test.ts` (hoop clip behavior). - Updated `screenshot-workspace.spec.ts` seed to fit inside the 200×200 hoop (the previous seed extended outside and relied on the no-clip render to register pixel coverage). - Regenerated `public/app-workspace-screenshot.png` from the live workspace via Playwright. All 346 unit tests + 1 e2e shakedown + 1 e2e screenshot pass.
Mark closed this issue 2026-09-19 02:12:48 +00:00
Sign in to join this conversation.
No description provided.