Commit Graph

4 Commits

Author SHA1 Message Date
Alejandro Gómez
dc4345a64b perf: Make NIP-17 inbox sync on-demand for optimal login performance
This commit eliminates automatic inbox initialization on login, preventing
unwanted network requests and heavy I/O operations. Inbox sync now only
activates when users explicitly enable it.

## Problem

When logging in, the app would automatically:
- Initialize gift wrap service immediately
- Auto-enable inbox sync without user consent
- Load encrypted content from Dexie
- Wait up to 1 second for cache readiness
- Fetch inbox relay lists from network
- Subscribe to gift wrap events
- Open persistent relay connections

This caused:
- App hangs during login (network/IO blocking)
- Unwanted network activity before user opts in
- Poor performance on initial load
- Unnecessary resource consumption when DMs not needed

## Solution

### 1. On-Demand Initialization (useAccountSync.ts)
**Before**: Auto-init and auto-enable on every login
**After**: Watch settings$ and only init when user enables

```typescript
// Only initialize when user explicitly enables inbox sync
const settingsSub = giftWrapService.settings$.subscribe((settings) => {
  if (settings.enabled && giftWrapService.userPubkey !== pubkey) {
    giftWrapService.init(pubkey, signer);
  }
});
```

### 2. Early Exit for Disabled State (gift-wrap.ts)
**Before**: Always loaded cache and relays, then checked enabled flag
**After**: Check enabled FIRST, exit early if disabled

```typescript
async init(pubkey: string, signer: ISigner | null) {
  // Set basic properties
  this.userPubkey = pubkey;
  this.signer = signer;

  // Early exit if disabled (prevents expensive operations)
  if (!this.settings$.value.enabled) {
    return;
  }

  // Only do expensive operations when enabled
  await getStoredEncryptedContentIds();
  await this.waitForCacheReady();
  this.loadInboxRelays();
  // ...
}
```

### 3. Updated Documentation
- Clarified on-demand initialization flow
- Updated lifecycle documentation with performance notes
- Changed "auto-enable" section to "on-demand" section

## Performance Impact

**Login Performance**:
-  No automatic Dexie reads
-  No cache waiting (up to 1s saved)
-  No network requests for inbox relays
-  No relay subscriptions until needed
-  Instant login when DMs not needed

**User Control**:
- Users explicitly opt-in via InboxViewer toggle
- Clear UI feedback about enabling inbox sync
- No surprise network activity

**When Enabled**:
- Full functionality identical to before
- All optimizations from previous commits preserved

## Testing

-  All 864 tests pass
-  Build succeeds with no errors
-  Verified on-demand initialization flow
-  Confirmed no auto-init on login

## Files Changed

- `src/hooks/useAccountSync.ts` - Watch settings, init only when enabled
- `src/services/gift-wrap.ts` - Early exit if disabled, expose userPubkey
- `src/components/InboxViewer.tsx` - Updated comments
- `docs/gift-wrap-architecture.md` - Updated flow and lifecycle docs

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 17:04:05 +01:00
Alejandro Gómez
cfeb40f42d fix: Improve NIP-17 inbox relay detection and UX
This commit refines the NIP-17 encrypted messaging implementation with
better relay detection, cleaner UI, and comprehensive documentation.

## Core Fixes

### 1. Fix Missing User Inbox Relays (nip-17-adapter.ts)
- **Problem**: When creating conversations, user's own inbox relays were
  only checked from cache, not actively fetched if cache was empty
- **Result**: Send failures with "missing relays" even when relays were
  fetched and connected elsewhere
- **Solution**: Actively fetch user's inbox relays if cache is empty,
  with fallback to cached value for performance
- **Impact**: Reliable relay detection for sending messages

### 2. Improve View-Only Detection (ChatViewer.tsx)
- **Problem**: Used stale `unreachableParticipants` metadata set at
  conversation creation time, causing false warnings even after relay
  lists loaded
- **Solution**: Added dynamic `canSendMessage` useMemo that checks
  current state of `participantInboxRelays` in real-time
- **Impact**: Send button correctly enables/disables as relay lists load

### 3. Cleaner UI (ChatViewer.tsx)
- Removed large yellow warning banners about view-only mode
- Removed "Sending disabled - waiting for relay lists" text in composer
- Send button now simply disables when relay lists are missing
- **Impact**: Less intrusive, cleaner messaging interface

## Additional Improvements

### Cache Readiness Check (gift-wrap.ts)
- Added `waitForCacheReady()` to prevent race condition on page reload
- Waits up to 1s for encrypted content cache to be accessible before
  processing conversations
- **Impact**: Fixes "inbox appears empty" issue on page reload

### Simplified Event Caching (nip-17-adapter.ts)
- Removed redundant `syntheticEventCache` WeakMap
- Uses eventStore as single source of truth with O(1) lookup
- **Impact**: Reduced complexity, eventStore already handles deduplication

### Removed Self-Chat Workaround (nip-17-adapter.ts)
- Deleted 70-line custom gift wrap construction for self-chat
- Applesauce's `SendWrappedMessage` works fine for self-chat
- **Impact**: Cleaner code, better maintainability

### Debug Logging System (dm-debug.ts - NEW)
- Added dedicated DM debug logging utilities
- Enable with: `localStorage.setItem('grimoire:debug:dms', 'true')`
- Levels: dmDebug (verbose), dmInfo (important), dmWarn (warnings)
- **Impact**: Better troubleshooting for NIP-17 issues

### Comprehensive Documentation (docs/gift-wrap-architecture.md - NEW)
- 450+ line architecture document
- Component diagrams, data flow, cache strategy
- Security considerations, performance optimizations
- Debugging guide and testing strategy
- **Impact**: Complete reference for gift wrap implementation

## Testing

-  All tests pass (864 tests)
-  Build succeeds with no errors
-  Lint passes (only pre-existing warnings)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-16 16:44:53 +01:00
Alejandro Gómez
c4bc3ab445 ui: improve relay tooltip, update docs 2025-12-22 19:43:00 +01:00
Claude
bebb4ed834 docs: add comprehensive ReqViewer state machine analysis and improvement plan
Analysis document:
- Identified critical bug in applesauce-relay catchError handling
- Documented 7 edge cases causing "LIVE with 0 relays" issue
- Root cause: relay disconnections treated as EOSE messages
- Detailed Nostr protocol semantics and applesauce behavior

Implementation plan:
- Hybrid approach: RelayStateManager + event metadata tracking
- New state types: ReqRelayState, ReqOverallState
- Enhanced hook: useReqTimelineEnhanced with per-relay tracking
- 3-phase rollout: infrastructure → UI → testing
- Comprehensive state machine with 8 query states, 8 relay states

This provides the foundation for production-quality REQ status tracking
that accurately handles disconnections, timeouts, and partial failures.
2025-12-22 15:59:00 +00:00