Commit Graph

7 Commits

Author SHA1 Message Date
Claude
be0e0bfa29 refactor: move wallet functionality to user menu
Move wallet connection and info from separate header button into
the user menu dropdown for better organization.

Changes:
- Remove standalone WalletButton component
- Add wallet section to user menu dropdown
- Show "Connect Wallet" option when no wallet is connected
- Display wallet balance and alias when connected
- Clicking wallet info opens detailed dialog with:
  - Balance (without suffix)
  - Wallet name/alias
  - Lightning address (lud16)
  - Supported NWC methods
  - Connected relay URLs
  - Disconnect button

This consolidates all user-related settings (account, relays,
blossom servers, wallet) in one consistent location.
2026-01-18 08:42:48 +00:00
Claude
4a85979922 refactor: use applesauce-wallet-connect and move wallet to header
Replace custom NWC client implementation with applesauce-wallet-connect:
- Install applesauce-wallet-connect for official NIP-47 support
- Create nwc.ts service wrapper for WalletConnect singleton
- Update NWCConnection type to match WalletConnectURI interface
- Use service/relays/secret properties instead of custom names

Move wallet display from user menu to header:
- Create standalone WalletButton component
- Add WalletButton to header next to UserMenu
- Remove wallet UI from user menu dropdown
- Show balance in header with yellow zap icon
- Clicking wallet button opens connect dialog

This provides better UX with wallet status visible in header
and uses the official applesauce implementation for reliability.
2026-01-17 22:17:12 +00:00
Alejandro
16764e1aca Display user's blossom servers in menu (#90)
* feat: Display blossom servers in user menu with caching

Implements caching and display of user's blossom server lists (kind 10063) in the user menu dropdown.

**Key Changes:**

1. **Database Schema (db.ts)**:
   - Added `CachedBlossomServerList` interface
   - Added `blossomServers` table to Dexie v15
   - Indexed by pubkey and updatedAt for efficient querying

2. **Caching Service (blossom-server-cache.ts)**:
   - Dual-layer caching: LRU memory cache (100 entries) + Dexie persistent cache
   - 24-hour TTL to reduce network requests
   - Auto-caches kind:10063 events from EventStore
   - Mirrors relay-list-cache pattern for consistency

3. **Sync Hooks**:
   - `useBlossomServerCacheSync`: Subscribes to EventStore for auto-caching kind:10063 events
   - `useAccountSync`: Extended to fetch and watch active account's blossom servers

4. **State Management**:
   - Added `blossomServers` field to `activeAccount` in GrimoireState
   - Created `setActiveAccountBlossomServers` pure function and callback
   - Reactive updates when user's server list changes

5. **User Menu UI (user-menu.tsx)**:
   - Added blossom servers section with HardDrive icon
   - Shows server count badge (e.g., "3 servers")
   - Clickable links open servers in new tabs
   - Displays only when user has configured servers

**Architecture:**
- Follows existing relay list caching pattern for consistency
- Reactive: UI auto-updates when kind:10063 events arrive
- Incremental sync: Fetches on login, caches for 24h
- Performance: Memory cache for <1ms lookups, Dexie for persistence

**Testing:**
- Build: ✓ No TypeScript errors
- Tests: ✓ All 838 tests passing

* feat: Open blossom server file lists directly from menus

**User Menu & Profile Viewer Improvements:**

1. **Enhanced Click Behavior**:
   - Clicking a blossom server now opens the file list for that server
   - Shows blobs uploaded by the user (user menu) or profile owner (profile viewer)
   - Pre-selects the clicked server in the dropdown

2. **UX Improvements**:
   - Removed server count from user menu label (cleaner UI)
   - Added `cursor-crosshair` to blossom server items (consistent with other clickable items)
   - Removed external link icon (not opening external URL anymore)

3. **Technical Changes**:
   - Updated `ListBlobsView` to accept optional `serverUrl` prop for pre-selection
   - User menu: Opens `blossom list` with `serverUrl` for active user
   - Profile viewer: Opens `blossom list` with both `pubkey` and `serverUrl`

