Commit Graph
184 Commits
Author SHA1 Message Date
Hiren Kangad 150bb91a27 refactor: centralize font-size clamps in textLimits.ts
Single source of truth for font-size constraints (text 6–160, sticky
8–96) used by creation defaults, resize-bake, and any future mutation
paths. Replaces scattered hardcoded min/max values.
2026-03-12 23:35:25 +05:30
Hiren Kangad 1ac727ea60 feat: zoom-bucket text sharpness + remove fontSize toolbar controls
Add TextSharpnessManager for crisp text rendering at all zoom levels:
- Discrete zoom buckets (0.5–3x) avoid texture churn on small zoom changes
- Initial bucket applied to all items on setup and newly created items
  via SceneManager.onItemCreated callback (fixes blurry-on-load)
- Visibility check uses getItemWorldBounds for correct grouped item coords
- TextSprite/StickySprite gain setZoomBucket() for resolution control

Remove fontSize +/- controls from contextual toolbar — font size is now
controlled purely through direct manipulation (resize → bake).
2026-03-12 23:23:30 +05:30
Hiren Kangad 9fac16e6a4 feat: contextual text formatting toolbar + resize fontSize baking
- Remove persistent font-size slider from main toolbar (tools only)
- Lock in zoom-aware creation defaults as named constants
- Split contextual toolbar by object type: text vs sticky
  - Text: fontSize + fontFamily + text color
  - Sticky: fontSize + fontFamily + text color + note fill color
  - Mixed selection: hide toolbar
- Bake scale into fontSize on text resize (reset sx/sy to 1)
- Sticky resize stays layout-driven (no font change)
2026-03-12 22:47:48 +05:30
Hiren Kangad 83e753bb69 perf: remove thumbnail generation from hot autosave path
extract.canvas(viewport) snapshots the entire viewport to a WebGL
texture on the main thread. When viewport dimensions × devicePixelRatio
exceed GPU limits, this causes texImage2D errors and ~1000ms stalls
that block focus, typing, and scroll. Thumbnails can be generated on
idle or server-side instead.
2026-03-12 22:24:59 +05:30
Hiren Kangad 93c7c792db fix(text): use requestAnimationFrame for editor open timing
queueMicrotask fires before the click event settles, causing the
textarea to blur immediately and trigger empty-text cleanup.
requestAnimationFrame waits one paint frame — enough for the pointer
event to fully resolve without the sluggishness of setTimeout(50).
2026-03-12 22:15:20 +05:30
Hiren Kangad d365049470 perf(text): remove 50ms editor delay + zoom-aware creation defaults
Replace setTimeout(50) with queueMicrotask for TEXT tool editor open
(matching STICKY tool). Add screenToWorld helper for zoom-aware font
sizes and sticky card dimensions. Remove unused Text/TextStyle imports.
2026-03-12 22:09:12 +05:30
Hiren Kangad 5158938eb3 refactor(text): update Editor TextFormatToolbar to use TextSprite API 2026-03-12 22:09:12 +05:30
Hiren Kangad 2efcd0e622 refactor(text): update TextEditor to use TextSprite API 2026-03-12 22:09:12 +05:30
Hiren Kangad 2e24500746 feat(text): wire TextSprite into SceneManager, eliminate inline text mutation 2026-03-12 22:09:12 +05:30
Hiren Kangad d85de4ba9e feat(text): add TextSprite with dirty-check caching 2026-03-12 22:09:12 +05:30
Hiren Kangad f12b75395a perf(sticky): remove creation delay + add dirty-checking to StickySprite
- Replace 50ms setTimeout with queueMicrotask for editor open
- Skip updateFromData() entirely when no inputs changed
- Cache background redraw inputs, skip Graphics clear+redraw when shape unchanged
- Separate text-only, style-only, and bg-only update paths
2026-03-12 22:09:12 +05:30
Hiren Kangad 565b7c6c19 fix(sticky): prevent crash on editor re-entry during sticky lifecycle
Clear editor state before scene callbacks to prevent blur timer or
startEditing re-entry from calling updateFromData on a destroyed sprite.
Guard all display object access with .destroyed checks.
2026-03-12 22:09:12 +05:30
Hiren Kangad a191f74c31 fix(sticky): wire fontSize from toolbar slider + update shortcuts help 2026-03-12 22:09:12 +05:30
Hiren Kangad a7faf004ae feat(sticky): enable double-click editing for sticky notes 2026-03-12 22:09:12 +05:30
Hiren Kangad e183e4b9d2 feat(sticky): extend TextEditor to support sticky note editing 2026-03-12 22:09:12 +05:30
Hiren Kangad 6eb78a2608 feat(sticky): add sticky note button to toolbar 2026-03-12 22:09:12 +05:30
Hiren Kangad 17680a4d8f feat(sticky): add STICKY tool type with click-to-place handler 2026-03-12 22:09:12 +05:30
Hiren Kangad 9fc62dbdc7 feat(sticky): wire StickySprite into SceneManager create/update 2026-03-12 22:09:12 +05:30
Hiren Kangad 92f6200f4b feat(sticky): add StickySprite renderer 2026-03-12 22:09:12 +05:30
Hiren Kangad 6ee6060600 feat(sticky): add StickyObject to scene format schema 2026-03-12 22:09:12 +05:30
Hiren Kangad 69fcab717c fix(review): add recursion depth guard to group child resolution
Prevents stack overflow from corrupted data with circular group references.
2026-03-12 22:09:12 +05:30
Hiren Kangad ecd4408d8a feat(review): group-aware comment targeting — resolve clicks to stable children
New reviewTargeting.ts provides resolveReviewTargetAtPoint() which:
- descends into groups to find the deepest commentable child under the click
- walks children in z-order (front-to-back) for correct visual stacking
- handles nested groups recursively
- returns null if no valid child exists under the point

