Commit Graph

83 Commits

Author SHA1 Message Date
Jeff Emmett 3b3eecdddb fix: stop demo→personal space redirect and clean up space switcher
Logged-in users visiting demo.rspace.online were auto-redirected to
their personal space on page load. Now only provisions the space
silently without redirecting. Also removes the redundant "Public
spaces" section from the dropdown and filters the /api/spaces endpoint
to only return demo, user's own spaces, and permissioned spaces.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 18:02:00 -08:00
Jeff Emmett 57fd1f4913 fix: always show Demo Space at top of space switcher dropdown
Adds a permanent "Demo Space" entry as the first item in the space
switcher dropdown across all rApps. Previously demo only appeared
in the "Public spaces" section (if the API returned it), making it
easy to miss. Now it's always visible at the top with a game
controller icon, followed by the sign-in/personal space CTA.

Also filters demo out of the "Public spaces" section to avoid
showing it twice.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:29:04 -08:00
Jeff Emmett 707d83525b fix: responsive header dropdowns + space switcher on all pages
- Remove overflow:hidden from header__left on mobile (was clipping
  app-switcher and space-switcher triggers)
- Add white-space/overflow/text-overflow to both trigger buttons so
  they truncate gracefully on narrow screens
- Add <rstack-space-switcher> to module landing and sub-page info
  shells so the spaces dropdown always appears next to the rApps dropdown

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 16:46:40 -08:00
Jeff Emmett e2ebd11d75 style: differentiate rApp tab headers with borders and spacing
Inactive tabs get a subtle background tint, hover/active tabs show
visible borders, active tab uses solid surface background. Wider gap
between tabs and full-width indicator line for clearer separation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 15:47:20 -08:00
Jeff Emmett 59bdd741be feat: bare-domain sub-pages show info/marketing pages + save-gate
Bare-domain URLs like rspace.online/rsocials/thread now render an info
page with CTAs instead of silently serving the functional app. The
functional app only appears inside a {space} context (e.g.
demo.rspace.online/rsocials/thread). API routes still pass through.

- Add SubPageInfo interface to shared/module.ts
- Add renderSubPageInfo() renderer to server/shell.ts
- Modify bare-domain routing: api/ passthrough → info page → demo fallback
- Add subPageInfos to 8 modules (rsocials, rflows, rnetwork, rtrips,
  rbooks, rphotos, rinbox, rsplat)
- Add window.__rspaceSaveGate() auth prompt on write operations
- Wire save-gate into rsocials Thread Builder save handler

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:16:17 -08:00
Jeff Emmett 1d0e82294b fix: move [+] tab button next to open tabs, style as new-tab shape
- Remove flex:1 from .tabs-scroll so tabs don't stretch across full width
- [+] button sits immediately after last tab instead of far right
- Restyle .tab-add to match .tab shape (same border-radius, padding, hover)
- Push .tab-actions (view toggle) to far right with margin-left: auto
- Dropdown menu follows the button naturally

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:56:51 -08:00
Jeff Emmett 1f071dc4a1 fix: layer flows drag-to-connect, notification 401 spam, /api/meta 404
- Tab bar: replace mouseenter/mouseleave with bounding-rect hit testing
  during drag-to-connect (robust for 3D CSS transforms)
- Tab bar: clean up document mousemove/mouseup listeners on re-render
  to prevent accumulation leak
- Notification bell: stop polling on 401, restart on auth-change
- Space settings: detect subdomain routing to avoid double-prefix on
  /api/meta URL (jeff.rspace.online/jeff/rspace → /jeff/jeff/rspace)
