Browse Source

fix feeds

imwald
Silberengel 5 months ago
parent
commit
027d8097c1
  1. 5
      src/components/NoteList/index.tsx
  2. 4
      src/components/NoteStats/DiscussionNoteStats.tsx
  3. 4
      src/components/NoteStats/index.tsx
  4. 93
      src/components/ReplyNoteList/index.tsx
  5. 33
      src/components/SimpleNoteFeed/index.tsx

5
src/components/NoteList/index.tsx

@ -215,7 +215,10 @@ const NoteList = forwardRef( @@ -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...')

4
src/components/NoteStats/DiscussionNoteStats.tsx

@ -38,7 +38,6 @@ export default function DiscussionNoteStats({ @@ -38,7 +38,6 @@ export default function DiscussionNoteStats({
loading ? 'animate-pulse' : '',
classNames?.buttonBar
)}
onClick={(e) => e.stopPropagation()}
>
<VoteButtons event={event} />
</div>
@ -51,10 +50,9 @@ export default function DiscussionNoteStats({ @@ -51,10 +50,9 @@ export default function DiscussionNoteStats({
<div className="flex justify-between h-5 [&_svg]:size-4">
<div
className={cn('flex items-center gap-2', loading ? 'animate-pulse' : '')}
onClick={(e) => e.stopPropagation()}
>
</div>
<div className="flex items-center gap-2" onClick={(e) => e.stopPropagation()}>
<div className="flex items-center gap-2">
<VoteButtons event={event} />
</div>
</div>

4
src/components/NoteStats/index.tsx

@ -79,7 +79,6 @@ export default function NoteStats({ @@ -79,7 +79,6 @@ export default function NoteStats({
loading ? 'animate-pulse' : '',
classNames?.buttonBar
)}
onClick={(e) => e.stopPropagation()}
>
<ReplyButton event={event} />
{!isDiscussion && !isReplyToDiscussion && <RepostButton event={event} />}
@ -103,14 +102,13 @@ export default function NoteStats({ @@ -103,14 +102,13 @@ export default function NoteStats({
<div className="flex justify-between h-5 [&_svg]:size-4">
<div
className={cn('flex items-center', loading ? 'animate-pulse' : '')}
onClick={(e) => e.stopPropagation()}
>
<ReplyButton event={event} />
{!isDiscussion && !isReplyToDiscussion && <RepostButton event={event} />}
<LikeButton event={event} />
<ZapButton event={event} />
</div>
<div className="flex items-center" onClick={(e) => e.stopPropagation()}>
<div className="flex items-center">
<BookmarkButton event={event} />
<SeenOnButton event={event} />
</div>

93
src/components/ReplyNoteList/index.tsx

@ -252,26 +252,23 @@ function ReplyNoteList({ index, event, sort = 'oldest' }: { index?: number; even @@ -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<Filter, 'since' | 'until'> & {
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 @@ -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) {

33
src/components/SimpleNoteFeed/index.tsx

@ -1,10 +1,10 @@ @@ -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< @@ -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< @@ -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< @@ -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<string>()
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< @@ -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(() => {

Loading…
Cancel
Save