Commit Graph

1188 Commits

Author SHA1 Message Date
Jeff Emmett 7a2c297a42 Merge branch 'dev' 2026-03-22 15:47:14 -07:00
Jeff Emmett 4c1cd21b8c fix(spaces): ensure demo space is always public in access checks
getSpaceConfig() read stored visibility without the demo override,
so the client-side access gate blocked unauthenticated users from
accessing the demo space.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 15:47:00 -07:00
Jeff Emmett 219f653921 Merge branch 'dev' 2026-03-22 15:39:53 -07:00
Jeff Emmett 692c75ee5c fix(shell): escape apostrophe in access gate to prevent script parse failure
The single quote in "don't" broke the JS string literal inside the
inline script, causing a SyntaxError that killed the entire script
block including tab bar and header initialization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 15:39:45 -07:00
Jeff Emmett 637174b0cb Merge branch 'dev' 2026-03-22 15:10:47 -07:00
Jeff Emmett 2de61cd7ad feat(rcal): move zoom/legend below calendar, add multi-day event spans
- Reorder layout: nav → calendar → legend → zoom bars → bottom bar
- Add "Calendar Legend" heading above source badges
- Fix getEventsForDate() to support multi-day range checking
- Render colored span bars across day cells for multi-day events
- Make showAccountModal/isSignedIn public on rstack-identity
- Tour final step triggers identity setup flow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 15:10:39 -07:00
Jeff Emmett 33a0f9ab04 chore(secrets): remove redundant env passthrough from docker-compose
Secrets now fetched from Infisical at container startup instead of
being passed through docker-compose from .env. Reduces .env to only
Infisical auth creds and non-Infisical container secrets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 14:48:20 -07:00
Jeff Emmett 8459d979b1 Merge branch 'dev' 2026-03-22 14:40:35 -07:00
Jeff Emmett 4383cffb9d fix(canvas): prevent shape re-seeding after user clears canvas
Added shapesSeeded flag to community doc metadata. Once shapes are
seeded (demo, template, or campaign), deleting all shapes no longer
triggers re-seeding on server restart. The demo reset endpoint clears
the flag so it can re-seed intentionally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 14:40:28 -07:00
Jeff Emmett b97d018292 Merge branch 'dev' 2026-03-22 14:35:17 -07:00
Jeff Emmett 466a0305fd fix(spaces): dedup space switcher + restructure into sections
Personal space rename only applies when isPersonal flag is set (not all
private spaces). Demo forced to public visibility. Public spaces no
longer filtered out. Sections: Private → Permissioned → Public →
✦ Discover → Create.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 14:35:07 -07:00
Jeff Emmett 358e327bad Merge branch 'dev' 2026-03-22 14:29:13 -07:00
Jeff Emmett ac402c29e9 feat(canvas): replace repulsion with snap guides + drop suggestion
Remove ambient repulsion loop (shapes drifting apart at 60fps). Add
Figma-style snap alignment guides during drag with magnetic stickiness,
and ghost drop suggestion when shapes overlap after drop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 14:28:32 -07:00
Jeff Emmett 6cccd158c4 Merge branch 'dev' 2026-03-22 14:25:02 -07:00
Jeff Emmett 4b08a02851 fix(seed): prevent demo data re-seeding after user deletes content
Added a `seeded` flag to Automerge doc metadata across 6 modules
(rcal, rnotes, rtasks, rvote, rbnb, rvnb). Once demo data is seeded,
deleting all content no longer triggers re-seeding on next page load.

Also removed rcal's per-request seedDemoIfEmpty() call from the route
handler — onInit + seedTemplate already handle initial seeding.

fix(canvas): prevent bulk delete dialog from stacking

The Delete key repeat was creating multiple overlays, making the dialog
appear unclosable. Added a guard to prevent duplicate dialogs, and
Escape key support to dismiss.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 14:24:51 -07:00
Jeff Emmett 6e94a457cb Merge branch 'dev' 2026-03-22 14:03:37 -07:00
Jeff Emmett eb470dff18 fix(auth): use client-side access gate for private spaces
Server-side HTML gates can't work because auth tokens are in
localStorage, not cookies. Replaced with:
- Client-side gate checks session, then verifies membership via
  new /api/space-access/:slug endpoint
- Shows "Sign In" for unauthenticated users
- Shows "no access + return to your space" for non-members
- Server-side gates remain for API/JSON requests and WebSocket

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 14:03:28 -07:00
Jeff Emmett da3a44e356 Merge branch 'dev' 2026-03-22 13:59:53 -07:00
Jeff Emmett fe7157ffe1 fix(shell): position settings/history panels below their buttons
Both panels now use position:fixed with JS-computed coordinates from
getBoundingClientRect(), ensuring they open directly below their
respective header buttons and right-aligned to the button edge.
History panel clamps left edge to prevent off-screen overflow.

