mirror of
https://github.com/dergigi/boris.git
synced 2025-12-17 06:34:24 +01:00
debug: add comprehensive logging to article loader
Add detailed debug logs prefixed with [article-loader] and [article-cache] to track: - Cache checks (hit/miss/expired) - EventStore checks - Relay queries and event streaming - UI state updates - Request lifecycle and abort conditions This will help debug why articles are still loading from relays on refresh.
This commit is contained in:
@@ -72,15 +72,26 @@ export function useArticleLoader({
|
||||
useEffect(() => {
|
||||
mountedRef.current = true
|
||||
|
||||
if (!relayPool || !naddr) return
|
||||
if (!relayPool || !naddr) {
|
||||
console.log('[article-loader] Skipping load - missing relayPool or naddr', { hasRelayPool: !!relayPool, hasNaddr: !!naddr })
|
||||
return
|
||||
}
|
||||
|
||||
console.log('[article-loader] Starting load for naddr:', naddr)
|
||||
|
||||
// Synchronously check cache sources BEFORE starting async loading
|
||||
// This prevents showing loading skeletons when content is immediately available
|
||||
// Do this outside the async function for immediate execution
|
||||
try {
|
||||
console.log('[article-loader] Checking localStorage cache...')
|
||||
// Check localStorage cache first (synchronous)
|
||||
const cachedArticle = getFromCache(naddr)
|
||||
if (cachedArticle) {
|
||||
console.log('[article-loader] ✅ Cache HIT - loading from localStorage', {
|
||||
title: cachedArticle.title,
|
||||
hasMarkdown: !!cachedArticle.markdown,
|
||||
markdownLength: cachedArticle.markdown?.length
|
||||
})
|
||||
const title = cachedArticle.title || 'Untitled Article'
|
||||
setCurrentTitle(title)
|
||||
setReaderContent({
|
||||
@@ -146,16 +157,24 @@ export function useArticleLoader({
|
||||
}
|
||||
|
||||
// Return early - we have cached content, no need to query relays
|
||||
console.log('[article-loader] Returning early with cached content')
|
||||
return
|
||||
} else {
|
||||
console.log('[article-loader] ❌ Cache MISS - not found in localStorage')
|
||||
}
|
||||
} catch (err) {
|
||||
// If cache check fails, fall through to async loading
|
||||
console.warn('Cache check failed:', err)
|
||||
console.warn('[article-loader] Cache check failed:', err)
|
||||
}
|
||||
|
||||
const loadArticle = async () => {
|
||||
const requestId = ++currentRequestIdRef.current
|
||||
if (!mountedRef.current) return
|
||||
console.log('[article-loader] Starting async loadArticle function', { requestId })
|
||||
|
||||
if (!mountedRef.current) {
|
||||
console.log('[article-loader] Component unmounted, aborting')
|
||||
return
|
||||
}
|
||||
|
||||
setSelectedUrl(`nostr:${naddr}`)
|
||||
setIsCollapsed(true)
|
||||
@@ -167,14 +186,22 @@ export function useArticleLoader({
|
||||
// Check eventStore for instant load (from bookmark cards, explore, etc.)
|
||||
// Cache was already checked synchronously above, so this only handles EventStore
|
||||
if (eventStore) {
|
||||
console.log('[article-loader] Checking EventStore...')
|
||||
try {
|
||||
// Decode naddr to get the coordinate
|
||||
const decoded = nip19.decode(naddr)
|
||||
if (decoded.type === 'naddr') {
|
||||
const pointer = decoded.data as AddressPointer
|
||||
const coordinate = `${pointer.kind}:${pointer.pubkey}:${pointer.identifier}`
|
||||
console.log('[article-loader] Looking for event with coordinate:', coordinate)
|
||||
const storedEvent = eventStore.getEvent?.(coordinate)
|
||||
if (storedEvent) {
|
||||
console.log('[article-loader] ✅ EventStore HIT - found event', {
|
||||
id: storedEvent.id,
|
||||
kind: storedEvent.kind,
|
||||
hasContent: !!storedEvent.content,
|
||||
contentLength: storedEvent.content?.length
|
||||
})
|
||||
const title = Helpers.getArticleTitle(storedEvent) || 'Untitled Article'
|
||||
setCurrentTitle(title)
|
||||
const image = Helpers.getArticleImage(storedEvent)
|
||||
@@ -197,17 +224,24 @@ export function useArticleLoader({
|
||||
|
||||
// If we found the content in EventStore, we can return early
|
||||
// This prevents unnecessary relay queries when offline
|
||||
console.log('[article-loader] Returning early with EventStore content')
|
||||
return
|
||||
} else {
|
||||
console.log('[article-loader] ❌ EventStore MISS - no event found for coordinate:', coordinate)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// Ignore store errors, fall through to relay query
|
||||
console.warn('[article-loader] EventStore check failed:', err)
|
||||
}
|
||||
} else {
|
||||
console.log('[article-loader] No EventStore available, skipping check')
|
||||
}
|
||||
|
||||
// At this point, we've checked EventStore and cache - neither had content
|
||||
// Only show loading skeleton if we also don't have preview data
|
||||
if (previewData) {
|
||||
console.log('[article-loader] Using preview data (no skeleton)', { title: previewData.title })
|
||||
// If we have preview data from navigation, show it immediately (no skeleton!)
|
||||
setCurrentTitle(previewData.title)
|
||||
setReaderContent({
|
||||
@@ -221,11 +255,13 @@ export function useArticleLoader({
|
||||
setReaderLoading(false) // Turn off loading immediately - we have the preview!
|
||||
} else {
|
||||
// No cache, no EventStore, no preview data - need to load from relays
|
||||
console.log('[article-loader] ⚠️ No cache, EventStore, or preview - showing loading skeleton and querying relays')
|
||||
setReaderLoading(true)
|
||||
setReaderContent(undefined)
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('[article-loader] Querying relays for article...')
|
||||
// Decode naddr to filter
|
||||
const decoded = nip19.decode(naddr)
|
||||
if (decoded.type !== 'naddr') {
|
||||
@@ -237,15 +273,34 @@ export function useArticleLoader({
|
||||
authors: [pointer.pubkey],
|
||||
'#d': [pointer.identifier]
|
||||
}
|
||||
console.log('[article-loader] Relay query filter:', filter)
|
||||
|
||||
let firstEmitted = false
|
||||
let latestEvent: NostrEvent | null = null
|
||||
|
||||
// Stream local-first via queryEvents; rely on EOSE (no timeouts)
|
||||
console.log('[article-loader] Starting queryEvents...')
|
||||
const events = await queryEvents(relayPool, filter, {
|
||||
onEvent: (evt) => {
|
||||
if (!mountedRef.current) return
|
||||
if (currentRequestIdRef.current !== requestId) return
|
||||
if (!mountedRef.current) {
|
||||
console.log('[article-loader] Component unmounted during event stream, ignoring')
|
||||
return
|
||||
}
|
||||
if (currentRequestIdRef.current !== requestId) {
|
||||
console.log('[article-loader] Request ID mismatch, ignoring event', {
|
||||
currentRequestId: currentRequestIdRef.current,
|
||||
eventRequestId: requestId
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
console.log('[article-loader] 📨 Received event from relay', {
|
||||
id: evt.id,
|
||||
kind: evt.kind,
|
||||
created_at: evt.created_at,
|
||||
contentLength: evt.content?.length,
|
||||
isFirst: !firstEmitted
|
||||
})
|
||||
|
||||
// Store in event store for future local reads
|
||||
try {
|
||||
@@ -262,6 +317,7 @@ export function useArticleLoader({
|
||||
|
||||
// Emit immediately on first event
|
||||
if (!firstEmitted) {
|
||||
console.log('[article-loader] ✅ First event received - updating UI immediately')
|
||||
firstEmitted = true
|
||||
const title = Helpers.getArticleTitle(evt) || 'Untitled Article'
|
||||
setCurrentTitle(title)
|
||||
@@ -282,15 +338,31 @@ export function useArticleLoader({
|
||||
setCurrentArticleEventId(evt.id)
|
||||
setCurrentArticle?.(evt)
|
||||
setReaderLoading(false)
|
||||
console.log('[article-loader] UI updated with first event')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (!mountedRef.current || currentRequestIdRef.current !== requestId) return
|
||||
console.log('[article-loader] QueryEvents completed', {
|
||||
eventCount: events.length,
|
||||
hasLatestEvent: !!latestEvent,
|
||||
mounted: mountedRef.current,
|
||||
requestIdMatch: currentRequestIdRef.current === requestId
|
||||
})
|
||||
|
||||
if (!mountedRef.current || currentRequestIdRef.current !== requestId) {
|
||||
console.log('[article-loader] Component unmounted or request ID changed, aborting')
|
||||
return
|
||||
}
|
||||
|
||||
// Finalize with newest version if it's newer than what we first rendered
|
||||
const finalEvent = (events.sort((a, b) => b.created_at - a.created_at)[0]) || latestEvent
|
||||
if (finalEvent) {
|
||||
console.log('[article-loader] ✅ Finalizing with event', {
|
||||
id: finalEvent.id,
|
||||
created_at: finalEvent.created_at,
|
||||
wasFirstEmitted: firstEmitted
|
||||
})
|
||||
const title = Helpers.getArticleTitle(finalEvent) || 'Untitled Article'
|
||||
setCurrentTitle(title)
|
||||
const image = Helpers.getArticleImage(finalEvent)
|
||||
@@ -310,9 +382,16 @@ export function useArticleLoader({
|
||||
setCurrentArticleCoordinate(articleCoordinate)
|
||||
setCurrentArticleEventId(finalEvent.id)
|
||||
setCurrentArticle?.(finalEvent)
|
||||
console.log('[article-loader] ✅ Finalized with event from relays')
|
||||
} else {
|
||||
// As a last resort, fall back to the legacy helper (which includes cache)
|
||||
console.log('[article-loader] ⚠️ No events from relays, falling back to fetchArticleByNaddr')
|
||||
const article = await fetchArticleByNaddr(relayPool, naddr, false, settingsRef.current)
|
||||
console.log('[article-loader] fetchArticleByNaddr result:', {
|
||||
hasArticle: !!article,
|
||||
title: article?.title,
|
||||
hasMarkdown: !!article?.markdown
|
||||
})
|
||||
if (!mountedRef.current || currentRequestIdRef.current !== requestId) return
|
||||
setCurrentTitle(article.title)
|
||||
setReaderContent({
|
||||
|
||||
Reference in New Issue
Block a user