Editor.tsx review click handler now delegates to the resolver instead of
raw queryRegion + topmost-z pick. Defensive guard rejects group objectIds
before draft creation.

Existing group-anchored threads continue to render and open normally.
2026-03-12 22:09:12 +05:30
Hiren Kangad 1134ddb5c9 refactor(review): use shared getPointAnchorWorld in jump-to-object 2026-03-12 22:09:12 +05:30
Hiren Kangad 40153751f6 refactor(review): remove panel draft composer, move suppression to Editor 2026-03-12 22:09:12 +05:30
Hiren Kangad 54a7557233 feat(review): wire InlineCommentComposer into Editor with anchored positioning 2026-03-12 22:09:12 +05:30
Hiren Kangad e5cf3d3632 feat(review): add useAnchoredOverlayPosition hook for world→screen conversion 2026-03-12 22:09:12 +05:30
Hiren Kangad cf879b34d5 feat(review): add draftCommentText state and double-submit guard 2026-03-12 22:09:12 +05:30
Hiren Kangad 6e1d9df7f0 feat(review): add InlineCommentComposer presentational component 2026-03-12 22:09:12 +05:30
Hiren Kangad 7aa55b66f0 refactor(review): extract shared anchor math into reviewAnchors.ts 2026-03-12 22:09:12 +05:30
Hiren Kangad 318b7358e1 fix(review): address code review findings — tool conflicts, dual inputs, pin animation
1. TEXT and ERASER tool clicks now suppressed during review mode via
   reviewMode flag on ToolContext (read from ref for live value)
2. Object-comment input hidden when draftPin is active — only one
   creation input visible at a time
3. PinOverlay entrance animation removed — focus styling (scale 1.15x,
   alpha changes) no longer fights with fade-in animation loop
