diff --git a/src/components/NoteList/index.tsx b/src/components/NoteList/index.tsx index ad6b710..141de35 100644 --- a/src/components/NoteList/index.tsx +++ b/src/components/NoteList/index.tsx @@ -215,7 +215,10 @@ const NoteList = forwardRef( refreshCount }) logger.debug('NoteList useEffect:', { subRequests, subRequestsLength: subRequests.length }) - if (!subRequests.length) return + if (!subRequests.length) { + console.log('❌ [NoteList] No subRequests, returning early') + return + } async function init() { console.log('🔄 [NoteList] Initializing feed...') diff --git a/src/components/NoteStats/DiscussionNoteStats.tsx b/src/components/NoteStats/DiscussionNoteStats.tsx index 3caad78..884e45a 100644 --- a/src/components/NoteStats/DiscussionNoteStats.tsx +++ b/src/components/NoteStats/DiscussionNoteStats.tsx @@ -38,7 +38,6 @@ export default function DiscussionNoteStats({ loading ? 'animate-pulse' : '', classNames?.buttonBar )} - onClick={(e) => e.stopPropagation()} > @@ -51,10 +50,9 @@ export default function DiscussionNoteStats({
e.stopPropagation()} >
-
e.stopPropagation()}> +
diff --git a/src/components/NoteStats/index.tsx b/src/components/NoteStats/index.tsx index 51a962d..4f231a5 100644 --- a/src/components/NoteStats/index.tsx +++ b/src/components/NoteStats/index.tsx @@ -79,7 +79,6 @@ export default function NoteStats({ loading ? 'animate-pulse' : '', classNames?.buttonBar )} - onClick={(e) => e.stopPropagation()} > {!isDiscussion && !isReplyToDiscussion && } @@ -103,14 +102,13 @@ export default function NoteStats({
e.stopPropagation()} > {!isDiscussion && !isReplyToDiscussion && }
-
e.stopPropagation()}> +
diff --git a/src/components/ReplyNoteList/index.tsx b/src/components/ReplyNoteList/index.tsx index 8900a4f..e5b31d5 100644 --- a/src/components/ReplyNoteList/index.tsx +++ b/src/components/ReplyNoteList/index.tsx @@ -252,26 +252,23 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even }, [rootInfo, onNewReply]) useEffect(() => { - if (loading || !rootInfo || currentIndex !== index) return - - const init = async () => { - setLoading(true) - - try { - - // Privacy: Only use user's own relays + defaults, never connect to other users' relays - const userReadRelays = userRelayList?.read || [] - const userWriteRelays = userRelayList?.write || [] - const finalRelayUrls = Array.from(new Set([ - ...FAST_READ_RELAY_URLS.map(url => normalizeUrl(url) || url), // Fast, well-connected relays - ...userReadRelays.map(url => normalizeUrl(url) || url), // User's read relays - ...userWriteRelays.map(url => normalizeUrl(url) || url) // User's write relays - ])) - - - const filters: (Omit & { - limit: number - })[] = [] + if (!rootInfo || currentIndex !== index) return + + const init = async () => { + setLoading(true) + logger.debug('[ReplyNoteList] Fetching replies for root:', rootInfo) + + try { + // Privacy: Only use user's own relays + defaults, never connect to other users' relays + const userReadRelays = userRelayList?.read || [] + const userWriteRelays = userRelayList?.write || [] + const finalRelayUrls = Array.from(new Set([ + ...FAST_READ_RELAY_URLS.map(url => normalizeUrl(url) || url), // Fast, well-connected relays + ...userReadRelays.map(url => normalizeUrl(url) || url), // User's read relays + ...userWriteRelays.map(url => normalizeUrl(url) || url) // User's write relays + ])) + + const filters: Filter[] = [] if (rootInfo.type === 'E') { // Fetch all reply types for event-based replies filters.push({ @@ -312,55 +309,27 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even } } + logger.debug('[ReplyNoteList] Using filters:', filters) + logger.debug('[ReplyNoteList] Using relays:', finalRelayUrls.length) + // Use fetchEvents instead of subscribeTimeline for one-time fetching + const allReplies = await client.fetchEvents(finalRelayUrls, filters) - const { closer, timelineKey } = await client.subscribeTimeline( - filters.map((filter) => ({ - urls: finalRelayUrls, // Use all relays, don't slice - filter - })), - { - onEvents: (evts, eosed) => { - if (evts.length > 0) { - const regularReplies = evts.filter((evt) => isReplyNoteEvent(evt)) - addReplies(regularReplies) - } - if (eosed) { - setUntil(evts.length >= LIMIT ? evts[evts.length - 1].created_at - 1 : undefined) - setLoading(false) - } - }, - onNew: (evt) => { - if (isReplyNoteEvent(evt)) { - addReplies([evt]) - } - } - } - ) + logger.debug('[ReplyNoteList] Fetched', allReplies.length, 'replies') - // Add a fallback timeout to prevent infinite loading - const fallbackTimeout = setTimeout(() => { - if (loading) { - setLoading(false) - logger.debug('Reply loading timeout - stopping after 8 seconds') - } - }, 8000) - setTimelineKey(timelineKey) - return () => { - clearTimeout(fallbackTimeout) - closer?.() - } - } catch { + // Filter and add replies + const regularReplies = allReplies.filter((evt) => isReplyNoteEvent(evt)) + addReplies(regularReplies) + + setLoading(false) + } catch (error) { + logger.error('[ReplyNoteList] Error fetching replies:', error) setLoading(false) } - return } - const promise = init() - return () => { - promise.then((closer) => closer?.()) - } - }, [rootInfo, currentIndex, index, onNewReply]) + init() + }, [rootInfo, currentIndex, index]) useEffect(() => { if (replies.length === 0 && !loading && timelineKey) { diff --git a/src/components/SimpleNoteFeed/index.tsx b/src/components/SimpleNoteFeed/index.tsx index 7c73fb9..1f04e1a 100644 --- a/src/components/SimpleNoteFeed/index.tsx +++ b/src/components/SimpleNoteFeed/index.tsx @@ -1,10 +1,10 @@ -import { forwardRef, useEffect, useState, useCallback, useMemo } from 'react' +import { forwardRef, useEffect, useState, useCallback } from 'react' import { useTranslation } from 'react-i18next' import { RefreshCw } from 'lucide-react' import { useNostr } from '@/providers/NostrProvider' import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider' import { normalizeUrl } from '@/lib/url' -import { BIG_RELAY_URLS, FAST_READ_RELAY_URLS, FAST_WRITE_RELAY_URLS } from '@/constants' +import { FAST_READ_RELAY_URLS } from '@/constants' import client from '@/services/client.service' import { Event } from 'nostr-tools' import { kinds } from 'nostr-tools' @@ -44,10 +44,7 @@ const SimpleNoteFeed = forwardRef< const allRelays = [ ...(myRelayList.read || []), // User's inboxes (kind 10002) ...(myRelayList.write || []), // User's outboxes (kind 10002) - ...(favoriteRelays || []), // User's favorite relays (kind 10012) - ...BIG_RELAY_URLS, // Big relays ...FAST_READ_RELAY_URLS, // Fast read relays - ...FAST_WRITE_RELAY_URLS // Fast write relays ] // Normalize and deduplicate relay URLs @@ -61,15 +58,17 @@ const SimpleNoteFeed = forwardRef< // Fetch events using the same pattern as Discussions const fetchEvents = useCallback(async () => { - if (loading && !isRefreshing) return + if (isRefreshing) return setLoading(true) setIsRefreshing(true) try { + console.log('🔄 [SimpleNoteFeed] Starting fetch...', { authors, kinds: requestedKinds, limit }) logger.debug('[SimpleNoteFeed] Fetching events...', { authors, kinds: requestedKinds, limit }) // Get comprehensive relay list const allRelays = await buildComprehensiveRelayList() + console.log('📡 [SimpleNoteFeed] Using relays:', allRelays.length) // Build filter const filter: any = { @@ -81,15 +80,31 @@ const SimpleNoteFeed = forwardRef< filter.authors = authors } + console.log('🔍 [SimpleNoteFeed] Using filter:', filter) logger.debug('[SimpleNoteFeed] Using filter:', filter) // Fetch events + console.log('⏳ [SimpleNoteFeed] Calling client.fetchEvents...') const fetchedEvents = await client.fetchEvents(allRelays, [filter]) + console.log('✅ [SimpleNoteFeed] Fetched', fetchedEvents.length, 'events') logger.debug('[SimpleNoteFeed] Fetched', fetchedEvents.length, 'events') + // Deduplicate events by ID (same event might come from different relays) + const seenIds = new Set() + const uniqueEvents = fetchedEvents.filter(event => { + if (seenIds.has(event.id)) { + return false + } + seenIds.add(event.id) + return true + }) + + console.log('🔗 [SimpleNoteFeed] Deduplicated to', uniqueEvents.length, 'unique events') + logger.debug('[SimpleNoteFeed] Deduplicated to', uniqueEvents.length, 'unique events') + // Filter events (basic filtering) - const filteredEvents = fetchedEvents.filter(event => { + const filteredEvents = uniqueEvents.filter(event => { // Skip deleted events if (event.content === '') return false @@ -101,16 +116,18 @@ const SimpleNoteFeed = forwardRef< return true }) + console.log('🎯 [SimpleNoteFeed] Filtered to', filteredEvents.length, 'events') logger.debug('[SimpleNoteFeed] Filtered to', filteredEvents.length, 'events') setEvents(filteredEvents) } catch (error) { + console.error('❌ [SimpleNoteFeed] Error fetching events:', error) logger.error('[SimpleNoteFeed] Error fetching events:', error) } finally { setLoading(false) setIsRefreshing(false) } - }, [authors, requestedKinds, limit, hideReplies, buildComprehensiveRelayList, loading, isRefreshing]) + }, [authors, requestedKinds, limit, hideReplies, buildComprehensiveRelayList, isRefreshing]) // Initial fetch useEffect(() => {