Also adds missing click handlers for settings-btn and history-btn
in canvas.html (previously only wired in shell.ts module pages).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:59:44 -07:00
Jeff Emmett a38cd7bb5d Merge branch 'dev' 2026-03-22 13:49:59 -07:00
Jeff Emmett 7d4e6122f1 feat(auth): enforce space access control for private spaces
Non-members of private spaces are now blocked at three layers:
- WebSocket upgrade rejects with 403
- Module middleware shows access denied page (browser) or JSON 403 (API)
- Space root dashboard shows access denied page
Friendly "Private Space" page with link back to user's own space.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:49:50 -07:00
Jeff Emmett 13c2062fad Merge branch 'dev' 2026-03-22 13:29:45 -07:00
Jeff Emmett 8eb2738b65 refactor(shell): move history & settings icons next to space switcher
Both dropdown-wrap buttons now sit in header-left directly after the
space switcher, keeping space-related controls grouped together.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:29:39 -07:00
Jeff Emmett 4f9e29e5e7 fix(canvas): persist deletions immediately to prevent resurrection
Destructive operations (forget, delete, remember) now flush to
IndexedDB + localStorage immediately instead of using 2s debounce,
preventing deleted items from reappearing on page reload.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:29:33 -07:00
Jeff Emmett e7f655c901 Merge branch 'dev' 2026-03-22 13:25:37 -07:00
Jeff Emmett e0f0426e59 fix(canvas): limit separation dynamics to rApps/embeds, not drawings/slides
- Add folk-shape to pushExemptTags so wb drawings (pencil, rect, circle,
  line) are exempt from repulsion and can overlap other shapes freely
- Skip wb-drawing elements in repulsion loop and free-position placement
- Locked shapes are not pushed by repulsion (full push goes to unlocked neighbor)
- getExistingShapeRects uses pushExemptTags instead of hardcoded arrow check

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:25:27 -07:00
Jeff Emmett 2a313206a6 Merge branch 'dev' 2026-03-22 13:20:10 -07:00
Jeff Emmett 842ac4d67e feat(canvas): eraser works on all shapes, add lock icon for shapes
- Eraser now targets any folk-shape (not just wb-drawing), erasing whatever it touches
- Added lock property to folk-shape: locked shapes can't be moved, resized, or erased
- Lock state persisted via Automerge sync (toJSON/applyData/fromData)
- Lock icon appears beside calendar icon when shape(s) selected, toggles lock on click

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 13:19:54 -07:00
Jeff Emmett 851cc283ee feat(canvas): folk-shape and canvas.html updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 12:44:49 -07:00
Jeff Emmett 0d8d42c49e fix(rcal): distinguish pinch-zoom from scroll-pan on calendar
Trackpad pinch (ctrlKey wheel) zooms granularity, two-finger scroll
navigates the timeline forward/backward instead of zooming.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 12:44:45 -07:00
Jeff Emmett 0fbf12e5f8 fix(routing): serve rspace.online/{moduleId} as app in shell instead of landing page
rspace.online/rcal was redirecting to rcal.online (standalone domain) via
the landing page proxy. Now rewrites to /demo/{moduleId} so it loads the
actual app within the rSpace shell with app/space switchers, matching the
behavior of {space}.rspace.online/{moduleId}.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 11:24:39 -07:00
Jeff Emmett 63c1b7c1e7 refactor(shell): convert settings & history panels to dropdown menus
Replace full-height slide-in panels with compact dropdowns that appear
beneath header icons. Both icons now grouped in header-right with
mutual exclusion and click-outside-to-close behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 23:17:17 -07:00
Jeff Emmett 6f066f649a fix(server): block disabled modules on subdomain routes
Ensure disabled modules redirect to space root on subdomain routing,
and pre-load community doc before checking enabled modules list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 23:17:11 -07:00
Jeff Emmett e56b4fe89c fix(canvas): hide feed toggle on mobile corner tools
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 22:31:58 -07:00
Jeff Emmett 9b0a672c7b feat(canvas): add Ctrl+Z undo / Ctrl+Shift+Z redo for shape operations
Local inverse-change stack that records before-snapshots of each mutation
and applies forward Automerge changes to restore state on undo. Batches
rapid same-shape changes (<500ms) so drags produce a single undo entry.
Supports create, move/resize, forget, remember, and hard-delete operations.
Max 50 entries, redo stack clears on new changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 22:31:22 -07:00
Jeff Emmett 6491681e3e fix(auth): force platform authenticator + redirect disabled modules
Force authenticatorAttachment: 'platform' across all WebAuthn registration
flows to prevent USB security key prompts. Redirect browser navigations to
space root when accessing disabled modules instead of returning JSON error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 22:31:13 -07:00
Jeff Emmett 15f7e759d1 fix(canvas): map shape interaction + reminder widget dismissal
Map viewer: disable MapLibre interactions when inside a folk-shape
until editing mode (double-click). Prevents map panning when trying
to select/move the shape on canvas.

