import { NDKEvent, NDKFilter, NDKKind } from '@nostr-dev-kit/ndk'; import { useInfiniteQuery } from '@tanstack/react-query'; import { useCallback, useEffect, useMemo } from 'react'; import { VList } from 'virtua'; import { useStorage } from '@libs/storage/provider'; import { ArrowRightCircleIcon, LoaderIcon } from '@shared/icons'; import { MemoizedArticleNote, MemoizedFileNote, MemoizedRepost, MemoizedTextNote, NoteWrapper, UnknownNote, } from '@shared/notes'; import { NoteSkeleton } from '@shared/notes/skeleton'; import { TitleBar } from '@shared/titleBar'; import { EventLoader, WidgetWrapper } from '@shared/widgets'; import { useWidgets } from '@stores/widgets'; import { useNostr } from '@utils/hooks/useNostr'; import { toRawEvent } from '@utils/rawEvent'; import { DBEvent } from '@utils/types'; export function LocalNetworkWidget() { const { sub } = useNostr(); const { db } = useStorage(); const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } = useInfiniteQuery({ queryKey: ['local-network-widget'], queryFn: async ({ pageParam = 0 }) => { return await db.getAllEvents(20, pageParam); }, getNextPageParam: (lastPage) => lastPage.nextCursor, }); const isFetched = useWidgets((state) => state.isFetched); const dbEvents = useMemo( () => (data ? data.pages.flatMap((d: { data: DBEvent[] }) => d.data) : []), [data] ); // render event match event kind const renderItem = useCallback( (dbEvent: DBEvent) => { const event: NDKEvent = JSON.parse(dbEvent.event as string); switch (event.kind) { case NDKKind.Text: return ( ); case NDKKind.Repost: return ; case 1063: return ( ); case NDKKind.Article: return ( ); default: return ( ); } }, [dbEvents] ); // subscribe for new event // sub will be managed by lru-cache useEffect(() => { if (db.account && db.account.network && dbEvents.length > 0) { const filter: NDKFilter = { kinds: [NDKKind.Text, NDKKind.Repost], authors: db.account.network, since: Math.floor(Date.now() / 1000), }; sub(filter, async (event) => { const rawEvent = toRawEvent(event); await db.createEvent(rawEvent); }); } }, [data]); return (
{status === 'loading' ? (
) : dbEvents.length === 0 ? ( ) : ( {!isFetched ? : null} {dbEvents.map((item) => renderItem(item))}
{dbEvents.length > 0 ? ( ) : null}
)}
); }