Files
pansy/web
steveandClaude Opus 4.8 2cde8a24f5
Build image / build-and-push (push) Successful in 8s
Address Gadfly review on #11 field editor
Fix the real bugs surfaced by the PR #30 adversarial review (duplicates
across models collapsed):

- Optimistic PATCH now bumps the cached row version so a second edit
  started before the first PATCH resolves sends the next version instead
  of re-sending a stale one and self-conflicting (spurious 409 +
  "updated elsewhere" toast + lost edit). Drop the per-PATCH onSettled
  refetch: onSuccess already writes the authoritative row and onError
  always rolls back, so the invalidate was a request storm during drags
  and a refetch race, with no drift benefit.
- Color picker committed a PATCH on every onChange (continuous during a
  native picker drag). Track the value locally and commit one PATCH on
  blur.
- Rotate read shiftKey from the pointerdown event, so toggling Shift
  mid-drag didn't switch snap/free. Pass the live pointermove event into
  the gesture callback and read shiftKey from it.
- Window pointer listeners had no unmount cleanup: deleting/deselecting
  an object mid-drag leaked listeners and could leave objectDragging
  stuck true (freezing pan). Track the active gesture's cleanup and run
  it on unmount.
- commitDim accepted 0/negative width/height (invalid geometry flashed
  into the optimistic cache before rollback) and fired a spurious 1cm
  PATCH on blur-without-edit from cm<->ft rounding drift. Guard
  width/height against the server minimum and compare at display
  precision first.

Perf:
- Split the z-order sort from the live-merge so a pointermove is an O(n)
  map, not an O(n log n) re-sort.
- Memoize the toEditorObject map so object identities are stable across
  renders and ObjectShape's memo holds.
- Snapshot the svg rect once per gesture instead of calling
  getBoundingClientRect (a layout reflow) on every pointermove.

Maintainability:
- Move per-kind default z-index into kinds.ts (single source of truth).
- Rename the ToastItem `toast` param so it stops shadowing the module's
  `toast` export.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01JdQpdYYsTgtkJBxbcpAszi
2026-07-18 21:01:00 -04:00
..