- rSpace module: add GET /api/meta endpoint returning space owner/members

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 11:12:19 -08:00
Jeff Emmett 7b397b522c fix: [+] tab menu clipped by overflow — move outside scroll container
The add-menu dropdown was inside .tabs-scroll which has overflow-x: auto,
causing the browser to clip overflow-y as well (per CSS spec). Move the
.tab-add-wrap (button + menu) out of .tabs-scroll into .tab-bar directly
so the dropdown renders without clipping, beneath the [+] button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 10:33:09 -08:00
Jeff Emmett abb3f57ca0 fix: space settings panel hidden behind canvas due to backdrop-filter containment
Move <rstack-space-settings> outside the header element so its position:fixed
is relative to the viewport instead of the 56px header (backdrop-filter creates
a containing block for fixed descendants). Bump panel z-index above all canvas
elements. Also migrate hardcoded colors to CSS theme variables across shell
components.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 10:30:20 -08:00
Jeff Emmett f5260e0817 feat: move dark/light mode toggle to user profile dropdown
Replaced the dark mode checkbox in the My Account modal with a
sun/moon toggle directly in the profile dropdown menu. Sun on the
left, moon on the right, with a colored slider (amber for light,
indigo for dark).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 10:12:42 -08:00
Jeff Emmett 495baa5935 fix: allow unauthenticated thread builder save/share operations
The space role middleware was blocking all POST/PUT requests from
unauthenticated users with a 403, preventing the thread builder's
save draft and share buttons from working. Added publicWrite module
flag to bypass the role check for modules with public API endpoints.
Also fixed saveDraft() to properly surface server errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:57:59 -08:00
Jeff Emmett a6008a4f2d refactor: complete rfunds → rflows rename across configs and references
Update docker-compose, vite config, Traefik labels, module imports,
and all cross-module references to use the new rflows naming.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 19:13:14 -08:00
Jeff Emmett cdfe8c5b78 feat: add unified notification system with real-time WS delivery
Persistent, PostgreSQL-backed notification system replacing the in-memory
access request polling. Notifications are created via notify(), persisted
to DB, and delivered in real-time over WebSocket with a 30s polling fallback.

Infrastructure:
- notifications + notification_preferences tables in EncryptID schema
- 10 CRUD functions in db.ts (create, list, count, read, dismiss, etc.)
- notification-service.ts: core notify(), WS registry, notifySpaceAdmins()
- notification-routes.ts: REST API at /api/notifications
- rstack-notification-bell.ts: bell icon component with dropdown panel

Module integration (11 hooks):
- spaces.ts: access_request, access_approved, access_denied, member_joined,
  member_left, role_changed
- index.ts WS handler: ping_user (24h expiry)
- encryptid/server.ts: guardian_accepted, recovery_initiated (owner + guardians),
  recovery_approved

Legacy cleanup:
- Removed access request polling, badge, and approve/deny UI from
  rstack-identity.ts (now handled by notification bell)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 18:59:09 -08:00
Jeff Emmett da2b21cd98 feat: add voice dictation to MI bar, markdown, chat & prompt inputs
Extract Web Speech API logic from folk-transcription into a reusable
SpeechDictation utility, then wire mic buttons into all 4 text input
surfaces. Dictation fills inputs in real-time without auto-submitting.
Hidden gracefully in unsupported browsers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 17:10:52 -08:00
Jeff Emmett 63ac2a268e perf: parallelize local-first init — batch IDB loads, cache crypto keys, preload sync states
Sequential document loading during init() was the main bottleneck: each cached
doc required a serial IDB read + key derivation + decryption + Automerge.load.
With N documents this meant N× single-doc latency instead of 1×.

