refactor all widgets

This commit is contained in:
2023-11-01 08:07:49 +07:00
parent e7738fb128
commit fd5ecc18a9
37 changed files with 1096 additions and 1271 deletions

View File

@@ -1,66 +1,76 @@
import { NDKEvent } from '@nostr-dev-kit/ndk';
import { useQuery } from '@tanstack/react-query';
import { useCallback } from 'react';
import { useInfiniteQuery } from '@tanstack/react-query';
import { useMemo } from 'react';
import { VList } from 'virtua';
import { useNDK } from '@libs/ndk/provider';
import { LoaderIcon } from '@shared/icons';
import { ArrowRightCircleIcon, LoaderIcon } from '@shared/icons';
import { FileNote, NoteWrapper } from '@shared/notes';
import { TitleBar } from '@shared/titleBar';
import { WidgetWrapper } from '@shared/widgets';
import { nHoursAgo } from '@utils/date';
import { FETCH_LIMIT } from '@stores/constants';
import { Widget } from '@utils/types';
export function GlobalFilesWidget({ params }: { params: Widget }) {
const { ndk } = useNDK();
const { status, data } = useQuery({
queryKey: ['global-file-sharing'],
queryFn: async () => {
const events = await ndk.fetchEvents({
// @ts-expect-error, NDK not support file metadata yet
kinds: [1063],
since: nHoursAgo(24),
});
const sortedEvents = [...events].sort((x, y) => y.created_at - x.created_at);
return sortedEvents;
},
refetchOnWindowFocus: false,
});
const { ndk, relayUrls, fetcher } = useNDK();
const { status, data, hasNextPage, isFetchingNextPage, fetchNextPage } =
useInfiniteQuery({
queryKey: ['global-files'],
initialPageParam: 0,
queryFn: async ({
signal,
pageParam,
}: {
signal: AbortSignal;
pageParam: number;
}) => {
const events = await fetcher.fetchLatestEvents(
relayUrls,
{
kinds: [1063],
},
FETCH_LIMIT,
{ asOf: pageParam === 0 ? undefined : pageParam, abortSignal: signal }
);
// render event match event kind
const renderItem = useCallback(
(event: NDKEvent) => {
return (
<NoteWrapper key={event.id} event={event}>
<FileNote />
</NoteWrapper>
);
},
const ndkEvents = events.map((event) => {
return new NDKEvent(ndk, event);
});
return ndkEvents.sort((a, b) => b.created_at - a.created_at);
},
getNextPageParam: (lastPage) => {
const lastEvent = lastPage.at(-1);
if (!lastEvent) return;
return lastEvent.created_at - 1;
},
refetchOnWindowFocus: false,
refetchOnReconnect: false,
});
const allEvents = useMemo(
() => (data ? data.pages.flatMap((page) => page) : []),
[data]
);
return (
<WidgetWrapper>
<TitleBar id={params.id} title={params.title} />
<div className="flex-1">
<VList className="flex-1">
{status === 'pending' ? (
<div className="flex h-full w-full items-center justify-center ">
<div className="inline-flex flex-col items-center justify-center gap-2">
<LoaderIcon className="h-5 w-5 animate-spin text-black dark:text-white" />
<p className="text-sm font-medium text-neutral-500 dark:text-neutral-400">
Loading file sharing event...
</p>
</div>
<div className="flex h-full w-full items-center justify-center">
<LoaderIcon className="h-5 w-5 animate-spin" />
</div>
) : data.length === 0 ? (
) : allEvents.length === 0 ? (
<div className="flex h-full w-full flex-col items-center justify-center px-3">
<div className="flex flex-col items-center gap-4">
<img src="/ghost.png" alt="empty feeds" className="h-16 w-16" />
<div className="text-center">
<h3 className="font-semibold leading-tight text-neutral-900 dark:text-neutral-100">
Oops, it looks like there are no file sharing events.
Oops, it looks like there are no files.
</h3>
<p className="text-neutral-500 dark:text-neutral-400">
You can close this widget
@@ -69,12 +79,32 @@ export function GlobalFilesWidget({ params }: { params: Widget }) {
</div>
</div>
) : (
<VList className="h-full" style={{ contentVisibility: 'auto' }}>
{data.map((item) => renderItem(item))}
<div className="h-14" />
</VList>
allEvents.map((item) => (
<NoteWrapper key={item.id} event={item}>
<FileNote />
</NoteWrapper>
))
)}
</div>
<div className="flex h-16 items-center justify-center px-3 pb-3">
{hasNextPage ? (
<button
type="button"
onClick={() => fetchNextPage()}
disabled={!hasNextPage || isFetchingNextPage}
className="inline-flex h-10 w-max items-center justify-center gap-2 rounded-full bg-blue-500 px-6 font-medium text-white hover:bg-blue-600 focus:outline-none"
>
{isFetchingNextPage ? (
<LoaderIcon className="h-4 w-4 animate-spin" />
) : (
<>
<ArrowRightCircleIcon className="h-5 w-5" />
Load more
</>
)}
</button>
) : null}
</div>
</VList>
</WidgetWrapper>
);
}