Commit Graph

323 Commits

Author SHA1 Message Date
Jeff Emmett 11e39f0179 fix: use tldraw tick event for synchronous pinned shape updates
Replace requestAnimationFrame polling with tldraw's 'tick' event which
fires synchronously with the render cycle. This ensures the pinned shape
position is updated BEFORE rendering, eliminating the visual lag where
the shape appeared to "chase" the camera during zooming.

Changes:
- Use editor.on('tick') instead of requestAnimationFrame polling
- Remove throttling (no longer needed with tick event)
- Reduce position tolerance from 0.5 to 0.01 for more precise tracking
- Simplify code by removing unnecessary camera tracking refs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 20:12:08 -05:00
Jeff Emmett a5e097f786 fix: prevent ValidationError by not setting undefined values in shape.meta
When unpinning a shape, the previous code set pinnedAtZoom, originalX, and
originalY to undefined in shape.meta. This caused a ValidationError because
tldraw requires JSON serializable values (undefined is not valid JSON).

Fixed by using object destructuring to exclude these properties from meta
instead of setting them to undefined.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 20:04:55 -05:00
Jeff Emmett 125ebacc00 fix: improve pinned shape zoom behavior - maintain constant visual size
- Pinned shapes now stay exactly the same size visually during zoom
- Uses CSS transform scale instead of changing w/h props
- Content inside shapes renders identically at all zoom levels
- Stores pinnedAtZoom in shape.meta for reference
- Returns to original position smoothly when unpinned
- Removed size-changing logic that was causing content reflow issues

The transform approach ensures text, UI elements, and all content
inside pinned shapes remain pixel-perfect regardless of canvas zoom.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 20:00:29 -05:00
Jeff Emmett 156dc4562c refactor: reorder context menu and remove Collections
- Move "Create Tool" to top of context menu
- Move "Shortcut to Frames" to second position
- Remove "Collections" submenu (functionality still available via keyboard shortcuts)
- Cleaner menu structure prioritizing creation tools

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 19:49:35 -05:00
Jeff Emmett 8d333510d5 feat: replace MycrozineTemplate with MycroZineGenerator in toolbar and context menu
- Updated CustomToolbar.tsx to use MycroZineGenerator tool
- Updated CustomContextMenu.tsx to use MycroZineGenerator in Create Tool submenu
- Updated overrides.tsx with MycroZineGenerator tool definition
- Removed all references to old MycrozineTemplate

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 19:44:08 -05:00
Jeff Emmett 04d6859b8a feat: add MycroZine Generator shape with 5-phase workflow
Implements interactive 8-page zine creation tool:
- Phase 1: Ideation - chat UI for topic/content planning
- Phase 2: Drafts - generates 8 pages, spawns on canvas
- Phase 3: Feedback - approve/edit individual pages
- Phase 4: Finalizing - regenerate pages with feedback
- Phase 5: Complete - print layout download, template save

