Session was stored as { claims: { username, sub } } but getSessionInfo()
read sess.username (top-level) instead of sess.claims.username — always
falling back to "Anonymous". Fixed in all 3 locations: folk-notes-app,
comment-panel, collab-presence.
Also fixed awareness race: Yjs provider broadcast initial awareness before
user field was set, creating a ghost "anonymous" peer. Now identity is set
on awareness before provider connects, and the duplicate set is removed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Mobile toolbar collapsed position now flush with bottom-toolbar (bottom: 8px)
- Toolbar defaults to collapsed on mobile (<768px)
- Zoom expand/minimize uses distinct icons (magnifier +/-) instead of CSS rotation
- SW update banner on all pages: "New version available — Tap to update"
- Detects controllerchange + updatefound events
- Purple gradient bar, dismissible, reloads on tap
- Added to both shell.ts (module pages) and canvas.html (standalone)
- folk-rapp: filter picker/switcher by enabled modules
- server/shell: react to modules-changed event for runtime module toggling
- collab-presence: minor overlay updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Harmonize the two disconnected presence systems into one:
- New shared/collab-presence.ts utility (broadcastPresence, startPresenceHeartbeat)
- Collab overlay now listens to custom presence messages, shows module context in people panel
- Fixed Shadow DOM focus tracking using composedPath() for focus rings through shadow boundaries
- Replaced rNotes custom presence with shared utility (kept sidebar dots)
- Added presence heartbeat to all 27 rApp components with dynamic context strings
- Bumped cache versions in all modified mod.ts files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>