2026-03-12 22:09:12 +05:30
Hiren Kangad 16a677dc89 fix: remove entrance animation so dropped items are instantly draggable
Items were fading in from alpha 0 via spring animation, preventing
immediate interaction. Removed the entrance animation entirely — items
now appear at full opacity and are movable on first frame.
2026-03-12 22:09:12 +05:30
Hiren Kangad 5f60cc826a fix(review): gate pin visibility on review mode per spec 2026-03-12 22:09:12 +05:30
Hiren Kangad c6b2c325a5 feat(review): wire FeedbackPanel with draft pin, expandRequest, and point-aware jump-to-object
- Pass expandRequest, focusedThreadId, draftPin, onCreatePointThread to FeedbackPanel
- Lift thread detail state via onThreadDetailChange → setOpenThreadDetailId
- Jump-to-object centers on pin location for point-pinned threads
- Pan-only by default; zoom in if object appears <50px on screen
- Show toast when jumping to deleted object
2026-03-12 22:09:12 +05:30
Hiren Kangad a1efdedb2a feat(review): add focused thread highlight and headerSlot to ThreadList
- FOCUSED_BG and FOCUSED_BORDER tokens in feedbackStyles
- headerSlot prop for draft pin comment input above thread list
- focusedThreadId prop highlights active thread row with accent border
- ThreadListItem gains focused prop with left border + subtle background
2026-03-12 22:09:12 +05:30
Hiren Kangad 9bd2810f5a feat(review): update FeedbackPanel with expandRequest, draftPin input, and lifted thread detail state
- Replace expandThreadId with expandRequest pulse pattern (seq counter)
- Add draftPin, onCreatePointThread, focusedThreadId, onThreadDetailChange props
- Lift expandedThreadId changes to parent via onThreadDetailChange callback
- Draft pin comment input section shown above thread list
- Thread detail collapse signal via expandRequest with null threadId
- Pass thread object to onJumpToObject for point-aware navigation
2026-03-12 22:09:12 +05:30
Hiren Kangad 3b15166c32 feat(review): wire PinOverlay ghost/focus from Editor state 2026-03-12 22:09:12 +05:30
Hiren Kangad f05a2c8c34 feat(review): add Escape handler and point thread submit
- Escape priority: draft pin → thread detail collapse → review mode exit
- Draft/detail clearing works even when focus is in input field
- Review mode exit respects input/textarea focus context
- handleCreatePointThread: REST POST with auto-focus on success
- Clear draft/focus/expandRequest when review mode exits
2026-03-12 22:09:12 +05:30
Hiren Kangad 08fe062b92 feat(review): add review-mode pointer handlers for pin click + draft placement
- pointerdown records position, pointermove detects drag (>5px)
- pointerup fires review logic only if no drag occurred
- Hit-test priority: existing pin → scene object → empty canvas
- 10px screen-space click radius for forgiving object detection
- Permission gating: viewer role cannot place draft pins
2026-03-12 22:09:12 +05:30
Hiren Kangad e854ad59e2 feat(review): add ghost pin rendering and focused pin visuals to PinOverlay
- setGhostPin(): renders white semi-transparent "+" bubble at relative coords
- setFocusedThread(): scales focused pin 1.15x, dims others to 0.7 alpha
- Ghost and focus visuals reapplied on refresh()
- Ghost container cleaned up on destroy()
2026-03-12 22:09:12 +05:30
Hiren Kangad 358d30beb3 refactor(review): split focusedThreadId into persistent focus + expandRequest pulse
- Add DraftPin interface (exported for FeedbackPanel)
- Add expandRequest state with seq counter for re-trigger
- Add draftPin, openThreadDetailId, expandSeqRef state
- Remove old pointerdown pin-click handler with requestAnimationFrame clear
2026-03-12 22:09:12 +05:30
Hiren Kangad 2d1c06cec9 feat(review): make review mode independent of tool selection
- Tool button clicks no longer exit review mode
- Review button moved outside tool group with divider separator
- Tool active state no longer dimmed during review mode
- Updated hint text for review mode
2026-03-12 22:09:12 +05:30
Hiren Kangad d3f7c45dda fix(crop): ensure overlay renders on top of scene items
CropOverlay was hidden behind images because SceneManager._applyZOrder()
reorders viewport children by z-index, pushing non-scene children behind.
Now start() moves itself to the top of the viewport child list.
2026-03-11 18:17:43 +05:30
Hiren Kangad 3413d58f83 fix(crop): return cropOverlayRef instead of .current to fix null timing
The cropOverlay was created asynchronously inside a polling interval but
returned synchronously as .current (null). By returning the ref itself,
Editor.tsx reads .current at call time when the overlay actually exists.
2026-03-11 17:39:34 +05:30
Hiren Kangad 01f22c9d43 fix: address code review findings from crop/text commit
- CropOverlay: register move/up handlers dynamically on drag start (single
  handler instead of 8x per-handle), remove on drag end. Override destroy()
  to call _cleanup() preventing keyboard listener leaks.
- Text format toolbar: re-measure text bounds (w/h) after fontSize/fontFamily
  changes, update spatial index and transform box.
- TextEditor: add clearText() method; tools.ts uses it instead of fragile
  document.querySelector('textarea').
- SceneManager._updateItem: apply crop mask on remote sync for image items.
- useCanvasSetup: stop TextEditor on unmount to prevent orphaned textarea.
- Double-click zoom: use item.data dimensions instead of getBounds() (which
  includes shadow offset).
2026-03-11 17:28:52 +05:30
Hiren Kangad 58da934ec1 feat: text tool UX, image crop, text format toolbar, double-click focus
- Text tool: click-to-place immediately opens inline editor, auto-switches
  back to select tool. Empty text cleanup on save.
