Comment: scale not persisted across reload #41
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#41
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?
Resizing a comment marker via the transformer (same surface as rotation above) visually scales the pin but the scale is discarded on reload.
Root cause: same pipeline as the rotation bug.
applyTransformskips comment markers; the RPC has no scale field; the table has no scale column.Fix: add
scale_xandscale_ycolumns (or a singlescaleif we only allow uniform scaling — preferred), accept incomment.update, send on transformend, apply on load.Consolidated Spec for Issues #36-#41
Objective
Make comments feel like first-class board objects: erasable, deletable from the sidebar, toggleable between active/resolved, non-reactive to the right mouse button, and with their rotation and scale surviving a reload.
Scope at a glance
tools.jsproperties.jsserver/*,comments.jscomments.jscomments.jscomments.jsFiles to Modify / Create
crates/hero_whiteboard_server/src/migrations/005_comment_transform.sql(NEW) — addsrotation REAL NOT NULL DEFAULT 0andscale REAL NOT NULL DEFAULT 1columns tocomments.crates/hero_whiteboard_server/src/db/models.rs— extend theCommentstruct withrotationandscale.crates/hero_whiteboard_server/src/db/queries.rs— include both columns in SELECT / INSERT / UPDATE for comments.crates/hero_whiteboard_server/src/handlers/comment.rs—createaccepts optionalrotation/scale;updateacceptsrotation/scale; newset_resolvedaccepts aresolvedbool (reusescomment.resolvemethod name with the new field to stay backwards-compatible).crates/hero_whiteboard_server/src/db/queries.rs— renameresolve_commenttoset_comment_resolved(conn, id, resolved, now)settingresolved = ?.crates/hero_whiteboard_server/openrpc.json— document the new fields oncomment.create/comment.update/comment.resolve.crates/hero_whiteboard_ui/static/web/js/whiteboard/tools.js— eraser walks.comment-marker; transformertransformendroutes comment markers toWhiteboardComments.onTransformEnd.crates/hero_whiteboard_ui/static/web/js/whiteboard/comments.js— right-click guard, Unresolve support, load/save rotation + scale,onTransformEndhelper,unresolveCommentexport.crates/hero_whiteboard_ui/static/web/js/whiteboard/properties.js— detectcomment-markerinshow()and render a small pane (Resolved badge, Resolve/Unresolve button, Delete button).Implementation Plan
Step 1: Schema + server (rotation, scale, unresolve)
Files: migration, models, queries, handler, openrpc.json
005_comment_transform.sqladdingrotation REAL NOT NULL DEFAULT 0andscale REAL NOT NULL DEFAULT 1to thecommentstable.Commentstruct; SELECT/INSERT/UPDATE inqueries.rsinclude both columns.comment.updatehandler reads optionalrotationandscalefrom params and passes them through. Clamp scale server-side to[0.2, 5.0]as a safety net.resolve_comment→set_comment_resolved(conn, id, resolved, now);comment.resolvehandler readsparams["resolved"].as_bool().unwrap_or(true)and calls the new helper.resolvedparam oncomment.resolve.Dependencies: none.
Step 2: Client-side rotation + scale persistence
Files:
comments.js,tools.jsaddCommentMarker, applycomment.rotation || 0andcomment.scale || 1to the group before adding to the layer.dragendhandler to includerotationandscalein thecomment.updatepayload (they may not have changed, but sending them is idempotent).WhiteboardComments.onTransformEnd(group)that readsgroup.rotation()and averagesscaleX/scaleY, clamps to[0.2, 5], bakes the uniform scale back onto the group (so the next transform is clean), updates_comments[id].data, sends the RPC, and broadcasts.handleSyncMessage, add acomment.updatedbranch that also readsrotationandscaleand applies them to the marker.tools.jstransformend, iterate nodes; for eachnode.hasName('comment-marker')callWhiteboardComments.onTransformEnd(node)instead ofWhiteboardObjects.applyTransform(node).Dependencies: Step 1 (needs the new RPC fields).
Step 3: Right-click guard
Files:
comments.jsaddCommentMarker, theclick taphandler short-circuits whene.evt && e.evt.button !== 0. The nativecontextmenuhandler incontextmenu.jsalready shows the canvas menu (comment markers are not.objectancestors), so no further change is needed there.Dependencies: none.
Step 4: Unresolve UI
Files:
comments.jsunresolveComment(id)which callsrpcCall('comment.resolve', { id: id, resolved: false }), flipsentry.data.resolved = false, updates marker appearance, broadcastscomment.unresolved, and re-renders the popover.showCommentPopover, render an Unresolve button (classcomment-btn unresolve) whencomment.resolved, wired toWhiteboardComments.unresolveComment.comment.unresolvedinhandleSyncMessage(mirror of the resolved branch).Dependencies: Step 1 (needs server to accept
resolved: false).Step 5: Eraser deletes comments
Files:
tools.jseraseAtPosition, after the object + connector loops, walklayer.find('.comment-marker'); for each that intersects the eraser box, extractnumericId = parseInt(node.id().replace('comment-', ''), 10)and callWhiteboardComments.deleteComment(numericId).Dependencies: none.
Step 6: Properties panel for comments
Files:
properties.jsshow(node), before the regular type dispatch, detectnode.hasName && node.hasName('comment-marker')and render a minimal pane:WhiteboardComments.resolveComment/unresolveComment/deleteComment.Dependencies: Step 4 (
unresolveCommentexport).Acceptance Criteria
[0.2, 5].Notes
scalecolumn) because the pin is a circle; non-uniform deformation has no useful semantics.comment.resolvewith aresolvedparam (instead of addingcomment.unresolve) keeps the method count flat and matches how most systems model boolean flips.Pull request opened: #42
This PR implements the consolidated spec (posted above) covering all six comment fixes.
CI
cargo check --workspace: passcargo clippy --workspace -- -D warnings: passcargo fmt --check: pass