Browse Source

bug-fixes

imwald
Silberengel 1 month ago
parent
commit
ec17e4d2ad
  1. 5
      src/components/NormalFeed/index.tsx
  2. 98
      src/components/NoteList/index.tsx
  3. 1
      src/components/Relay/index.tsx
  4. 18
      src/components/ReplyNoteList/index.tsx
  5. 2
      src/components/SearchResult/index.tsx
  6. 33
      src/pages/primary/NoteListPage/RelaysFeed.tsx
  7. 11
      src/pages/primary/NoteListPage/index.tsx

5
src/components/NormalFeed/index.tsx

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
import NoteList, { TNoteListRef } from '@/components/NoteList'
import Tabs, { TabDefinition } from '@/components/Tabs'
import logger from '@/lib/logger'
import { useKindFilter } from '@/providers/KindFilterProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import storage from '@/services/local-storage.service'
@ -13,7 +12,6 @@ const NormalFeed = forwardRef<TNoteListRef, { @@ -13,7 +12,6 @@ const NormalFeed = forwardRef<TNoteListRef, {
subRequests: TFeedSubRequest[]
areAlgoRelays?: boolean
isMainFeed?: boolean
showRelayCloseReason?: boolean
/** When set (e.g. on Home), tabs are rendered in layout subHeader instead of in-feed; avoids overlap */
setSubHeader?: (node: React.ReactNode) => void
}>(function NormalFeed(
@ -21,12 +19,10 @@ const NormalFeed = forwardRef<TNoteListRef, { @@ -21,12 +19,10 @@ const NormalFeed = forwardRef<TNoteListRef, {
subRequests,
areAlgoRelays = false,
isMainFeed = false,
showRelayCloseReason = false,
setSubHeader
},
ref
) {
logger.debug('NormalFeed component rendering with:', { subRequests, areAlgoRelays, isMainFeed })
const { hideUntrustedNotes } = useUserTrust()
const { showKinds, showKind1OPs, showKind1Replies, showKind1111 } = useKindFilter()
const [temporaryShowKinds, setTemporaryShowKinds] = useState(showKinds)
@ -112,7 +108,6 @@ const NormalFeed = forwardRef<TNoteListRef, { @@ -112,7 +108,6 @@ const NormalFeed = forwardRef<TNoteListRef, {
hideReplies={listMode === 'posts'}
hideUntrustedNotes={hideUntrustedNotes}
areAlgoRelays={areAlgoRelays}
showRelayCloseReason={showRelayCloseReason}
/>
</div>
</>

98
src/components/NoteList/index.tsx

@ -18,7 +18,6 @@ import { useNostr } from '@/providers/NostrProvider' @@ -18,7 +18,6 @@ import { useNostr } from '@/providers/NostrProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import { useZap } from '@/providers/ZapProvider'
import client from '@/services/client.service'
import logger from '@/lib/logger'
import { TFeedSubRequest } from '@/types'
import dayjs from 'dayjs'
import { Event, kinds } from 'nostr-tools'
@ -34,7 +33,6 @@ import { @@ -34,7 +33,6 @@ import {
} from 'react'
import { useTranslation } from 'react-i18next'
import PullToRefresh from 'react-simple-pull-to-refresh'
import { toast } from 'sonner'
import NoteCard, { NoteCardLoadingSkeleton } from '../NoteCard'
const LIMIT = 500 // Increased from 200 to load more events per request
@ -53,7 +51,6 @@ const NoteList = forwardRef( @@ -53,7 +51,6 @@ const NoteList = forwardRef(
hideReplies = false,
hideUntrustedNotes = false,
areAlgoRelays = false,
showRelayCloseReason = false,
pinnedEventIds = [],
useFilterAsIs = false,
extraShouldHideEvent
@ -67,7 +64,6 @@ const NoteList = forwardRef( @@ -67,7 +64,6 @@ const NoteList = forwardRef(
hideReplies?: boolean
hideUntrustedNotes?: boolean
areAlgoRelays?: boolean
showRelayCloseReason?: boolean
pinnedEventIds?: string[]
/** When true, use filter from subRequests as-is (kinds, limit) instead of showKinds. For spell feeds. */
useFilterAsIs?: boolean
@ -229,16 +225,7 @@ const NoteList = forwardRef( @@ -229,16 +225,7 @@ const NoteList = forwardRef(
useImperativeHandle(ref, () => ({ scrollToTop, refresh }), [])
useEffect(() => {
logger.info('[NoteList] useEffect triggered', {
subRequestsLength: subRequests.length,
subRequests: subRequests.map(({ urls, filter }) => ({
urls: urls.slice(0, 2),
filterKeys: Object.keys(filter)
}))
})
if (!subRequests.length) {
logger.warn('[NoteList] subRequests is empty, not initializing')
setLoading(false)
setEvents([])
// Return a no-op closer function to satisfy the cleanup function
@ -246,13 +233,6 @@ const NoteList = forwardRef( @@ -246,13 +233,6 @@ const NoteList = forwardRef(
}
async function init() {
logger.debug('[NoteList] init called', {
subRequestsCount: subRequests.length,
showKindsLength: showKinds.length,
showKinds,
useFilterAsIs,
areAlgoRelays
})
setLoading(true)
setEvents([])
setNewEvents([])
@ -278,36 +258,15 @@ const NoteList = forwardRef( @@ -278,36 +258,15 @@ const NoteList = forwardRef(
// CRITICAL: Validate filter has kinds before subscribing
if (!finalFilter.kinds || finalFilter.kinds.length === 0) {
logger.error('[NoteList] Filter missing kinds! Using default', {
originalFilter: filter,
showKinds,
useFilterAsIs
})
finalFilter.kinds = [kinds.ShortTextNote]
}
return { urls, filter: finalFilter }
})
logger.debug('[NoteList] Subscribing with filters', {
subRequestCount: mappedSubRequests.length,
filters: mappedSubRequests.map(({ urls, filter }) => ({
urls: urls.slice(0, 2), // Log first 2 URLs
kinds: filter.kinds,
limit: filter.limit,
hasKinds: !!(filter.kinds && filter.kinds.length > 0)
}))
})
// CRITICAL: Validate all filters have kinds before subscribing
const invalidFilters = mappedSubRequests.filter(({ filter }) => !filter.kinds || filter.kinds.length === 0)
if (invalidFilters.length > 0) {
logger.error('[NoteList] CRITICAL: Some filters are missing kinds!', {
invalidCount: invalidFilters.length,
totalCount: mappedSubRequests.length,
showKinds,
useFilterAsIs
})
// Don't subscribe with invalid filters - this would return no events
setLoading(false)
setEvents([])
@ -315,10 +274,6 @@ const NoteList = forwardRef( @@ -315,10 +274,6 @@ const NoteList = forwardRef(
return () => {}
}
logger.info('[NoteList] About to call subscribeTimeline', {
mappedSubRequestsCount: mappedSubRequests.length
})
let closer: (() => void) | undefined
let timelineKey: string | undefined
@ -335,13 +290,6 @@ const NoteList = forwardRef( @@ -335,13 +290,6 @@ const NoteList = forwardRef(
mappedSubRequests,
{
onEvents: (events: Event[], eosed: boolean) => {
logger.debug('[NoteList] onEvents called', {
eventCount: events.length,
eosed,
showKindsLength: showKinds.length,
subRequestsCount: subRequests.length
})
if (events.length > 0) {
setEvents(events)
@ -390,7 +338,6 @@ const NoteList = forwardRef( @@ -390,7 +338,6 @@ const NoteList = forwardRef(
}
} else if (eosed) {
// No events received but EOSE - set empty events array and stop loading
logger.debug('[NoteList] EOSE with no events, stopping loading')
setEvents([])
setLoading(false)
}
@ -435,37 +382,6 @@ const NoteList = forwardRef( @@ -435,37 +382,6 @@ const NoteList = forwardRef(
)
}
},
onClose: (url: string, reason: string) => {
if (!showRelayCloseReason) return
// ignore reasons from nostr-tools
if (
[
'closed by caller',
'relay connection errored',
'relay connection closed',
'pingpong timed out',
'relay connection closed by us'
].includes(reason)
) {
return
}
// don't toast for routine connection failures (noisy and expected when relays are down/slow)
const r = reason.toLowerCase()
if (
r.includes('connection failed') ||
r.includes('econnrefused') ||
r.includes('econnreset') ||
r.includes('etimedout') ||
r.includes('timeout') ||
r.includes('network') ||
r.includes('enotfound') ||
r.includes('connection refused')
) {
return
}
toast.error(`${url}: ${reason}`)
}
},
{
startLogin,
@ -477,20 +393,11 @@ const NoteList = forwardRef( @@ -477,20 +393,11 @@ const NoteList = forwardRef(
])
closer = result.closer
timelineKey = result.timelineKey
logger.info('[NoteList] subscribeTimeline completed', {
hasTimelineKey: !!timelineKey,
hasCloser: !!closer
})
setTimelineKey(timelineKey)
return closer
} catch (error) {
logger.error('[NoteList] Error in subscribeTimeline', {
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined
})
} catch (_error) {
setLoading(false)
// Return a no-op closer function instead of throwing - allows cleanup to work
// The error is already logged, no need to crash the component
return () => {}
}
}
@ -708,9 +615,8 @@ const NoteList = forwardRef( @@ -708,9 +615,8 @@ const NoteList = forwardRef(
}
})
}
} catch (error) {
} catch (_error) {
// On error, don't set hasMore to false - might be temporary network issue
logger.error('[NoteList] Error loading more events', { error })
consecutiveEmptyRef.current += 1
// Only stop after MANY consecutive errors - be very patient with network issues
// This prevents stopping when relays are temporarily down or slow

1
src/components/Relay/index.tsx

@ -77,7 +77,6 @@ export default function Relay({ url, className }: { url?: string; className?: st @@ -77,7 +77,6 @@ export default function Relay({ url, className }: { url?: string; className?: st
subRequests={[
{ urls: [normalizedUrl], filter: debouncedInput ? { search: debouncedInput } : {} }
]}
showRelayCloseReason
/>
</div>
)

18
src/components/ReplyNoteList/index.tsx

@ -297,13 +297,11 @@ function ReplyNoteList({ @@ -297,13 +297,11 @@ function ReplyNoteList({
const hasCache = cachedData !== null
if (hasCache) {
logger.debug('[ReplyNoteList] Found cached replies:', cachedData.length, 'replies', hasFreshCache ? '(fresh)' : '(stale)')
// Display cached data immediately (even if stale) for instant switching
addReplies(cachedData)
setLoading(false)
} else {
// No cache at all, show loading while fetching
logger.debug('[ReplyNoteList] No cache found, fetching from relays')
setLoading(true)
}
@ -373,14 +371,9 @@ function ReplyNoteList({ @@ -373,14 +371,9 @@ function ReplyNoteList({
}
}
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 queryService.fetchEvents(finalRelayUrls, filters)
logger.debug('[ReplyNoteList] Fetched', allReplies.length, 'replies')
// Filter and add replies
const regularReplies = allReplies.filter((evt) => isReplyNoteEvent(evt))
@ -395,7 +388,6 @@ function ReplyNoteList({ @@ -395,7 +388,6 @@ function ReplyNoteList({
// This ensures we keep all previously seen replies and add any new ones
// addReplies will deduplicate, so it's safe to call even if some replies are already displayed
if (mergedCachedReplies) {
logger.debug('[ReplyNoteList] Adding merged cached replies to UI:', mergedCachedReplies.length, 'total replies')
addReplies(mergedCachedReplies)
} else {
// Fallback: if cache somehow failed, at least add the fetched replies
@ -406,16 +398,6 @@ function ReplyNoteList({ @@ -406,16 +398,6 @@ function ReplyNoteList({
if (!hasCache) {
// No cache: stop loading after adding replies
setLoading(false)
} else {
// Background refresh: check if we got new replies
const cachedReplyIds = new Set(cachedData!.map(r => r.id))
const hasNewReplies = regularReplies.some(r => !cachedReplyIds.has(r.id))
if (hasNewReplies) {
logger.debug('[ReplyNoteList] Background refresh found new replies, UI updated')
} else {
logger.debug('[ReplyNoteList] Background refresh: no new replies, existing replies preserved')
}
}
} catch (error) {
logger.error('[ReplyNoteList] Error fetching replies:', error)

2
src/components/SearchResult/index.tsx

@ -53,7 +53,6 @@ export default function SearchResult({ searchParams }: { searchParams: TSearchPa @@ -53,7 +53,6 @@ export default function SearchResult({ searchParams }: { searchParams: TSearchPa
return (
<NormalFeed
subRequests={[{ urls: searchRelays, filter: { search: searchParams.search } }]}
showRelayCloseReason
/>
)
}
@ -61,7 +60,6 @@ export default function SearchResult({ searchParams }: { searchParams: TSearchPa @@ -61,7 +60,6 @@ export default function SearchResult({ searchParams }: { searchParams: TSearchPa
return (
<NormalFeed
subRequests={[{ urls: searchRelays, filter: { '#t': [searchParams.search] } }]}
showRelayCloseReason
/>
)
}

33
src/pages/primary/NoteListPage/RelaysFeed.tsx

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
import NormalFeed from '@/components/NormalFeed'
import { checkAlgoRelay } from '@/lib/relay'
import logger from '@/lib/logger'
import { useFeed } from '@/providers/FeedProvider'
import { useKindFilter } from '@/providers/KindFilterProvider'
import relayInfoService from '@/services/relay-info.service'
@ -15,19 +14,11 @@ export default function RelaysFeed({ @@ -15,19 +14,11 @@ export default function RelaysFeed({
/** When set, subscription kinds (fixed list); otherwise uses KindFilterProvider. */
kindsOverride?: number[]
}) {
logger.debug('RelaysFeed component rendering')
const { feedInfo, relayUrls } = useFeed()
const { showKinds } = useKindFilter()
const [areAlgoRelays, setAreAlgoRelays] = useState(false)
const relayInfoFetchedRef = useRef(false)
// Debug logging
logger.debug('RelaysFeed debug:', {
feedInfo,
relayUrls: relayUrls.length,
showKinds: showKinds.length
})
// Fetch relay info in background (non-blocking) - don't wait for it to render
useEffect(() => {
// Only fetch once per relayUrls change
@ -52,23 +43,14 @@ export default function RelaysFeed({ @@ -52,23 +43,14 @@ export default function RelaysFeed({
])
const areAlgo = relayInfos.every((relayInfo) => checkAlgoRelay(relayInfo))
setAreAlgoRelays(areAlgo)
logger.debug('RelaysFeed: Relay info fetched successfully', {
relayCount: relayUrls.length,
areAlgoRelays: areAlgo
})
} catch (error) {
logger.debug('RelaysFeed: Failed to get relay infos (non-blocking)', {
error: error instanceof Error ? error.message : String(error),
relayUrls: relayUrls.length
})
} catch (_error) {
// Default to false - feed will work without this info
setAreAlgoRelays(false)
}
}
// Don't await - let it run in background
init().catch((err) => {
logger.debug('RelaysFeed: Unhandled error in init', { error: err })
init().catch(() => {
setAreAlgoRelays(false)
})
}, [relayUrls])
@ -105,25 +87,14 @@ export default function RelaysFeed({ @@ -105,25 +87,14 @@ export default function RelaysFeed({
}, [canRenderFeed, relayUrls, defaultKinds, kindsOverride])
if (!canRenderFeed) {
if (relayUrls.length === 0) {
logger.debug('RelaysFeed: relayUrls is empty, not rendering feed')
}
return null
}
logger.component('RelaysFeed', 'Rendering NormalFeed', {
subRequests: subRequests.length,
relayUrls: relayUrls.length,
areAlgoRelays,
filterKinds: subRequests[0]?.filter?.kinds?.length || 0
})
return (
<NormalFeed
subRequests={subRequests}
areAlgoRelays={areAlgoRelays}
isMainFeed
showRelayCloseReason
setSubHeader={setSubHeader}
/>
)

11
src/pages/primary/NoteListPage/index.tsx

@ -24,11 +24,9 @@ import { KeyboardShortcutsHelpButton } from '@/components/KeyboardShortcutsHelp' @@ -24,11 +24,9 @@ import { KeyboardShortcutsHelpButton } from '@/components/KeyboardShortcutsHelp'
import AccountButton from '@/components/Titlebar/AccountButton'
import FollowingFeed from './FollowingFeed'
import RelaysFeed from './RelaysFeed'
import logger from '@/lib/logger'
import { usePrimaryNoteView } from '@/PageManager'
const NoteListPage = forwardRef((_, ref) => {
logger.debug('NoteListPage component rendering')
const { t } = useTranslation()
const { addRelayUrls, removeRelayUrls } = useCurrentRelays()
const layoutRef = useRef<TPageRef>(null)
@ -64,14 +62,6 @@ const NoteListPage = forwardRef((_, ref) => { @@ -64,14 +62,6 @@ const NoteListPage = forwardRef((_, ref) => {
}
}, [relayUrls])
// Debug logging
logger.debug('NoteListPage debug:', {
isReady,
feedInfo,
relayUrls,
pubkey: !!pubkey
})
let content: React.ReactNode = null
if (!isReady) {
content = <div className="text-center text-sm text-muted-foreground">{t('loading...')}</div>
@ -158,7 +148,6 @@ function NoteListPageTitlebar({ @@ -158,7 +148,6 @@ function NoteListPageTitlebar({
onClick={(e) => {
e.preventDefault()
e.stopPropagation()
logger.debug('Im Wald button clicked, clearing overlay')
setPrimaryNoteView(null)
}}
>

Loading…
Cancel
Save