- Crop: select image + press C (or right-click > Crop) to enter crop mode.
  8 drag handles with rule-of-thirds grid, dimmed outside area.
  Enter confirms, Escape cancels. Non-destructive (stored as normalized rect).
- Text format toolbar: appears when text items selected, with font size +/-,
  font family dropdown, and color picker with presets.
- Double-click image: zoom-to-fit (PureRef-style focus)
- Entrance animation: replaced bounce with simple fade-in (no delay before
  items become interactive)
- TextEditor: allow empty text (caller handles cleanup)
2026-03-11 17:22:25 +05:30
Hiren Kangad 4ed475c62e fix(canvas): zoom-stable handles and group-scale multi-selection
- Transform handles counter-scale by 1/zoom so they stay constant screen size
- Selection border stroke also counter-scales
- Multi-select resize scales items as a unit from bounding box anchor
- Redraw transform box on viewport zoom/pan via 'moved' listener
2026-03-11 16:59:10 +05:30
Hiren 155dc6ac01 - Add mattermost_id column to RefBoard users for OAuth linking
- Admin panel shows per-user RefBoard login status (Active vs Not signed in)
- Add RefBoard config: REFBOARD_PUBLIC_URL, REFBOARD_INTERNAL_URL, REFBOARD_API_KEY
- Update .env.example with RefBoard section
2026-03-11 13:40:00 +05:30
Hiren Kangad 6518ed6763 fix: hardening pass — permissions, socket reconnect, canvas setup, arrangements
- Fix 403 on save for public collection viewers (return role in GET board response)
- Add read-only status indicator (StatusBar + StatusIndicator)
- Fix beforeunload save to use fetch+keepalive with auth header
- Socket reconnect now rejoins board room automatically
- Canvas setup uses polling instead of brittle 200ms timer
- Fix double user:left on disconnect (use disconnecting event, snapshot rooms)
- Thread + comment creation wrapped in db.transaction
- Prevent owner downgrade via addCollectionMember (check existing member)
- Bound redirect depth in downloadImage to 5
- Arrangement operations anchor to bounding box top-left (no drift)
- Distribute H/V also anchor to top-left
- Fix annotations fetch to use axios api instance (401 interceptor)
- Replace require() with static import in shortcut-definitions
2026-03-11 08:08:21 +05:30
Hiren Kangad fc2d9df741 feat: annotation UX overhaul, animated packing, toolbar redesign
- PinOverlay: zero-allocation rendering with in-place Graphics/Text updates,
  fix WebGL texture crash (addressModeU null) from orphaned Text objects
- Pins always visible on media, track during drag via updatePositions() fast path
- Replace eraser with Review mode in toolbar tool group (orange gradient)
- Add tool instruction hints bar below toolbar (context-sensitive per tool)
- Feedback panel: glassmorphism, improved ThreadDetail/CommentItem/ThreadListItem
- Timestamps: relative with "ago" suffix, full date on hover tooltip
- De-emphasize pin numbers, show status text in thread list
- Animated arrangement transitions (easeOutCubic, 320ms) for pack/grid/row/column
- Disable snap guides (user requested)
- Paste now selects newly created items
- Remove eraser keyboard shortcuts, remap tool shortcuts
- Orphaned thread cleanup: safe destroy check for deleted media pins
2026-03-11 01:53:56 +05:30
Hiren Kangad ed8424d9a1 feat(annotations): Figma-style UI overhaul
- Redesign PinOverlay: teardrop pins with author initials, colors, numbers
- Split FeedbackPanel into modular components:
  - feedback/FeedbackPanel.tsx (orchestrator)
  - feedback/ThreadList.tsx (list view with filters)
  - feedback/ThreadListItem.tsx (individual thread row)
  - feedback/ThreadDetail.tsx (expanded thread with comments)
  - feedback/CommentItem.tsx (single comment)
  - feedback/CommentInput.tsx (reusable input with Enter/Shift+Enter)
  - feedback/feedbackStyles.ts (shared design tokens)
- Add status colors: red (open), green (resolved)
- Add relative timestamps (2h ago, 3d, etc.)
- Wire pin clicks to expand threads in panel
- Pins follow media transforms in real-time
- Add delete thread with inline confirmation
- Register review mode shortcut (. key)
- Better empty states and filter bar (Open/Resolved/All/Mine)
2026-03-11 01:08:05 +05:30