- Remove Mattermost integration (OAuth, channel bridge, file sync watcher,
frontend import modal). RefBoard now ships as a self-contained app.
- Replace SSO Login screen with email/password form (+ optional register link
gated by ALLOW_SELF_REGISTRATION).
- Add SEED_ADMIN_EMAIL / SEED_ADMIN_PASSWORD env-var bootstrap so a fresh
install ships with an admin account on first boot (idempotent).
- ALLOW_SELF_REGISTRATION flag (default false) gates POST /api/auth/register.
First user can always register (auto-promoted to admin).
- Drop mattermost_id and mm_file_id columns + board_channel_links table
from the schema; remove related db helpers and exports.
- Add MIT LICENSE, comprehensive README, .env.example, docker-compose.yml
(bundles MinIO so one command boots a working stack).
- Expand .gitignore for typical Node + Docker dev artefacts.
The asset progress overlay (e.g. "Loading assets 6/22") was incompatible
with the viewport culling system — culling only loads nearby textures and
unloads distant ones, so loaded count could never reach total. Simplified
to a brief spinner during scene data parsing only.
- Set texture to Texture.EMPTY before destroying sprites in
AnimatedGifSprite and PdfPageSprite (matches VideoSprite pattern)
- Add full-screen loading overlay that blocks interaction until
scene and assets finish loading
- TransformBox rotates with single-item selection (Figma-style), with
handles and resize math projected into rotated coordinate space
- Fix VideoSprite alphaMode crash by swapping texture to EMPTY before
destroying, preventing PixiJS render loop from reading null source
- Fix Ctrl+V double-paste: internal clipboard now always takes priority
over system clipboard PNG, with wasRecentInternalPaste() guard
- Add asset loading progress bar and suppress "Drop images here" flash
during initial scene load
Replace the split snapshot/native renderer paths with a single
composition pipeline (compositionRenderer.ts) that:
- Loads actual source images and uses naturalWidth/Height for
correct full-resolution sampling (fixes top-left-corner-only bug
caused by data.w/h being capped to 600px display dimensions)
- Routes image-only selections through native Canvas 2D composition
- Falls back to viewport snapshot for mixed/unsupported selections
with explicit warnings instead of silent degradation
- Resolves group children via itemResolver for proper group export
- Rejects group children from native composition (local coords
incompatible with world-space drawing)
- Adds canvas size safety limits with auto-downscale
- Guards VideoSprite._drawFrame against null texture source race
condition during zoom-triggered culling
New files:
- compositionRenderer.ts — unified composition module
- compositionRenderer.test.ts — 16 tests for entry flattening,
bounds, dimensions, group handling
Modified:
- clipboard.ts — uses composeSelection() instead of direct renderers
- export.ts — uses composeSelection() + getCompositionDimensions()
- Editor.tsx, useShortcutHandler.ts — pass scene for group resolution
- VideoSprite.ts — null guard on texture source in frame loop
The crop editor (getImageEditorGeometry) was anchoring on a view-space
point that maps differently in cropped vs uncropped local space when
flipped. For asymmetric crops + flip, the full image would appear
shifted from where the visible image was — the user saw the image
"jump" when entering crop mode.
Fix: anchor on the container's local origin instead. In the cropped
sprite, local (0,0) corresponds to source pixel (srcRect.x, srcRect.y).
Position the editor so that same source pixel maps to the same world
point in both cropped and uncropped states. This works correctly for
all flip/rotation/crop combinations.
- Fix crop confirm anchor drift for rotated images by using crop corner
world point instead of AABB min in useCanvasSetup.ts
- Document ungroup shear limitation for non-uniform scale + rotation
- Add 6 integration tests covering crop confirm and ungroup paths
Fix text staying blurry on zoom by ensuring the first setZoomBucket call
always applies (PixiJS v8 defaults to auto-resolution which skipped the
initial bucket=1 assignment), listening on both 'moved' and 'zoomed'
viewport events, and tightening bucket thresholds from 6 to 9 levels.
- Move markdown editor from canvas overlay to side panel (70% width)
for better performance and editing experience
- Add @blocknote/mantine for full BlockNoteView with default UI components
- Fix socket reconnect loop caused by unstable pasteOpts object reference
(memoize with useMemo)
- Add ResizeObserver to markdown overlay cards for automatic height sync
- Call mdOverlay.refreshAll() on every canvas change so overlays track
pack/grid/arrange/save operations
- Paste goes to BlockNote editor when contentEditable is focused
- Simplify toolbar: single color picker (accent + auto-derived bg),
title/name field, width presets S/M/L
- Guard normalize/flip operations to skip markdown and sticky items
- Fix title not updating on card preview (pass name prop, bump revision)
- Fix preview not refreshing after editor save (revision counter + overlay refresh)