fix: bookmark loading completing properly now

Fixed critical issue where async operations in onEvent callback
were blocking the queryEvents observable from completing:

Changes:
1. Removed async/await from onEvent callback
   - Now just collects events synchronously
   - No blocking operations in the stream

2. Moved auto-decryption to after query completes
   - Batch process encrypted events after EOSE
   - Sequential decryption (cleaner, more predictable)

3. Simplified useEffect triggers in App.tsx
   - Removed duplicate mount + account change effects
   - Single effect handles both cases

Result: Query now completes properly, bookmarks load and display.
This commit is contained in:
Gigi
2025-10-17 22:13:58 +02:00
parent 5bd57573be
commit e5a7a07deb
2 changed files with 20 additions and 27 deletions

View File

@@ -68,19 +68,10 @@ function AppRoutes({
await loadBookmarks()
}, [loadBookmarks])
// Load bookmarks on mount if account exists (app reopen)
// Load bookmarks when account changes (includes initial mount)
useEffect(() => {
if (activeAccount && relayPool) {
console.log('[app] 📱 App mounted with active account, loading bookmarks')
loadBookmarks()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []) // Empty deps - only on mount, loadBookmarks is stable
// Load bookmarks when account changes (login)
useEffect(() => {
if (activeAccount && relayPool) {
console.log('[app] 👤 Active account changed, loading bookmarks')
console.log('[app] 👤 Loading bookmarks (account + relayPool ready)')
loadBookmarks()
}
}, [activeAccount, relayPool, loadBookmarks])

View File

@@ -186,12 +186,12 @@ export const fetchBookmarks = async (
setBookmarks([bookmark])
}
// Stream events with auto-decryption
// Stream events (just collect, decrypt after)
const rawEvents = await queryEvents(
relayPool,
{ kinds: [KINDS.ListSimple, KINDS.ListReplaceable, KINDS.List, KINDS.WebBookmark], authors: [activeAccount.pubkey] },
{
onEvent: async (evt) => {
onEvent: (evt) => {
// Deduplicate by key
const key = getEventKey(evt)
const existing = eventMap.get(key)
@@ -205,19 +205,6 @@ export const fetchBookmarks = async (
processedCount++
console.log(`[app] 📨 Event ${processedCount}: kind=${evt.kind}, id=${evt.id.slice(0, 8)}, hasEncrypted=${hasEncryptedContent(evt)}`)
// Auto-decrypt if has encrypted content
if (hasEncryptedContent(evt)) {
console.log('[app] 🔓 Auto-decrypting bookmark event', evt.id.slice(0, 8))
try {
// Trigger decryption by collecting from this single event
// This will unlock the content for the main collection pass
await collectBookmarksFromEvents([evt], activeAccount, signerCandidate)
console.log('[app] ✅ Auto-decrypted:', evt.id.slice(0, 8))
} catch (error) {
console.error('[app] ❌ Auto-decrypt failed:', evt.id.slice(0, 8), error)
}
}
}
}
)
@@ -236,7 +223,22 @@ export const fetchBookmarks = async (
return
}
// Final update with all events
// Auto-decrypt events with encrypted content (batch processing)
const encryptedEvents = dedupedEvents.filter(evt => hasEncryptedContent(evt))
if (encryptedEvents.length > 0) {
console.log('[app] 🔓 Auto-decrypting', encryptedEvents.length, 'encrypted events')
for (const evt of encryptedEvents) {
try {
// Trigger decryption - this unlocks the content for the main collection pass
await collectBookmarksFromEvents([evt], activeAccount, signerCandidate)
console.log('[app] ✅ Auto-decrypted:', evt.id.slice(0, 8))
} catch (error) {
console.error('[app] ❌ Auto-decrypt failed:', evt.id.slice(0, 8), error)
}
}
}
// Final update with all events (now with decrypted content)
console.log('[app] 🔄 Final bookmark processing with', dedupedEvents.length, 'events')
await updateBookmarks(dedupedEvents)
console.log('[app] ✅ Bookmarks processing complete')