Features:
- Style selector (punk-zine, minimal, collage, retro, academic)
- Tone selector (rebellious, playful, informative, poetic)
- Chat-based ideation workflow
- Page grid with approval/feedback UI
- LocalStorage template persistence
- Punk green (#00ff00) theme

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 19:35:28 -05:00
Jeff Emmett 2a3406e8c4 fix: improve backwards compatibility for older JSON imports
- Add validation for highlight shapes (same as draw)
- Improve segment validation to check for NaN/Infinity in point coordinates
- Add more custom shape types to valid shapes list
- Fix arrow shape validation (use start/end props instead of points array)
- Fix line shape validation (uses object format for points, not array)
- Better error messages for invalid shapes

Prevents "No nearest point found" errors when importing older files
with malformed path geometry data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 19:13:20 -05:00
Jeff Emmett 0753656c9a perf: optimize bundle size with lazy loading and dependency removal
- Add route-level lazy loading for all pages (Default, Board, Dashboard, etc.)
- Remove gun, webnative, holosphere dependencies (175 packages removed)
- Stub HoloSphereService for future Nostr integration (keeps h3-js for holon calculations)
- Stub FileSystemContext (webnative removed)
- Defer Daily.co initialization until needed
- Add loading spinner for route transitions
- Remove large-utils manual chunk from vite config

Initial page load significantly reduced - heavy Board component (7.5MB)
now loads on-demand instead of upfront.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 18:59:52 -05:00
Jeff Emmett 2d9d216bc7 feat: re-enable Map tool and add GPS location sharing
- Re-enable Map tool in CustomToolbar and CustomContextMenu
- Add GPS location sharing state and UI to MapShapeUtil
- Show collaborator locations on map with colored markers
- Add toggle button to share/stop sharing your location
- Cleanup GPS watch and markers on component unmount

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 18:39:26 -05:00
Jeff Emmett df80a3f616 fix: resolve user identity caching issues on logout/login
- Preserve tldraw-user-id-* and crypto keys on logout (prevents duplicate cursors)
- Add session-logged-in event for immediate tool enabling after login
- Add session-cleared event for component state cleanup
- Clear only session-specific data (permissions, graph cache, room ID)
- CryptIDDropdown: reset connections state on logout
- useNetworkGraph: clear graph cache on logout

The key fix is preserving tldraw user IDs across login/logout cycles.
Previously, clearing these IDs caused each login to create a new presence
record while old ones persisted in Automerge, resulting in stacked cursors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 18:34:41 -05:00
Jeff Emmett 0a95c31974 feat: improve keyboard shortcuts UI with Command Palette
- Add openCommandPalette() export function for manual triggering
- Update ? button to open the colorful Command Palette modal instead of dropdown
- Add support for manual opening with Escape and click-outside to close
- Clean up unused shortcut dropdown code and state
- Maintain Ctrl+Shift hold behavior for quick access

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 16:31:35 -05:00
Jeff Emmett 3f71222bf9 feat: integrate board protection settings into existing settings dropdown
- Remove separate BoardSettingsDropdown button from UI panel
- Add board protection toggle and editor management to existing settings dropdown
- Show protection section only for admins (board owner or global admin)
- Add ability to toggle view-only mode for protected boards
- Add editor management UI with invite and remove functionality
- Fix TypeScript type annotations for API responses

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 13:05:45 -05:00
Jeff Emmett a178623e42 feat: add BoardSettingsDropdown to top-right UI panel
Added the board settings dropdown between ShareBoardButton and StarBoardButton.
Provides access to:
- Board protection toggle (view-only mode)
- Editor management for protected boards
- Admin request functionality

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 12:54:12 -05:00
Jeff Emmett 2fe96faf53 feat: flip permissions model - everyone edits by default, protected boards opt-in
NEW PERMISSION MODEL:
- All users (including anonymous) can now EDIT by default
- Boards can be marked as "protected" by admin - only listed editors can edit
- Global admins (jeffemmett@gmail.com) have admin on ALL boards
- Added BoardSettingsDropdown with view-only toggle for admins

Backend changes:
- Added is_protected column to boards table
- Added global_admins table
- New getEffectivePermission logic prioritizes: token > global admin > owner > protection status
- New API endpoints: /auth/global-admin-status, /admin/request, /boards/:id/info, /boards/:id/editors
- Admin request sends email via Resend API

Frontend changes:
- BoardSettingsDropdown component with protection toggle and editor management
- Updated AuthContext and Board.tsx to default to 'edit' permission
- isReadOnly now only true for protected boards where user is not an editor

Task: task-052

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 12:43:14 -05:00
Jeff Emmett 91093f706f feat: add Drawfast tool, improve share UI, and various UI enhancements
New features:
- Add Drawfast tool and shape for quick drawing
- Add useLiveImage hook for real-time image generation
- Improve ShareBoardButton with better UI and functionality

UI improvements:
- Refactor CryptIDDropdown for cleaner interface
- Enhance components.tsx with better tool visibility handling
- Add context menu and toolbar enhancements
- Update MycelialIntelligenceBar styling

Backend:
- Add board permissions API endpoints
- Update worker with new networking routes
- Add html2canvas dependency

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 00:03:12 -05:00
Jeff Emmett 626920966a feat: improve social network presence handling and cleanup
- Add "(you)" indicator on tooltip when hovering current user's node
- Ensure current user always appears in graph even with no connections
- Add new participants immediately to graph (no 30s delay)
- Implement "leave" message protocol for presence cleanup:
  - Client sends leave message before disconnecting
  - Server broadcasts leave to other clients on disconnect
  - Clients remove presence records on receiving leave
- Generate consistent user colors from CryptID username (not session ID)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-15 00:01:28 -05:00
Jeff Emmett 4df9e42e4e feat: add offline storage fallback for browser reload
When the browser reloads without network connectivity, the canvas now
automatically loads from local IndexedDB storage and renders the last
known state.

Changes:
- Board.tsx: Updated render condition to allow rendering when offline
  with local data (isOfflineWithLocalData flag)
- useAutomergeStoreV2: Added isNetworkOnline parameter and offline fast
  path that immediately loads records from Automerge doc without waiting
  for network patches
- useAutomergeSyncRepo: Passes isNetworkOnline to useAutomergeStoreV2
- ConnectionStatusIndicator: Updated messaging to clarify users are
  viewing locally cached canvas when offline

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 23:57:26 -05:00
Jeff Emmett e4b767625c feat: add user dropdown menu, fix auth tool visibility, improve network graph
- Add dropdown menu when clicking user nodes in network graph with options:
  - Connect with <username>
  - Navigate to <username> (pan to cursor)
  - Screenfollow <username> (follow camera)
  - Open <username>'s profile
- Fix tool visibility for logged-in users (timing issue with read-only mode)
- Fix 401 errors by correcting localStorage key from 'cryptid_session' to 'canvas_auth_session'
- Remove "(anonymous)" suffix from usernames in tooltips
- Simplify node colors to use user's profile/presence color
- Clear permission cache on logout to prevent stale state
- Various UI improvements to auth components and network graph

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 18:41:53 -05:00
Jeff Emmett 195cc7f86e feat: add version history, Resend email, CryptID registration flow
- Switch email service from SendGrid to Resend
- Add multi-step CryptID registration with passwordless explainer
- Add email backup for multi-device account access
- Add version history API endpoints (history, snapshot, diff, revert)
- Create VersionHistoryPanel UI with diff visualization
  - Green highlighting for added shapes
  - Red highlighting for removed shapes
  - Purple highlighting for modified shapes
- Fix network graph connect/trust buttons
- Enhance CryptID dropdown with better integration buttons
- Add Obsidian vault connection modal

🤖 Generated with [Claude Code](https://claude.ai/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-10 14:21:50 -08:00
Jeff Emmett b6af3ecba8 feat: improve mobile touch/pen interactions across custom tools
- Add onTouchStart/onTouchEnd handlers to all interactive elements
- Add touchAction: 'manipulation' CSS to prevent 300ms click delay
- Increase minimum touch target sizes to 44px for accessibility
- Fix ImageGen: Generate button, Copy/Download/Delete, input field
- Fix VideoGen: Upload, URL input, prompt, duration, Generate button
- Fix Transcription: Start/Stop/Pause buttons, textarea, Save/Cancel
- Fix Multmux: Create Session, Refresh, session list, input fields

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 10:27:44 -08:00
Jeff Emmett b4c4d36e56 feat: add maximize button to all tool shapes
Add useMaximize hook to all shapes using StandardizedToolWrapper:
- MapShapeUtil, MultmuxShapeUtil, MarkdownShapeUtil
- ObsNoteShapeUtil, ImageGenShapeUtil, VideoGenShapeUtil
- HolonShapeUtil, PromptShapeUtil, EmbedShapeUtil
- FathomMeetingsBrowserShapeUtil, FathomNoteShapeUtil
- HolonBrowserShapeUtil, ObsidianBrowserShapeUtil
- TranscriptionShapeUtil, VideoChatShapeUtil

All tools now have maximize/fullscreen functionality via the
standardized header bar.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 01:02:57 -08:00
Jeff Emmett 7420d18d36 feat: add maximize button to StandardizedToolWrapper
- Add maximize/fullscreen button to standardized header bar
- Create useMaximize hook for shape utils to enable fullscreen
- Shape fills viewport when maximized, restores on Esc or toggle
- Implement on ChatBoxShapeUtil as example (other shapes can add easily)
- Button shows ⤢ for maximize, ⊡ for exit fullscreen

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 00:51:23 -08:00
Jeff Emmett 351e437ec1 fix: offline-first loading from IndexedDB when server is down
- Remove blocking await adapter.whenReady() that prevented offline mode
- Load from IndexedDB immediately without waiting for network
- Set handle and mark as ready BEFORE network sync for instant UI
- Background server sync with 5-second timeout
- Continue with local data if network is unavailable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 00:48:02 -08:00
Jeff Emmett a6b3024a99 feat: add invite/share feature with QR code, URL, NFC, and audio connect
- Add InviteDialog component with tabbed interface for sharing boards
- Add ShareBoardButton component to toolbar
- Integrate qrcode.react for QR code generation
- Implement Web NFC API for NFC tag writing
- Add placeholder for audio connect feature (coming soon)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 05:35:30 +01:00
Jeff Emmett 6d8180cf40 feat: unified top-right menu with grey oval container
- Created single grey oval container for all top-right menu items
- Order: CryptID -> Star -> Gear -> Question mark
- Added vertical separator lines between each menu item
- Consistent styling with rounded container and subtle shadow
- Removed separate styling for individual buttons

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 17:17:17 -08:00
Jeff Emmett 24f298e195 feat: dark theme social network graph with arrows + responsive MI bar
Social Network Graph:
- Dark/black theme with semi-transparent background
- Arrow markers on edges showing connection direction
- Color-coded arrows: grey (default), yellow (connected), green (trusted)
- Updated header, stats, and icon button colors for dark theme

MI (Mycelial Intelligence) Bar:
- Responsive width: full width on mobile, percentage on narrow, fixed on desktop
- Position: moves to bottom on mobile (above toolbar), stays at top on desktop
- Smooth transitions when resizing
- Smaller max height on mobile (300px vs 400px)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 17:09:33 -08:00
Jeff Emmett f921c5229a fix: graceful fallback for network graph API errors + Map fixes
Network Graph:
- Add graceful fallback when API returns 401 or other errors
- Falls back to showing room participants as nodes
- Prevents error spam in console for unauthenticated users

Map Shape (linter changes):
- Add isFetchingNearby state for loading indicator
- Improve addAnnotation to accept name/color options
- Add logging for Find Nearby debugging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 16:47:19 -08:00
Jeff Emmett 8123f0fadd feat: redesign top-right UI, fix Map interactions and schema validation
UI Changes:
- Add CryptIDDropdown component with Google integration under Integrations
- Remove user presence avatars (moved to network graph)
- New top-right layout: CryptID -> Star -> Gear dropdown -> Question mark
- Settings gear shows dropdown with dark mode toggle + All Settings link
- Network graph label changed to "Social Network"
- Network graph shows for all users including anonymous
- Solo users see themselves as a lone node

Map Shape Fixes:
- Fix stale closure bug: tool clicks now work using activeToolRef
- Fix wheel scroll: native event listener prevents tldraw capture
- Add pointerEvents: 'auto' to map container for proper mouse interaction

Bug Fix:
- Add Map shape sanitization in AutomergeToTLStore for pinnedToView/isMinimized
- Prevents "Expected boolean, got undefined" errors on old Map data

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 15:21:48 -08:00
Jeff Emmett ee3ec16cb6 feat: add StandardizedToolWrapper and fix map interactions
- Wrap map component in StandardizedToolWrapper with header bar
- Add onPointerDown={stopPropagation} to all sidebar interactive elements
- Add handleMapWheel that forwards wheel zoom to map component
- Add pinnedToView, tags, isMinimized props for consistency
- Fix TypeScript type for stopPropagation handler

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 12:44:48 -08:00
Jeff Emmett e8984a757b fix: enable open-mapping module with TypeScript fixes
- Fix unused parameter errors (prefix with underscore)
- Fix TrustCircleManager API: add getTrustLevel/setTrustLevel methods
- Fix MyceliumNetwork method calls: addNode→createNode, addHypha→createHypha
- Fix createCommitment signature to use CommitmentParams object
- Fix GeohashCommitment type with proper geohash field
- Fix PRECISION_CELL_SIZE usage (returns {lat,lng} object)
- Add type assertions for fetch response data
- Fix MapCanvas attributionControl type
- Fix GPSCollaborationLayer markerStyle merge with defaults
- Update MapShapeUtil with better event handling:
  - Raise z-index to 10000 for all map buttons
  - Add pointerEvents: auto for button clickability
  - Add handleWheel with preventDefault to enable map zoom
  - Add capturePointerEvents for proper interaction

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 11:48:49 -08:00
Jeff Emmett ecb3dfd646 fix: MapShapeUtil cleanup errors and schema validation
- Add isMountedRef to track component mount state
- Fix map initialization cleanup with named event handlers
- Add try/catch blocks for all MapLibre operations
- Fix style change, resize, and annotations effects with mounted checks
- Update callbacks (observeUser, selectSearchResult, findNearby) with null checks
- Add legacy property support (interactive, showGPS, showSearch, showDirections, sharingLocation, gpsUsers)
- Prevents 'getLayer' and 'map' undefined errors during component unmount
- Complete Mapus-style UI with sidebar, search, find nearby, annotations, and drawing tools

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 22:42:59 -08:00
Jeff Emmett 71c0059c9a feat: add canvas users to CryptID connections dropdown
Shows all collaborators currently on the canvas with their connection status:
- Green border: Trusted (edit access)
- Yellow border: Connected (view access)
- Grey border: Not connected

Users can:
- Add unconnected users as Connected or Trusted
- Upgrade Connected users to Trusted
- Downgrade Trusted users to Connected
- Remove connections

Also fixes TypeScript errors in networking module.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 23:08:16 -08:00
Jeff Emmett fab58aead0 fix: correct networking imports and API response format
- Fix useSession → useAuth import (matches actual export)
- Fix GraphEdge properties: source/target instead of fromUserId/toUserId
- Add missing trustLevel, effectiveTrustLevel to edge response
- Add myConnections to NetworkGraph type
- Prefix unused myConnections param with underscore

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-05 22:51:58 -08:00
Jeff Emmett 30608dfdc8 feat: integrate read-only mode for board permissions
- Add permission fetching and state management in Board.tsx
- Fetch user's permission level when board loads
- Set tldraw to read-only mode when user has 'view' permission
- Show AnonymousViewerBanner for unauthenticated users
- Banner prompts CryptID sign-up with your specified messaging
- Update permission state when user authenticates
- Wire up permission API routes in worker/worker.ts
  - GET /boards/:boardId/permission
  - GET /boards/:boardId/permissions (admin)
  - POST /boards/:boardId/permissions (admin)
  - DELETE /boards/:boardId/permissions/:userId (admin)
  - PATCH /boards/:boardId (admin)
- Add X-CryptID-PublicKey to CORS allowed headers
- Add PUT, PATCH, DELETE to CORS allowed methods

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-05 22:45:31 -08:00
Jeff Emmett c00106e2b7 feat: implement user permissions system (view/edit/admin)
Phase 1 of user permissions feature:
- Add board permissions schema to D1 database
  - boards table with owner, default_permission, is_public
  - board_permissions table for per-user permissions
- Add permission types (PermissionLevel) to worker and client
- Implement permission API handlers in worker/boardPermissions.ts
  - GET /boards/:boardId/permission - check user's permission
  - GET /boards/:boardId/permissions - list all (admin only)
  - POST /boards/:boardId/permissions - grant permission (admin)
  - DELETE /boards/:boardId/permissions/:userId - revoke (admin)
  - PATCH /boards/:boardId - update board settings (admin)
- Update AuthContext with permission fetching and caching
  - fetchBoardPermission() - fetch and cache permission for a board
  - canEdit() - check if user can edit current board
  - isAdmin() - check if user is admin for current board
- Create AnonymousViewerBanner component with CryptID signup prompt
- Add CSS styles for anonymous viewer banner
- Fix automerge sync manager to flush saves on peer disconnect

Permission levels:
- view: Read-only, cannot create/edit/delete shapes
- edit: Can modify board contents
- admin: Full access + permission management

Next steps:
- Integrate with Board component for read-only mode
- Wire up permission checking in Automerge sync
- Add permission management UI for admins

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-05 22:27:12 -08:00
Jeff Emmett d49f7486e2 chore: exclude open-mapping from build, fix TypeScript errors
- Add src/open-mapping/** to tsconfig exclude (21K lines, to harden later)
- Delete MapShapeUtil.backup.tsx
- Fix ConnectionStatus type in OfflineIndicator
- Fix data type assertions in MapShapeUtil (routing/search)
- Fix GoogleDataService.authenticate() call with required param
- Add ts-expect-error for Automerge NetworkAdapter 'ready' event
- Add .wasm?module type declaration for Wrangler imports
- Include GPS location sharing enhancements in MapShapeUtil

TypeScript now compiles cleanly. Vite build needs NODE_OPTIONS for memory.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 12:16:29 -08:00
Jeff Emmett e778e20bae chore: add D1 database ID and refactor MapShape
- Add production D1 database ID for cryptid-auth
- Refactor MapShapeUtil for cleaner implementation
- Add map layers module
- Update UI components

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 21:32:46 -08:00
Jeff Emmett 9b06bfadb3 Merge feature/open-mapping: Automerge CRDT sync and open-mapping module
Key changes:
- Automerge CRDT infrastructure for offline-first sync
- Open-mapping collaborative route planning module
- MapShape integration with canvas
- Connection status indicator
- Binary document persistence in R2
- Resolved merge conflicts with PrivateWorkspace feature

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 19:48:38 -08:00
Jeff Emmett 856bfa8e9b feat: implement binary Automerge CRDT sync and open-mapping module
Binary Automerge Sync:
- CloudflareAdapter: binary sync messages with documentId tracking
- Message buffering for early server messages before documentId set
- Worker sends initial sync on WebSocket connect
- Removed JSON HTTP POST sync in favor of native Automerge protocol
- Multi-client binary sync verified working

Worker CRDT Infrastructure:
- automerge-init.ts: WASM initialization for Cloudflare Workers
- automerge-sync-manager.ts: sync state management per peer
- automerge-r2-storage.ts: binary document persistence to R2
- AutomergeDurableObject: integrated CRDT sync handling

Open Mapping Module:
- Collaborative map component with real-time sync
- MapShapeUtil for tldraw canvas integration
- Presence layer with location sharing
- Privacy system with ZK-GPS protocol concepts
- Mycelium network for organic route visualization
- Conic sections for map projection optimization
- Discovery system (spores, hunts, collectibles, anchors)
- Geographic transformation utilities

UI Updates:
- ConnectionStatusIndicator for offline/sync status
- Map tool in toolbar
- Context menu updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 19:45:02 -08:00
Jeff Emmett 8892a9cf3a feat: add Google integration to user dropdown and keyboard shortcuts panel
- Add Google Workspace integration directly in user dropdown (CustomPeopleMenu)
  - Shows connection status (Connected/Not Connected)
  - Connect button to trigger OAuth flow
  - Browse Data button to open GoogleExportBrowser modal
- Add toggleable keyboard shortcuts panel (? icon)
  - Shows full names of tools and actions with their shortcuts
  - Organized by category: Tools, Custom Tools, Actions, Custom Actions
  - Toggle on/off by clicking, closes when clicking outside
- Import GoogleExportBrowser component for data browsing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 19:21:21 -08:00
Jeff Emmett 09bce4dd94 feat: implement Phase 5 - permission flow and drag detection for data sovereignty
- Add VisibilityChangeModal for confirming visibility changes
- Add VisibilityChangeManager to handle events and drag detection
- GoogleItem shapes now dispatch visibility change events on badge click
- Support both local->shared and shared->local transitions
- Auto-detect when GoogleItems are dragged outside PrivateWorkspace
- Session storage for "don't ask again" preference

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 17:59:58 -08:00
Jeff Emmett 84c6bf834c feat: Add GoogleItemShape with privacy badges (Phase 4)
Privacy-aware item shapes for Google Export data:

- GoogleItemShapeUtil: Custom shape for Google items with:
  - Visual distinction: dashed border + shaded overlay for LOCAL items
  - Solid border for SHARED items
  - Privacy badge (🔒 local, 🌐 shared) in top-right corner
  - Click badge to trigger visibility change (Phase 5)
  - Service icon, title, preview, date display
  - Optional thumbnail support for photos
  - Dark mode support

- GoogleItemTool: Tool for creating GoogleItem shapes

- Updated ShareableItem type to include `service` and `thumbnailUrl`

- Updated usePrivateWorkspace hook to create GoogleItem shapes
  instead of placeholder text shapes

Items added from GoogleExportBrowser now appear as proper
GoogleItem shapes with privacy indicators inside the workspace.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 17:52:54 -08:00
Jeff Emmett 052c98417d feat: Add Private Workspace zone for data sovereignty (Phase 3)
- PrivateWorkspaceShapeUtil: Frosted glass container shape with:
  - Dashed indigo border for visual distinction
  - Pin/collapse/close buttons in header
  - Dark mode support
  - Position/size persistence to localStorage
  - Helper functions for zone detection

- PrivateWorkspaceTool: Tool for creating workspace zones

- usePrivateWorkspace hook:
  - Creates/toggles workspace visibility
  - Listens for 'add-google-items-to-canvas' events
  - Places items inside the private zone
  - Persists visibility state

- PrivateWorkspaceManager: Headless component that manages
  workspace lifecycle inside Tldraw context

Items added from GoogleExportBrowser will now appear in the
Private Workspace zone as placeholder text shapes (Phase 4
will add proper GoogleItemShape with visual badges).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 16:54:27 -08:00
Jeff Emmett 33f5dc7e7f refactor: Rename GoogleDataBrowser to GoogleExportBrowser
- Rename component file and interface for consistent naming
- Update all imports and state variables in UserSettingsModal
- Better reflects the purpose as a data export browser

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 16:46:10 -08:00
Jeff Emmett a754ffab57 feat(components): add GoogleDataBrowser popup modal
Phase 2 of Data Sovereignty Zone implementation:
- Create GoogleDataBrowser component with service tabs (Gmail, Drive, Photos, Calendar)
- Searchable item list with checkboxes for multi-select
- Select All/Clear functionality
- Dark mode support with consistent styling
- "Add to Private Workspace" button
- Privacy note explaining local-only encryption
- Emits 'add-google-items-to-canvas' event for Board.tsx integration

Integration with UserSettingsModal:
- Import and render GoogleDataBrowser when "Open Data Browser" clicked
- Handler for adding selected items to canvas

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 16:40:52 -08:00
Jeff Emmett c9c8c008b2 feat(settings): add Google Workspace integration card
Phase 1 of Data Sovereignty Zone implementation:
- Add Google Workspace section to Settings > Integrations tab
- Show connection status, import counts (emails, files, photos, events)
- Connect/Disconnect Google account buttons
- "Open Data Browser" button (Phase 2 will implement the browser)
- Add getStoredCounts() and getInstance() to GoogleDataService

Privacy messaging: "Your data is encrypted with AES-256 and stored
only in your browser. Choose what to share to the board."

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 16:33:39 -08:00
Jeff Emmett 8bc3924a10 Merge origin/main into feature/google-export
Bring in all the latest changes from main including:
- Index validation and migration for tldraw shapes
- UserSettingsModal with integrations tab
- CryptID authentication updates
- AI services (image gen, video gen, mycelial intelligence)
- Automerge sync improvements
- Various UI improvements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 16:29:34 -08:00
Jeff Emmett e69ed0e867 feat: implement Google Data Sovereignty module for local-first data control
Core modules:
- encryption.ts: WebCrypto AES-256-GCM, HKDF key derivation, PKCE utilities
- database.ts: IndexedDB schema for gmail, drive, photos, calendar
- oauth.ts: OAuth 2.0 PKCE flow with encrypted token storage
- share.ts: Create tldraw shapes from encrypted data
- backup.ts: R2 backup service with encrypted manifest

Importers:
- gmail.ts: Gmail import with pagination and batch storage
- drive.ts: Drive import with folder navigation, Google Docs export
- photos.ts: Photos thumbnail import (403 issue pending investigation)
- calendar.ts: Calendar import with date range filtering

Test interface at /google route for debugging OAuth flow.

Known issue: Photos API returning 403 on some thumbnail URLs - needs
further investigation with proper OAuth consent screen setup.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 15:22:40 -08:00
Jeff Emmett 8cda0d4e28 Merge main into feature/open-mapping, resolve conflicts 2025-12-04 06:51:35 -08:00
Jeff Emmett 8dac699acf Merge branch 'main' into feature/open-mapping 2025-12-04 06:50:37 -08:00