**Flow:**
- User menu → Click server → Opens files for active user on that server
- Profile viewer → Click server → Opens files for viewed user on that server

* fix: Properly fetch blossom servers for any profile view

**Problem:**
Blossom servers were only visible for the logged-in user's profile,
not for other users' profiles being viewed.

**Solution:**
Enhanced ProfileViewer blossom server fetching with multi-layer approach:

1. **Cache-first loading**: Check blossomServerCache for instant display
2. **EventStore check**: Use existing cached event if available
3. **Reactive subscription**: Subscribe to EventStore for real-time updates
4. **Network fetch**: Use addressLoader to fetch latest from relays
5. **Auto-caching**: Update cache when new events arrive

**Benefits:**
- Blossom servers now display for ANY user's profile
- Instant display from cache (< 1ms)
- Reactive updates when data changes
- Proper cache hydration for future visits
- Consistent with relay list fetching pattern

**Technical:**
- Imported and integrated blossomServerCache service
- Added cache check before network fetch
- Separated EventStore subscription from network fetch
- Added cache updates on event arrival

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-14 14:52:16 +01:00
Alejandro
32d394b398 feat: add preview routes for Nostr identifiers (npub, nevent, note, naddr) (#33)
* feat: add preview routes for Nostr identifiers (npub, nevent, note, naddr)

This commit adds dedicated preview routes for Nostr identifiers at the root level:
- /npub... - Shows a single profile view for npub identifiers
- /nevent... - Shows a single event detail view for nevent identifiers
- /note... - Shows a single event detail view for note identifiers
- /naddr... - Redirects spellbooks (kind 30777) to /:actor/:identifier route

Key changes:
- Created PreviewProfilePage component for npub identifiers
- Created PreviewEventPage component for nevent/note identifiers
- Created PreviewAddressPage component for naddr redirects
- Added hideBottomBar prop to AppShell to hide tabs in preview mode
- Added routes to root.tsx for all identifier types

Preview pages don't show bottom tabs and don't affect user's workspace layout.

* chore: update package-lock.json

* refactor: create reusable useNip19Decode hook and improve preview pages

This commit makes the preview pages production-ready by:

1. Created useNip19Decode hook (src/hooks/useNip19Decode.ts):
   - Reusable hook for decoding NIP-19 identifiers (npub, note, nevent, naddr, nprofile)
   - Type-safe with discriminated union for decoded entities
   - Comprehensive error handling with retry functionality
   - Loading states and error messages
   - Well-documented with JSDoc comments and usage examples

2. Comprehensive test coverage (src/hooks/useNip19Decode.test.ts):
   - 11 tests covering all entity types (npub, note, nevent, naddr)
   - Tests for error handling (missing identifier, invalid format, corrupted bech32)
   - Tests for retry functionality and state changes
   - Uses jsdom environment for React hook testing
   - All tests passing ✓

3. Refactored preview pages to use the hook:
   - PreviewProfilePage: Simplified from 80 to 81 lines with cleaner logic
   - PreviewEventPage: Improved type safety and error handling
   - PreviewAddressPage: Better separation of concerns
   - All pages now have consistent error handling and retry functionality
   - Better user experience with improved error messages

4. Dependencies added:
   - @testing-library/react for React hook testing
   - @testing-library/dom for DOM testing utilities
   - jsdom and happy-dom for browser environment simulation in tests

Benefits:
- Code deduplication: Preview pages share decoding logic
- Type safety: Discriminated union prevents type errors
- Testability: Hook can be tested independently
- Maintainability: Single source of truth for NIP-19 decoding
- User experience: Consistent error handling and retry across all preview pages
- Production-ready: Comprehensive tests and error handling

* refactor: simplify useNip19Decode to synchronous with memoization

NIP-19 decoding is synchronous - removed unnecessary async complexity:

Hook changes (src/hooks/useNip19Decode.ts):
- Removed loading states (isLoading, setIsLoading)
- Removed retry functionality (unnecessary for sync operations)
- Now uses useMemo for efficient memoization
- Returns { decoded, error } instead of { decoded, isLoading, error, retry }
- Same string always yields same result (memoized)
- Went from ~120 lines to ~115 lines, but much simpler

Preview page changes:
- Removed loading spinners and states
- Removed retry buttons
- Simplified error handling
- Cleaner, more readable code
- PreviewProfilePage: 55 lines (down from 81)
- PreviewEventPage: 83 lines (down from 105)
- PreviewAddressPage: 83 lines (down from 117)

Test changes (src/hooks/useNip19Decode.test.ts):
- Removed waitFor and async/await (not needed for sync)
- Tests run faster (39ms vs 77ms - 49% improvement)
- Added memoization tests to verify caching works
- Simplified from 11 async tests to 11 sync tests
- All 11 tests passing ✓

Benefits:
- Simpler mental model: decode happens instantly
- Better performance: no state updates, just memoization
- Easier to test: synchronous tests are simpler
- More correct: matches the actual synchronous nature of nip19.decode()
- Less code: removed ~150 lines of unnecessary complexity

* feat: show detail view for all addressable events in naddr preview

Previously, PreviewAddressPage only handled spellbooks (kind 30777) and
showed errors for other addressable events. Now:

- Spellbooks (kind 30777): Redirect to /:actor/:identifier (existing behavior)
- All other addressable events: Show in EventDetailViewer

This enables previewing any addressable event (long-form articles, live
events, community posts, etc.) via naddr links.

Changes:
- Import EventDetailViewer
- Removed error state for non-spellbook kinds
- Show EventDetailViewer with AddressPointer for all other kinds
- Simplified from 83 lines to 77 lines

* fix: correct route patterns for NIP-19 identifier previews

The previous route patterns (/npub:identifier) conflicted with the catch-all
/:actor/:identifier route and didn't properly match NIP-19 identifiers.

Fixed by:
1. Using wildcard routes with correct prefixes:
   - /npub1* (not /npub:identifier)
   - /nevent1* (not /nevent:identifier)
   - /note1* (not /note:identifier)
   - /naddr1* (not /naddr:identifier)

2. Updated preview components to use params['*'] for wildcard capture:
   - Reconstruct full identifier as prefix + captured part
   - e.g., npub1 + params['*'] = npub107jk7htfv...

This ensures routes properly match before the catch-all /:actor/:identifier
route and correctly capture the full bech32-encoded identifier.

Test URL: /npub107jk7htfv243u0x5ynn43scq9wrxtaasmrwwa8lfu2ydwag6cx2quqncxg

* style: apply prettier formatting

* fix: use loader-based routing for NIP-19 identifiers in React Router v7

Previous attempts using wildcard routes didn't work properly in React Router v7.

Solution:
- Single /:identifier route with a loader that validates NIP-19 prefixes
- Loader throws 404 if identifier doesn't start with npub1/note1/nevent1/naddr1
- Created Nip19PreviewRouter component that routes to correct preview page
- Routes are properly ordered: /:identifier before /:actor/:identifier catch-all

This ensures /npub107jk... routes to profile preview, not spellbook route.

Benefits:
- Simpler routing configuration (1 route vs 4 duplicate routes)
- Proper validation via loader
- Clean separation of concerns with router component
- Works correctly in React Router v7

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-04 20:12:48 +01:00
Alejandro Gómez
e7a7bb05a4 feat: clickable spell and spellbook links 2025-12-22 12:38:37 +01:00
Claude
470c802364 fix: ensure compact previews properly truncate RichText to single line
- Add line-clamp-1 to all compact preview components for consistent truncation
- Fix DefaultCompactPreview, GenericRepostCompactPreview, ZapCompactPreview
- Fix Kind1111Renderer parent event preview truncation
- Apply auto-formatting fixes from linter
2025-12-22 09:38:27 +00:00
Alejandro Gómez
3c62a0e236 ui: share spellbook dialog improvements 2025-12-21 22:18:37 +01:00