- collab.blocks sync had no guard against empty arrays
- when project loads, collab syncs empty blocks from server
- this overwrites createDefaultBlocks() with empty array
- added if (collab.blocks.length > 0) guard, same as layers
- LeftSidebar was hiding entire Bibliothek section when blocks array was empty
- Removed blocks.length > 0 conditional wrapper
- Added blocks || [] fallback to prevent crash
- Library tree now visible even with no blocks
- Root cause: App.tsx collab sync effect called setLayers(collab.layers)
even when collab.layers was empty, wiping out initialLayers
- Effect: RenderEngine.render() iterates layers to draw elements;
with 0 layers, no elements render (appear to disappear)
- Fix: guard against empty collab.layers
Fixes: drawing tools work on desktop and mobile, objects persist after release
- Add pointercancel listener (treated same as pointerup)
- Remove e.preventDefault() from pointerdown/pointerup (was suppressing touch events)
- Expand onMouseUp tool list: arc, polygon, revcloud now confirm on release
Fixes: object disappears on touch release, tools work same on mobile as desktop
- InteractionEngine: pointerdown on canvas, pointermove/pointerup on document
- Pointer capture for smooth dragging outside canvas
- CSS: touch-action: none on canvas to prevent browser touch interception
- Fixes: tools not working on desktop (mouseup lost outside canvas) and mobile (no touch support)
- RightSidebar: added onCollapse prop and close button in header
- LeftSidebar: wired existing onCollapse prop in App.tsx
- CSS: show .leftbar-toggle and .rightbar-close on mobile
- Both buttons call setMobile{Left,Right}Open(false) to close overlays
- MobileDrawers component rendered empty drawer-left/drawer-right overlays
- These had drawer-body with 0 children, covering the real leftbar/rightbar
- Real sidebars with actual content now visible as slide-in overlays
- overflow-y: auto on mobile sidebars so all tools are reachable
- Re-enable tool-section-label, tool-btn-label, leftbar-title on mobile
- Tool grid 2-column with labels for better mobile UX
- LeftSidebar/RightSidebar: added className prop for 'open' class
- Topbar: wired hamburger onClick + added mobile-drawer-toggle button for right panel
- App.tsx: added SettingsModal import/state/render, passed className props to sidebars
- styles.css: mobile sidebars now fixed slide-in overlays (translateX) instead of display:none
- ui.types.ts: added className to RightSidebarProps, onOpenLeftDrawer/onOpenRightDrawer to TopbarProps
- Tested at 390px viewport: both sidebars slide in correctly, transform verified via DOM
- Add ownership checks on all notification and share routes (403 Forbidden)
- Validate permission field (only view/edit/admin allowed)
- Remove user_id from POST notifications (only self-notifications)
- Add getNotification/getProjectShare to DB interface + adapter
- Add res.ok checks on all frontend API calls
- Add click-outside handler for notification dropdown
- Add initial notification load on mount for badge count
- Add email validation + duplicate check in ShareDialog
- Add Enter key handler in ShareDialog
- Add submitting state to prevent double-click
- Guard against null token in Dashboard
Root cause: layers.id is TEXT PRIMARY KEY (global unique across all drawings).
Hardcoded IDs layer-0..layer-4 collided when multiple projects tried to create
the same layer IDs. Second project got UNIQUE constraint failed on POST /layers.
Without layers, elements had dangling layer_id refs causing FOREIGN KEY errors.
Fix: makeInitialLayers() generates unique IDs: layer-{timestamp}-{index}.
activeLayerId initialized from first layer, not hardcoded.
activeLayerName uses activeLayerId variable, not hardcoded layer-0.
On project load with existing layers, activeLayerId set from first DB layer.
Three fixes:
1. interaction/index.ts: Add layerId to created element in confirmDraw()
2. CanvasArea.tsx: Sync layers to LayerManager via layerManagerRef
3. App.tsx: Fallback to activeLayerId in handleElementCreated if layerId missing
Root cause: LayerManager.activeLayerId was empty because layers were never
synced from React state to the interaction layer LayerManager. New elements
got layer_id="" which failed SQLite FOREIGN KEY constraint.
Also includes Yjs sync race condition fix from previous commit.
- CanvasArea: add useEffect to refresh InteractionEngine callbacks when props change
- App.tsx: handleElementCreated/Deleted/Modified now use functional setElements updates
- Root cause: CanvasArea init useEffect had empty deps, capturing stale callbacks at mount
- handleElementCreated used [...elements, el] with stale elements=[] closure
- Each new element replaced all previous ones instead of appending
- All 343 tests pass, tsc clean