Conversation
…anvas (frappe#563) blockEmpty and delegatesSurface aside, the select tool never delegated surface pointerdowns to the whiteboard layer on a unified document, so the legacy whiteboard's own selectAt/clearSelection — which is what actually nulls editingCell and drops the selection on an empty-canvas click — never ran there. An open cell editor (and its toolbar) stayed on screen after clicking away, and the table itself stayed selected too. onSurfacePointerDown now clears the whiteboard selection itself for a plain press on a unified doc, mirroring that same miss-click clear, before routing the press onward.
Confidence Score: 4/5The mixed-selection drag regression should be fixed before merging because dragging a selected shared shape leaves co-selected whiteboard objects behind. The unconditional pre-routing clear removes whiteboard objects before the shared transform captures the complete mixed selection. Files Needing Attention: frontend/src/components/canvas/DiagramCanvas.vue Prompt To Fix All With AI### Issue 1
frontend/src/components/canvas/DiagramCanvas.vue:509
**Mixed selection drag breaks**
When a unified canvas has a shared shape and whiteboard object selected together, this clears the whiteboard selection before the shared move snapshots it, causing the shape to move while the co-selected whiteboard object stays behind.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "fix: table cell editor now closes on any..." | Re-trigger Greptile |
| !isAdditiveEvent(event) && | ||
| (whiteboardUi.state.editingCell || whiteboardUi.state.selection.length) | ||
| ) { | ||
| whiteboardUi.clearSelection() |
There was a problem hiding this comment.
When a unified canvas has a shared shape and whiteboard object selected together, this clears the whiteboard selection before the shared move snapshots it, causing the shape to move while the co-selected whiteboard object stays behind.
Knowledge Base Used:
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/src/components/canvas/DiagramCanvas.vue
Line: 509
Comment:
**Mixed selection drag breaks**
When a unified canvas has a shared shape and whiteboard object selected together, this clears the whiteboard selection before the shared move snapshots it, causing the shape to move while the co-selected whiteboard object stays behind.
**Knowledge Base Used:**
- [Canvas interaction and rendering](https://app.greptile.com/frappe/-/custom-context/knowledge-base/frappe/draw/-/docs/canvas-interaction-and-rendering.md)
- [Whiteboard and freeform content](https://app.greptile.com/frappe/-/custom-context/knowledge-base/frappe/draw/-/docs/whiteboard-and-freeform-content.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
vibhavkatre
left a comment
There was a problem hiding this comment.
The diagnosis is right and the placement in onSurfacePointerDown is right, but one claim in the new comment is not true, and because of it the fix leaves a table on the unified canvas with no way back.
The comment says the press can never be on the table:
A press that reaches this handler is always off the table (its own pointerdown intercepts and stops propagation for any in-bounds press)
WhiteboardTable.vue:185 only stops propagation once the table is already selected:
if (isAdditiveEvent(event) || !ui.isSelected('table', props.table.id)) return
event.stopPropagation()and the comment above it says so explicitly — "fall through to the surface selectAt". On a legacy whiteboard that fall-through lands in selectAt, which selects the table. On a unified document it lands here, and delegatesSurface() returns false for the select tool, so nothing selects it.
What that costs. Today the only route into a table on a unified canvas is editTableCellAt on double-click (DiagramCanvas.vue:632), which selects the table and opens a cell editor. Before this PR the selection then stuck around — the bug #563 reports — so the table stayed usable. After this PR, clicking empty canvas correctly deselects it, and a single click on the table no longer brings it back: the user has to double-click into a cell every time they want to move or restyle the table.
The fix is small and belongs in the same block. Export a selectWhiteboardAt(store, point) from useWhiteboardInteraction.js — whiteboardHitAt + SELECT_FN are already there, just not exported — and in onSurfacePointerDown select the object under the point if there is one, clear otherwise:
if (isUnified.value && editorUi.state.tool === 'select' && !isAdditiveEvent(event)) {
const point = selection.toLogicalFor(event, surface.value, viewport)
if (!selectWhiteboardAt(store, point)) whiteboardUi.clearSelection()
}That keeps everything #563 asks for, makes a table selectable by a plain click on the unified canvas the way it is on a legacy whiteboard, and — worth checking while you are there — probably closes the same gap for drawn lines and strokes, which have no per-object pointerdown at all.
On the test. The source-inspection pattern is the house one and fine here, but the first regex pins the exact whitespace and line breaks of the if, so reformatting the condition breaks a passing test for no reason. The three ordering assertions below it are the ones carrying real meaning; I would keep those and loosen the first to the parts that matter (isUnified, tool === 'select', !isAdditiveEvent, clearSelection).
Summary
editingCellset), clicking empty canvas — away from the table — did not commit/close the editor on a unified document (the type "Create" makes, i.e. most new diagrams). The toolbar and caret both stayed on screen.delegatesSurface()inDiagramCanvas.vueonly routes a select-tool press to the whiteboard layer for tools inWHITEBOARD_TOOLS—selectisn't one of them. So a plain empty-canvas click never reached the whiteboard's ownselectAt/beginMarquee, which is what actually nullseditingCelland empties the selection on a miss-click. (A legacy whiteboard-only document was unaffected — there the sole-registrant rule routes every tool to the whiteboard layer regardless.)onSurfacePointerDownnow clears the whiteboard selection itself (whiteboardUi.clearSelection()) for a plain, non-additive press on a unified doc with the select tool, before routing the press onward — mirroring the same miss-click clear the legacy path already does. This closes the editor (committing the in-progress text) and drops the table's own selection, so clicking away returns the canvas to its normal, nothing-selected state.Test plan
yarn vitest run— all 151 files / 1741 tests pass, including a newtableCellEditorClose.test.jspinning the wiring (source-inspection house pattern —DiagramCanvas.vuecan't mount in the node test env, same asstructuralConnector.test.js)yarn build— succeeds🤖 Generated with Claude Code