Changes:
- Add loadMany() to EncryptedDocStore for parallel Promise.all() batch loading
- Cache derived space/doc CryptoKeys in DocCrypto (one derivation per session)
- Add preloadSyncStates() to DocSyncManager for parallel sync state loading
- Update all 11 module local-first-client init() methods to use batch APIs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 14:18:55 -08:00
Jeff Emmett 80e42596b3 fix: normalize visibility enums + tab tracking across remaining files
Update remaining references from legacy 4-value visibility model
(public/public_read/authenticated/members_only) to simplified 3-value
model (public/permissioned/private) in rInbox, rVote, identity component,
admin panel, and create-space page. Add tab trackRecent calls in shell.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:29:01 -08:00
Jeff Emmett eb2859d849 refactor: normalize space visibility enums + inline space create form
Align visibility values across server and UI to the canonical set:
public, permissioned, private (replacing public_read, authenticated,
members_only). Add inline space creation form to the space switcher
dropdown and tab bar instead of navigating to /new.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:27:31 -08:00
Jeff Emmett daa6013fd0 fix: add migrateVisibility runtime migration, fix participant→member role label
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:17:53 -08:00
Jeff Emmett 35a5a5f29a feat: workflow template, choice components, space settings, EncryptID vault, UI polish
- Pre-populated 4-node workflow template (trigger→action→condition→output) with blue arrows
- Add folk-choice-vote, folk-choice-rank, folk-choice-spider component libraries
- New rstack-space-settings component
- EncryptID encrypted vault schema and server endpoints
- Space management and community store enhancements
- Shell, landing, and module CSS refinements
- Tab bar, app switcher, identity, and MI component updates
- rNotes app improvements
- rFunds diagram adjustments

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 13:15:13 -08:00
Jeff Emmett 8bd899d146 fix: persist theme via html[data-theme] + theme.css custom properties
- Blocking <head> script restores canvas-theme from localStorage
  with prefers-color-scheme fallback (no FOUC)
- New theme.css with CSS custom properties for dark/light
- Removed data-theme from body/header/tab-row (now on <html>)
- Theme toggle writes to documentElement instead of body

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 11:56:51 -08:00
Jeff Emmett 4819852b14 fix: extract inline <style> blocks in tab-cache for canvas toolbar rendering
The tab cache's extractContent() only collected <link> stylesheets, missing
inline <style> blocks. The canvas toolbar CSS is entirely inline, causing
unstyled toolbar when switching to the rSpace tab via tab cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:51:35 -08:00
Jeff Emmett ebdda1e443 feat: enhanced rinbox multisig approval UI, module landing pages, help guide
- Rinbox: visual multisig approval cards with signer avatars, progress bars,
  email previews, status-colored borders, and compose-for-approval form
- Rinbox: help/guide popout with feature cards, how-it-works steps, use cases
- Rinbox: rich demo data with threaded comments, signer lists, multiple mailboxes
- Module landing pages: improved UX descriptions for rBooks, rCal, rNotes,
  rTrips, rVote, rWork with proper feature descriptions
- Added landingPage support to RSpaceModule interface and server routing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 22:05:08 -08:00
Jeff Emmett 94c5346eda fix: account completion indicators, email verify token type, SW cache
- Add /api/account/status endpoint returning email, multi-device,
  social recovery completion state
- Show red/green status dots on Account modal section headers for
  incomplete vs complete steps (email, device, recovery, data storage)
- Highlight Data Storage section with red warning when using local-only
  storage so users know they're responsible for their own data
- Fix email verification 500 error: change token type from
  'email_verification' to 'email_verify' to match DB check constraint
- Fix service worker: skip non-http(s) schemes to prevent
  chrome-extension:// cache put errors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:28:13 -08:00
Jeff Emmett 46c2a0b035 feat: layered local-first data architecture — encrypted backup, relay persistence, at-rest encryption
Implement the 4-layer data model (device → encrypted backup → shared sync → federated):

- Extract shared encryption-utils from community-store (deriveSpaceKey, AES-256-GCM, rSEN format)
- Encrypt module docs at rest when space has meta.encrypted === true
- Fix relay mode persistence: relay-backup/relay-restore wire protocol + .automerge.enc blob storage
- Add backup store + REST API (PUT/GET/DELETE /api/backup/:space/:docId) with JWT auth
- Add client BackupSyncManager with delta-only push, full restore, auto-backup
- Wire backup stubs in encryptid-bridge to BackupSyncManager
- Add rspace-backups Docker volume
- Create docs/DATA-ARCHITECTURE.md design doc with threat model and data flow diagrams

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:09:07 -08:00
Jeff Emmett 9443178d1c feat: Phase 5 — remove PostgreSQL from rForum, rSpace now fully PG-free
Migrate rForum provisioning metadata from shared PG pool to Automerge.
rForum was the last module using PostgreSQL; shared/db/pool.ts is now archived.

