Remote resize doesn't relayout object content — text drifts outside shapes in the other window #78
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_whiteboard#78
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Bug
When a board is open in two browser windows and one user resizes an object that has internal content (markdown text inside a shape, sticky note text, document content, etc.), the other window receives the new dimensions and applies them to the background shape, but does not re-lay-out the internal content. The text stays at its pre-resize position/wrap-width and visibly drifts outside the new shape bounds.
Reproduction
Reliable repro with: shape (rect/ellipse/diamond/star/etc.) + text. Same root-cause symptom is expected with sticky notes (markdown body), text objects (wrap), document cards (markdown content), and likely frame label, calendar widget, kanban board, mindmap, image, and webframe (their internal children also need to follow the resized bg).
Root cause
crates/hero_whiteboard_ui/static/web/js/whiteboard/sync.js--applySyncUpdate:bg.width(obj.width)/bg.height(obj.height)(or radius equivalents) to the remote object's background shape.WhiteboardObjects.rerenderXxx(node)when the text content has changed (obj.text !== node._mdSource). A dimension-only update therefore never triggers a content relayout.redrawwhen their state-data fields change. A pure dimension-only update doesn't redraw them either.image,webframesimilarly only sync bg dims, leaving their image/iframe-overlay child sizes (set from the local resize handler inobjects.js) out of sync.Meanwhile, the local resize path in
objects.js(thetransformendhandler around lines 990-1085) updates bg dims and calls the content rerender / widget redraw / image scaling — so the originating window looks correct. Only the remote window drifts.Affected file
crates/hero_whiteboard_ui/static/web/js/whiteboard/sync.js—applySyncUpdatefunction, dimension-update path.Expected behavior
After
applySyncUpdateupdates the bg dimensions of a remote object, the content should be re-laid-out so the remote view matches what the originating user just saw locally — text wraps to the new width, vertical-centering recomputes against the new height, widgets redraw at the new size, image/iframe children resize to track the new bg.Fix sketch
In
applySyncUpdate, after the bg dimensions are applied (around line 453), detect that dimensions actually changed and dispatch the appropriate relayout per type:Notes:
rerenderXxx(which callsWhiteboardSync.onUpdate) is safe becauseonUpdateearly-returns when_applyingSyncis true (sync.js:333).obj.text !== node._mdSourcebefore the new dispatch will avoid the double call).Acceptance criteria
Implementation Spec for Issue #78
Objective
When
applySyncUpdateinsync.jsapplies dimension changes from a remote user's resize, also relayout the receiving object's internal content so the remote view matches the originating one — text wraps to the new width and centers vertically against the new height, widgets redraw at the new size, and image/iframe children follow the new bg.Requirements
WhiteboardObjects.rerenderXxx(node)to re-lay-out the markdown content.WhiteboardXxx.redraw(node)so the widget redraws at the new size..img-contentchild to track the new bg..header,.placeholder,.labelchildren — same as the local resize handler does inobjects.js:1082-1099.(8, -20)and doesn't depend on bg dims — seeobjects.js:808-815).rerenderXxx -> WhiteboardSync.onUpdatealready early-returns under_applyingSync—sync.js:333).Files to Modify
crates/hero_whiteboard_ui/static/web/js/whiteboard/sync.js—applySyncUpdatefunction (around lines 414-609).No other file needs changes. The local
transformendhandler inobjects.jsalready does the equivalent relayout for the originating user.Implementation Plan
Step 1: Track dimension change and relayout content after type-specific update block
Files:
crates/hero_whiteboard_ui/static/web/js/whiteboard/sync.jsapplySyncUpdate, before the bg-dimension update at line 442, record whether dimensions are changing. Capture the old bg size and compare to the incomingobj.width/obj.height(only if both are positive, matching the existing guard). Use a small tolerance (e.g. < 0.5 px) to treat sub-pixel jitter as no-change:dimsChanged:requestAnimationFrameat line 599), add a second small dispatch that relays out content whendimsChangedis true:WhiteboardSync.onUpdate(node), which is a no-op when_applyingSyncis true (the surroundingtryalready sets it). No echo risk.Dependencies: none.
Acceptance Criteria
.img-contentfollows the new bg in window B..header,.placeholder,.labelfollow the new bg in window B.Notes
dimsChangeddetection compares old bg size againstobj.width/obj.heightso we don't relayout on every metadata-only sync.textChangedshort-circuit so we don't pay the cost twice.WhiteboardWebframebased on Konva node coordinates and re-syncs on the canvas redraw scheduled at the bottom ofapplySyncUpdate. The new code only resizes the Konva placeholder/header/label children that are visible during drag and used as the stand-in.Test Results
cargo test --workspace --lib: 4 lib targets, 0 tests / 0 passed / 0 failed each (no Rust unit tests for these crates).cargo clippy --workspace -- -D warnings: clean.node --check sync.js: parses cleanly.This is a JS-static-asset-only change. Manual verification recommended: open the same board in two browser windows, place a shape with markdown text in window A, drag-resize it, and confirm the text in window B re-wraps and re-centers. Repeat with sticky, text, document, calendar, kanban, mindmap, image, webframe.
Implementation Summary
Changes
crates/hero_whiteboard_ui/static/web/js/whiteboard/sync.js(+52 / -1)applySyncUpdate, snapshot the bg's previous size (handling Ellipse / radius-only / width-height shapes) before applying the incomingobj.width/obj.height.dimsChangedflag using a 0.5 px tolerance to ignore sub-pixel jitter.WhiteboardObjects.rerenderXxx(node)(skipped when text content also changed in the same update, to avoid double render).WhiteboardXxx.redraw(node)..img-contentchild..header,.placeholder,.labelchildren (mirrors the localtransformendhandler inobjects.js:1082-1099).(8, -20)and doesn't depend on bg dims).Why no echo loop
rerenderXxxcallsWhiteboardSync.onUpdate(node), butonUpdateearly-returns when_applyingSyncis true (sync.js:333). The wholeapplySyncUpdatebody runs inside_applyingSync = true, so no remote-triggered relayout re-broadcasts.Verification
cargo test --workspace --lib: 4 lib targets pass, 0 tests.cargo clippy --workspace -- -D warnings: clean.node --check sync.js: parses cleanly.Notes / caveats
dimsChangeddetection compares the current bg size to the incoming dims, so style/data-only sync updates do NOT trigger a relayout (no perf regression).