diff --git a/src/components/NoteList/index.tsx b/src/components/NoteList/index.tsx index 13092cdd..0affb438 100644 --- a/src/components/NoteList/index.tsx +++ b/src/components/NoteList/index.tsx @@ -41,6 +41,7 @@ import PullToRefresh from 'react-simple-pull-to-refresh' import { formatPubkey, pubkeyToNpub } from '@/lib/pubkey' import { NoteFeedProfileContext, type NoteFeedProfileContextValue } from '@/providers/NoteFeedProfileContext' import type { TProfile } from '@/types' +import { Loader2 } from 'lucide-react' import NoteCard, { NoteCardLoadingSkeleton } from '../NoteCard' const LIMIT = 100 // Increased from 200 to load more events per request @@ -87,7 +88,8 @@ const NoteList = forwardRef( */ preserveTimelineOnSubRequestsChange = false, /** - * Spells page: after this many ms, clear the loading skeleton so the list area renders; subscription keeps running. + * Spells / one-shot feeds: when the initial fetch finishes with zero rows, show explicit empty copy + * (see list footer). Does not end loading early — loading stays until EOSE, first events, or safety timeouts. */ spellFetchTimeoutMs, /** Spells page: bumps when user picks a feed; used with {@link onSpellFeedFirstPaint}. */ @@ -117,7 +119,7 @@ const NoteList = forwardRef( extraShouldHideEvent?: (evt: Event) => boolean feedSubscriptionKey?: string preserveTimelineOnSubRequestsChange?: boolean - /** When set (spells), max time to show the initial loading skeleton (ms). */ + /** When set (e.g. spells), use explicit empty-feed copy after load completes with no rows. */ spellFetchTimeoutMs?: number spellFeedInstrumentToken?: number onSpellFeedFirstPaint?: (detail: { eventCount: number; firstEventId: string }) => void @@ -732,7 +734,6 @@ const NoteList = forwardRef( showKind1111, useFilterAsIs, areAlgoRelays, - spellFetchTimeoutMs, oneShotFetch ]) @@ -758,21 +759,6 @@ const NoteList = forwardRef( } }, [timelineSubscriptionKey, refreshCount]) - /** Spells: drop loading skeleton quickly so rows (or empty + reload) appear while REQ continues. */ - useEffect(() => { - if (spellFetchTimeoutMs == null || spellFetchTimeoutMs <= 0) return - if (!subRequestsRef.current.length) return - let cancelled = false - const id = window.setTimeout(() => { - if (cancelled) return - setLoading(false) - }, spellFetchTimeoutMs) - return () => { - cancelled = true - clearTimeout(id) - } - }, [timelineSubscriptionKey, refreshCount, spellFetchTimeoutMs]) - // Use refs to avoid dependency issues and ensure latest values in async callbacks const showCountRef = useRef(showCount) const loadingRef = useRef(loading) @@ -1132,8 +1118,15 @@ const NoteList = forwardRef( /> ))} {events.length === 0 && loading ? ( -
{t('Loading...')}