Removed all withTimeout wrappers - now matches debug page behavior:
- Direct decrypt calls with no artificial timeouts
- Let operations fail naturally and quickly
- Bunker responds instantly (success or rejection)
No timeouts needed because:
1. Account queue is disabled (requests sent immediately)
2. Only decrypting truly encrypted content (no wasted attempts)
3. Bunker either succeeds quickly or fails quickly
This makes bookmark decryption instant, just like the debug page
encryption/decryption tests.
Use applesauce Helpers.hasHiddenContent() instead of checking for
any content. This properly detects encrypted content and avoids
sending unnecessary decrypt requests to Amber for events that just
have plain text content.
Before: (evt.content && evt.content.length > 0)
After: Helpers.hasHiddenContent(evt)
Result:
- Only events with encrypted content sent to Amber
- Reduces unnecessary decrypt requests
- Faster bookmark loading
The applesauce BaseAccount queues requests by default, waiting for
each to complete before sending the next. This caused decrypt requests
to timeout before ever reaching Amber/bunker.
Solution:
- Set disableQueue=true before batch operations
- All decrypt requests sent immediately
- Restore original queue state after completion
This should fix the hanging/timeout issue where Amber never saw
the decrypt requests because they were stuck in the account's queue.
Ref: https://hzrd149.github.io/applesauce/typedoc/classes/applesauce-accounts.BaseAccount.html#disablequeue
Removed mapWithConcurrency hack:
- Simpler code with plain for loop
- More predictable behavior
- Better for bunker signers (network round-trips)
- Each decrypt happens in order, no race conditions
Sequential processing is cleaner and works better with remote signers.
Changes:
- Use 5-second timeout instead of 30 seconds
- Detect encryption method from content format
- NIP-04 has '?iv=' in content, NIP-44 doesn't
- Try the likely method first to avoid unnecessary timeouts
- Falls back to other method if first fails
This should:
- Prevent hanging forever (5s timeout)
- Be much faster than 30s when wrong method is tried
- Usually decrypt instantly when right method is used first
The withTimeout wrapper was causing decrypt operations to wait
30 seconds before failing, even when bunker rejection was instant.
Now uses the same direct approach as the debug page encryption tests:
- No artificial timeouts
- Fast natural failures
- Should reduce decrypt time from 30s+ to near-instant
Fixes slow bookmark loading when bunker doesn't support nip44.
- Add withTimeout and mapWithConcurrency helpers in utils/async.ts
- Refactor collectBookmarksFromEvents to decrypt with 6-way concurrency
- Public bookmarks collected immediately, private decrypted in parallel
- Each decrypt wrapped with 30s timeout safety net
- Document non-blocking publish and concurrent decrypt in Amber.md
- Bunker (NIP-46) signers don't reliably support async decrypt operations
- Skip attempting to decrypt private bookmarks when using bunker
- Users can still see all public bookmarks
- Use extension signer for access to encrypted private bookmarks
- Prevents 15+ second hangs waiting for decrypt responses that won't come
- Give bunker operations more time to respond
- Will help determine if this is a timing issue or a fundamental limitation
- Still logging timeout errors for visibility
- Log nip04/nip44 decrypt errors instead of silently ignoring
- Will help identify why bookmark decryption is timing out with bunker
- Timeout errors will now be visible in console
- Wrap nip04/nip44 decrypt calls with 5 second timeout
- Prevents UI from hanging if decrypt request doesn't receive response
- Allows graceful degradation instead of infinite wait
- With bunker, decrypt responses may not arrive if perms/relay issues
- EventFactory expects an EventSigner interface with signEvent method
- account.signer is the actual NostrConnectSigner instance
- Add debug logging to trace signer type
- This should fix signing hanging when using bunker
- Remove reconnectBunkerSigner function, inline logic into App.tsx for better control
- Clean up try-catch wrapper in highlightCreationService, signing now works reliably
- Remove extra logging from signing process (already has [bunker] prefix logs)
- Simplify nostrConnect.ts to just export permissions helper
- Update api/article-og.ts to use local relay config instead of import
- All bunker signing tests now passing ✅
- Without this, requireConnection() tries to connect() again
- That breaks the entire signing flow
- Mark signer as connected after opening subscription
- The global decrypt queue in bookmarkProcessing was getting stuck
- Caused all NIP-46 operations to hang indefinitely
- Decrypt already has per-call timeouts; queue was unnecessary
- Highlights should now sign immediately without waiting for bookmarks
- Remove connect(undefined, permissions) on restore
- Let requireConnection() trigger connect per op
- Keeps highlights signing working as before while we debug decrypt
- Call signer.connect() instead of forcing isConnected
- Add [bunker] logs for connect lifecycle
- Should unblock nip44/nip04 decrypt calls that were timing out
- Wrap nip44/nip04 decrypt and unlockHiddenTags in timeouts
- Fallback nip44->nip04 if nip44 hangs/fails
- Add detailed [bunker] logs for each stage
- Keeps UI responsive while debugging bunker responses
- Remove bunkerFixVersion migration logic
- Simplify account loading to match applesauce examples
- Simplify reconnectBunkerSigner (no waiting, no complex logging)
- Direct nip04/nip44 exposure from signer (like ExtensionAccount)
- Clean up bookmark service account checking
- Keep debug logs for now until verified working
- Getters were returning new objects each time
- Code was getting reference then calling decrypt on it
- Now assign wrapped objects directly as properties
- This ensures our logging wrappers are actually used
- Log when decrypt/encrypt methods are called
- Log when they complete or fail
- Show pubkey and ciphertext/plaintext lengths
- This will tell us if decrypt is hanging in the signer or never returning
- Add detailed logging for signer subscription opening
- Enable debug logs for NostrConnectSigner via localStorage
- This will show if requests are being sent and responses received
- Helps diagnose why decrypt requests hang indefinitely
- Decryption was hanging because relay connections weren't established
- NostrConnectSigner sends requests via relays but pool wasn't connected
- Now wait for at least one bunker relay to be connected (5s timeout)
- Prevents decrypt/sign requests from being sent to unconnected relays
- Adds detailed logging for connection status
- NostrConnectSigner has nip04/nip44 but not exposed at account level
- ExtensionAccount exposes these via getters, NostrConnectAccount didn't
- Add properties dynamically during reconnection for compatibility
- Enables private bookmark decryption with bunker accounts
- Add detailed logs for active account changes and bunker detection
- Log signer status (listening, isConnected, hasRemote)
- Log each step of reconnection process
- Add signing attempt logs in highlightCreationService
- This will help diagnose where the signing process hangs
- Create centralized getDefaultBunkerPermissions() in nostrConnect service
- Update LoginOptions to use centralized permissions
- Add bunker reconnection logic in App.tsx on active account change
- Reconnect bunker signer with open() and connect() when restored from localStorage
- Surface permission errors to users via toast in useHighlightCreation
- Ensures highlights, reactions, settings, and bookmarks work after page reload with bunker
- Add explicit signing permissions for event kinds: 5, 7, 17, 9802, 30078, 39701, 0
- Add encryption/decryption permissions: nip04_encrypt/decrypt, nip44_encrypt/decrypt
- Improve error messages when bunker permissions are missing or denied
- Add debug logging hint for bunker permission issues in write service
- This ensures highlights, reactions, settings, reading positions, and web bookmarks all work with bunker
- Remove unused readingPositions and markedAsReadIds from useBookmarksData
- Remove eventStore parameter from useBookmarksData call
- Add reads and links fields to MeCache interface
Resolved conflicts by keeping feature branch changes:
- Kept /me/reads and /me/links routes (not /me/archive)
- Kept ReadingProgressFilters component and readingProgressUtils
- Kept readsService, linksService, and readingDataProcessor
- Restored files that were renamed/deleted in master
- Remove unused state variables (readsMap, linksMap) by using only setters
- Move VALID_FILTERS constant outside component to fix exhaustive-deps warning
- Remove unused isReading variable in ReadingProgressIndicator
- Remove unused extractUrlFromBookmark function and IndividualBookmark import
- Fix type errors in linksFromBookmarks by extracting metadata from tags instead of non-existent properties
- Create src/config/kinds.ts with named Nostr kind constants
- Add streaming support to fetchAllReads and fetchLinks with onItem callbacks
- Update all services to use KINDS constants instead of magic numbers
- Add mergeReadItem utility for DRY state management
- Add fallbackTitleFromUrl for external links without titles
- Relax validation to allow external items without titles
- Update Me.tsx to use streaming with Map-based state for reads/links
- Fix refresh to merge new data instead of clearing state
- Fix empty states for Reads and Links tabs (no more infinite skeletons)
- Services updated: readsService, linksService, libraryService, bookmarkService, exploreService, highlights/fetchByAuthor
- Create readingProgressUtils.ts with filterByReadingProgress function
- Create readingDataProcessor.ts with shared processing functions:
- processReadingPositions
- processMarkedAsRead
- filterValidItems
- sortByReadingActivity
- Refactor readsService.ts to use shared utilities
- Refactor linksService.ts to use shared utilities
- Eliminate 100+ lines of duplicated code
- Simplify Me.tsx filter logic to 2 lines
Benefits:
- Single source of truth for reading progress filtering
- Easier to maintain and modify
- Less code duplication across services
- More testable with isolated utility functions
- Reads: Only Nostr-native articles (kind:30023)
- Links: Only external URLs with reading progress
- Create linksService.ts for fetching external URL links
- Update readsService to filter only Nostr articles
- Add Links tab between Reads and Writings with same filtering
- Add /me/links route
- Update meCache to include links field
- Both tabs support reading progress filters
- Lazy loading for both tabs
This provides clear separation between native Nostr content and external web links.