Reminder widget: dismiss on Escape key and when clicking elsewhere
on canvas (deselecting shapes). Clean up schedule icon when shape
is deleted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 20:44:28 -07:00
Jeff Emmett d5e822ec7c fix(canvas): remove duplicate settings/history button handlers
Canvas.html had its own addEventListener calls for settings-btn and
history-btn, but the shell script already wires these. Both handlers
fired on click, causing double-toggle (open then immediately close).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 20:39:32 -07:00
Jeff Emmett 355b53ee17 fix(canvas): hide toolbar items for disabled modules
Inject enabledModules into client, tag 25 module-specific toolbar buttons
with data-requires-module, and filter out disabled items (plus empty groups)
at page init. Spaces with all modules enabled are unaffected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 20:36:10 -07:00
Jeff Emmett fcf4202045 fix(rmaps): remove max-height cap so map fills available space
Map container was capped at 700px, leaving blank space on most screens.
Removed the cap so calc(100vh - 220px) fills properly. Also matched
sidebar max-height to viewport.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 19:26:18 -07:00
Jeff Emmett 8b61203e17 revert: remove standalone domains we don't own
Reverts Traefik rules and removes standaloneDomain from rdesign, rvnb,
rbnb, rdocs, and crowdsurf — we don't have these domains.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 18:31:17 -07:00
Jeff Emmett d315375a93 fix(routing): add missing Traefik rules for 5 standalone domains
rdesign.online, rvnb.online, rbnb.online, rdocs.online, crowdsurf.online
had standaloneDomain declared in their modules but no Traefik router rules,
so {space}.r*.online subdomain redirects wouldn't reach the server.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 18:27:11 -07:00
Jeff Emmett ee1a791aea fix(canvas): move offline status to people badge, toolbar minimize to bottom, zoom to bottom-right
- Offline/reconnecting indicator now shows inside the "N online" people
  badge instead of the shell header (hidden on canvas via CSS override)
- Toolbar collapse/minimize button moved from top to bottom of toolbar
  stack so it sits where the last tool icon was
- Zoom controls moved from bottom-left to bottom-right; on mobile they
  sit above the bottom toolbar to avoid overlap

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 18:22:39 -07:00
Jeff Emmett dbe60f2711 fix(onboarding): remove moduleHasData gate so live spaces show module UI
Live spaces with no CRDT data were showing a generic onboarding page
instead of the module's actual UI. Demo always bypassed this check,
causing visual parity issues between demo.rspace.online and live spaces.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 18:22:11 -07:00
Jeff Emmett 36e76449fa fix(canvas): prevent horizontal overflow on mobile
- Add overflow:hidden on html element for canvas-layout pages
- Bottom toolbar: constrain to viewport with right:8px, horizontal
  scroll for overflow buttons, flex-shrink:0 on items
- Context menu: clamp position to viewport bounds
- Modal panels: use min() for min-width to respect small screens

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 18:17:27 -07:00
Jeff Emmett 823d2c4110 fix(spaces): filter disabled modules from space dashboard
renderSpaceDashboard was showing all modules regardless of space's
enabledModules setting — both in the app cards grid and the app-switcher
dropdown. Now filters using getSpaceShellMeta, same as renderShell.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 18:11:51 -07:00
Jeff Emmett cc504d4a86 fix(spaces): make DID resolve endpoint public (no auth needed for profile data)
The resolve-dids endpoint was returning 401 because unsigned fallback tokens
fail HS256 verification. Since username/displayName is public profile data,
remove auth requirement from the endpoint and client call.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 18:06:36 -07:00
Jeff Emmett 21236ccd15 Merge branch 'dev' 2026-03-21 17:28:13 -07:00
Jeff Emmett 524356d233 feat(tours+solo): add tours to remaining modules and solo mode toggle
Add guided tours to 6 modules that were missing them:
- Shadow DOM: rsocials dashboard, crowdsurf, rdata (TourEngine)
- Light DOM: rsplat, rbnb, rvnb (new LightTourEngine class)

Add solo mode toggle to collab overlay — click the presence badge
to hide your cursor/presence from others. Persists via localStorage,
dispatches event to canvas PresenceManager.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 17:26:57 -07:00
Jeff Emmett 544e557981 fix(theme): use CSS variables for dark mode across all canvas shapes
Replace hardcoded light-mode colors (#f8fafc, #e2e8f0, white, #1e293b, etc.)
with theme-aware CSS custom properties (--rs-bg-surface, --rs-text-primary,
--rs-border, etc.) in 24 shape files. Adds color inheritance to folk-shape
base class so all shapes get correct text color in both dark and light mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 17:26:35 -07:00