- Create modules/rforum/schemas.ts (ForumDoc, ForumInstance, ProvisionLog)
- Rewrite mod.ts: replace sql with Automerge getDoc/changeDoc, add onInit
- Rewrite provisioner.ts: pass SyncServer, logStep/updateInstance via changeDoc
- Fix dashboard snake_case → camelCase field references
- Archive schema.sql and shared/db/pool.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:25:26 -08:00
Jeff Emmett 88d618c1af feat: replace My Account submenu with consolidated popup modal
Consolidates email, device, recovery, postal address, data storage,
and dark mode settings into a single scrollable modal with collapsible
section cards — matching the existing My Spaces modal pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 15:22:13 -08:00
Jeff Emmett 22db2f439f feat: client-side encryption wiring + space scoping UI (Phase 5+6)
Phase 5 — EncryptID → DocCrypto bridge:
- Add EncryptedDocBridge connecting WebAuthn PRF to document encryption
- Add per-doc relay mode to SyncServer (encrypted spaces bypass participant mode)
- Wire encryption toggle to syncServer.setRelayOnly() on PATCH /:slug/encryption
- Restore relay mode for encrypted spaces on server startup
- Initialize DocBridge from PRF on login, clear on sign-out (both login-button + identity)
- Use bridge helpers for encrypted backup toggle in My Account

Phase 6 — Space scoping UI:
- Add "Modules" tab to Edit Space modal (enable/disable modules, scope toggles, encryption)
- Auto-filter app switcher by space's enabledModules via renderShell()
- Show "G" badge on global-scoped modules in app switcher
- Show lock icon in header for encrypted spaces
- Add getSpaceShellMeta() helper for auto-populating shell options

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:50:16 -08:00
Jeff Emmett b2ea5e04cf feat: unified space lifecycle & module scoping contract (Phase 0+1)
Extend RSpaceModule with scoping, lifecycle hooks (onInit, onSpaceCreate/Delete
with SpaceLifecycleContext, onSpaceEnable/Disable), and DocSchema support.
Add scoping to all 25 modules (8 space, 11 global-configurable, 6 global-fixed).
Consolidate 4 space creation endpoints into shared createSpace() function.
Add enabledModules enforcement middleware and module configuration API
(GET/PATCH /api/spaces/:slug/modules). Deprecation header on /api/communities.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:35:41 -08:00
Jeff Emmett 1f0ef59369 feat: add flow tubes, stable particle animation, and interactive port wiring
Replace invisible particle-only flow visualization with colored 3D tubes
between layers, spread horizontally to avoid overlap. Particles now travel
along tube paths. Add click-to-wire interaction on I/O port chips with
visual feedback (glow/breathe/dim). Prevent animation restart on Automerge
sync by surgically updating flow elements in-place.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 12:55:16 -08:00
Jeff Emmett 5c21b64a99 feat: add My Account submenu with dark mode + encrypted backup toggles
Reorganize user dropdown into expandable "My Account" submenu containing
account actions (Add Email, Add Device, Recovery) plus Dark Mode and
Encrypted Backup toggle switches. Move theme toggle from toolbar into
account settings, default to dark mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 12:45:11 -08:00
Jeff Emmett a402caacd8 fix: app-switcher routes through tab system + canvas fills viewport in tab pane
- App-switcher now dispatches module-select event instead of full page navigation
  for same-origin links; shell routes through TabCache for instant tab switching
- Tab pane gets height:100% in canvas-layout mode so #canvas fills the viewport
  (fixes pan/zoom not working on empty canvas background)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 12:35:38 -08:00
Jeff Emmett be271de7fb feat: add Gnosis Safe + EncryptID passkey wallet abstraction
Derive a deterministic secp256k1 EOA from the passkey's PRF output via
HKDF-SHA256, enabling hardware-backed signing for x402 micropayments and
Safe treasury proposals without storing private keys.

