Canvas unification — Phase 2a: tool-keyed interaction dispatcher - #2
Merged
Merged
Conversation
…patcher
Refactor the surface-interaction seam from a single-slot ref to a layer-keyed
registry resolved by the active tool. Prep for the unified canvas, where several
type layers mount at once and would otherwise clobber one shared handler ref
(last-writer-wins). Legacy single-type documents register exactly ONE surface
layer, so the resolver returns it unchanged — behaviour is identical.
- useModeInteraction: the provided value is now a registry ref { layerKey:
handlers }. registerModeInteraction(ref, layerKey, handlers) installs/detaches
by key. New pure resolveModeHandlers(registry, activeTool): 0 registrants →
null; 1 → that one (legacy); several → whiteboard tools to the whiteboard
layer, else the other registrant.
- whiteboard + flowchart interaction composables register under 'whiteboard' /
'flowchart' keys and detach on unmount (flowchart gains the teardown it lacked).
- DiagramCanvas resolves handlers for the active tool in delegatesSurface() and
delegateSurfaceEvent() instead of reading a single ref.
Verified: build + 100 unit tests (adds 4 for resolveModeHandlers) + live-app
regression — pen-drawing on a whiteboard still commits a stroke through the
refactored seam (1 stroke, 11 points, no errors). Not user-visible on its own;
the unified rendering that lights up multiple registrants is the next step.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Confidence Score: 4/5Safe to merge; the registry logic is correct and the single-registrant (legacy) path is unchanged. The double DiagramCanvas.vue — the duplicated registry resolution in Reviews (1): Last reviewed commit: "Frappe Draw: canvas unification phase 2a..." | Re-trigger Greptile |
Comment on lines
371
to
+374
| function delegateSurfaceEvent(handlerName, event) { | ||
| if (!delegatesSurface()) return false | ||
| const handler = modeInteraction.value[handlerName] | ||
| const handlers = activeModeHandlers() | ||
| const handler = handlers && handlers[handlerName] |
There was a problem hiding this comment.
delegateSurfaceEvent calls delegatesSurface() (which already runs activeModeHandlers()) and then calls activeModeHandlers() a second time. On pointermove this doubles the registry resolution on every frame.
Suggested change
| function delegateSurfaceEvent(handlerName, event) { | |
| if (!delegatesSurface()) return false | |
| const handler = modeInteraction.value[handlerName] | |
| const handlers = activeModeHandlers() | |
| const handler = handlers && handlers[handlerName] | |
| function delegateSurfaceEvent(handlerName, event) { | |
| const handlers = activeModeHandlers() | |
| if (!modeStrategy.value.handlesSurfaceInteraction || handlers == null) return false | |
| const handler = handlers[handlerName] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Phase 2a of the canvas unification. Converts the surface-interaction seam from a single-slot ref into a layer-keyed registry resolved by the active tool.
Today each type's interaction composable registers its pointer handlers into one shared
modeInteractionref. That's fine when only one layer mounts (single-type docs), but the unified canvas mounts several layers at once — they'd clobber each other (last-writer-wins). This makes registration keyed by layer and adds a pure resolver that picks the right handler for the active tool.Legacy is unchanged: a single-type document registers exactly one surface layer, so the resolver returns it regardless of tool — identical behaviour.
Changes
useModeInteraction.js: registry ref{ layerKey: handlers };registerModeInteraction(ref, layerKey, handlers); new pureresolveModeHandlers(registry, activeTool)(0 → null, 1 → that one, many → whiteboard-tools→whiteboard else the other).DiagramCanvas.vueresolves handlers by active tool indelegatesSurface()/delegateSurfaceEvent().Testing
resolveModeHandlers).🤖 Generated with Claude Code