Key changes:
- EOA key derivation with domain-separated HKDF (eoa-derivation.ts)
- Key manager integration with PRF-only EOA path (key-derivation.ts)
- Encrypted client-side wallet store for Safe associations (wallet-store.ts)
- Passkey-backed x402 signer replacing EVM_PRIVATE_KEY (passkey-signer.ts)
- Safe propose/confirm/execute proxy routes in rwallet (mod.ts)
- Wallet capability flag in JWT via users.wallet_address (server.ts)
- Payment operation permissions: x402, safe-propose, safe-execute (session.ts)

Privacy: Safe wallet associations stored client-side only (AES-256-GCM
encrypted localStorage). Server only knows user has wallet capability.

108 tests passing across 5 test suites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 12:18:34 -08:00
Jeff Emmett 2a7071edb4 fix: use correct x402 facilitator URL (www.x402.org)
The bare domain x402.org/facilitator returns a 308 redirect that
breaks payment verification. Use www.x402.org/facilitator instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 23:39:07 -08:00
Jeff Emmett 3808b51a64 feat: strip demo pages to show just the interactive component
Demo pages now render the same clean shell as regular spaces — just the
<folk-*> component full-page, no marketing wrapper (hero, feature cards,
CTA). Descriptions belong on landing pages, not demos.

- Remove demo branch from 7 module route handlers (rcal, rcart, rfunds,
  rnotes, rtrips, rtube, rvote)
- Delete 7 demo.ts files (~1200 lines of dead markup)
- Remove renderDemoShell() and DEMO_PAGE_CSS from server/shell.ts
- Remove demoPage field from RSpaceModule interface
- Rename top rApp dropdown item from "rSpace" to "rStack"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:03:46 -08:00
Jeff Emmett a39cf6e1c2 feat: auto-provision personal spaces on first visit + redirect logged-in users from demo
Server-side middleware creates the user's personal space when they visit
{username}.rspace.online for the first time (token in cookie, verified once).
Client-side redirect sends logged-in demo users to their personal space.
"Try Demo" button sets a sessionStorage flag to bypass the redirect.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:31:32 -08:00
Jeff Emmett ef1d93d7e9 feat(encryptid): persist login across subdomains via cross-domain cookie
EncryptID sessions were lost when navigating between rspace.online
subdomains (e.g. demo→cca) because localStorage is per-origin. Now
stores a domain-wide cookie (eid_token, domain=.rspace.online, 30 days)
alongside localStorage. On new subdomain visits, the cookie is synced
to localStorage at module load time. Expired tokens are auto-refreshed
via the server before being discarded. Sign-out clears both stores.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:10:36 -08:00
Jeff Emmett a61f562bbf feat: persistent tab bar, offline save improvements, and shape validation
- Tab bar state persists to localStorage per space
- Emergency synchronous localStorage fallback for beforeunload saves
- Merge Automerge full-sync instead of replacing (preserves local changes)
- Validate shape coordinates before applying (prevent NaN/Infinity)
- Save on visibilitychange for mobile browser tab backgrounding
- Add OutputPath type for module browsable content types
- Fix canvas module ID from "canvas" to "rspace" in tab-cache

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:11:14 -08:00
Jeff Emmett c7674ac526 feat: color-coded visibility badges and contextual space display names
- Visibility badges now color-coded: green (public), yellow (permissioned),
  red (private) with matching card border tints
- Public spaces show eye icon instead of lock
- Private spaces display as "username's (you)rSpace" instead of raw name
- Applied consistently across space switcher dropdown and My Spaces modal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:42:06 -08:00
Jeff Emmett 47b585665d fix: rename rStack to rSpace in app switcher dropdown
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:35:21 -08:00
Jeff Emmett 2b58068a1a feat: persistent sessions with 30-day JWT and auto-refresh on page load
Sessions now last 30 days instead of 15 minutes. Both the rstack-identity
component and legacy header auto-refresh the token when < 7 days remain,
so users who visit at least once every ~23 days stay logged in indefinitely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:33:31 -08:00
Jeff Emmett 34877b1f9e feat: add "My Spaces" modal to identity dropdown
Adds a clickable "My Spaces" item in the profile dropdown that opens
a full-screen overlay showing all user spaces as clickable cards.
Fetches /api/spaces, splits into "Your Spaces" and "Public Spaces"
sections, with navigation via rspaceNavUrl and a "Create New Space" CTA.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:26:31 -08:00
Jeff Emmett d5563d4636 fix: pass auth token in WebSocket connections for private spaces
WebSocket clients were connecting without auth tokens, causing 401
rejections for authenticated/members_only spaces. Now reads the
encryptid_session from localStorage and appends ?token= to WS URLs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:08:07 -08:00
Jeff Emmett 1db8341fb2 feat: email forwarding via Mailcow aliases + private space access gate
Email forwarding (EncryptID):
- New mailcow.ts API client for alias CRUD via Mailcow REST API
- Schema: email_forward_enabled + email_forward_mailcow_id columns
- API endpoints: GET/POST email-forward status, enable, disable
- Profile email change hook updates/disables alias automatically
- Docker: rmail-mailcow network + MAILCOW_API_URL/KEY env vars

Private spaces:
- Access gate overlay blocks members_only spaces for unauthenticated users
- Space visibility injected into HTML via middleware
- Auto-provision creates spaces as members_only by default
- Personalized "Create {username}'s Space" CTA in space switcher
- Removed unused /notifications endpoint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:54:07 -08:00
Jeff Emmett 75b148e772 Merge branch 'dev'
# Conflicts:
#	modules/rcal/mod.ts
#	modules/rfiles/mod.ts
#	modules/rforum/mod.ts
#	modules/rmaps/mod.ts
#	modules/rnetwork/mod.ts
#	modules/rswag/mod.ts
#	modules/rwork/mod.ts
#	shared/module.ts
2026-02-28 19:51:51 -08:00
Jeff Emmett 5613370817 refactor: rename module directories to match r-prefixed module IDs
All 22 module directories under modules/ now match their module IDs
(e.g. modules/cart → modules/rcart, modules/canvas → modules/rspace).
Updated all import paths, vite build config, HTML template asset refs,
docker-compose standalone commands, and .gitignore accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:49:26 -08:00
Jeff Emmett 8895c0fb75 feat: always-visible tab close buttons + rApp dropdown shows open apps
- Tab close (×) buttons now visible at 35% opacity instead of hidden,
  brightening on hover so users can see they're clickable
- [+] dropdown now shows all rApps including already-open ones
- Already-open rApps shown dimmed with a cyan dot indicator
- Clicking an open rApp surfaces it (switches tab) instead of duplicating

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:10:08 -08:00
Jeff Emmett 29d49c7b26 feat: always-visible tab close buttons + rApp dropdown shows open apps
- Tab close (×) buttons now visible at 35% opacity instead of hidden,
  brightening on hover so users can see they're clickable
- [+] dropdown now shows all rApps including already-open ones
- Already-open rApps shown dimmed with a cyan dot indicator
- Clicking an open rApp surfaces it (switches tab) instead of duplicating

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:08:45 -08:00
Jeff Emmett abbfb552cc feat: client-side tab caching for instant tab switching
Previously loaded tabs stay in the DOM and are shown/hidden via CSS.
New tabs are fetched via fetch() + DOMParser on first visit, then
cached. Switching back is instant with no network request.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:21:10 +00:00
Jeff Emmett d9bd7557fa fix: dropdown menus use fixed positioning to escape overflow clipping
Dropdown menus in app-switcher and space-switcher were clipped by
overflow:hidden on .rstack-header__left (mobile). Changed from
position:absolute to position:fixed with dynamic getBoundingClientRect
positioning. Bumped shell asset versions to v=5 to bypass CF cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:36:18 +00:00
Jeff Emmett 08928a9f8e fix: app-switcher dropdown navigates within demo on subdomains
On demo.rspace.online, the dropdown was linking to landing pages
(rspace.online/moduleId) instead of navigating between demo pages.
Changed condition to only use landing-page links on the bare domain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:06:52 +00:00