import { keepPreviousData, useInfiniteQuery } from '@tanstack/react-query'; import { FileIcon } from 'lucide-react'; import { Skeleton } from '#/components/atoms/skeleton.jsx'; import { EmptyState } from '#/components/molecules/empty-state.jsx'; import { ErrorNotice } from '#/components/molecules/error-notice.jsx'; import { FileCard } from '#/components/molecules/file-card.jsx'; import { TextLink } from '#/components/molecules/text-link.jsx'; import { FilesHeader } from '#/components/organisms/files-header.jsx'; import { ImageGrid } from '#/components/organisms/image-grid.jsx'; import { get } from '#/lib/api.js'; import { queryKeys } from '#/lib/query.js'; import { cn } from '#/lib/utils.js'; function buildQuery(filters) { const query = new URLSearchParams(); if (filters.kind) query.set('kind', filters.kind); if (filters.app) query.set('app', filters.app); if (filters.unused) query.set('unused', '1'); if (filters.sort === 'largest') query.set('sort', 'largest'); const qs = query.toString(); return qs ? `/blobs?${qs}` : '/blobs'; } export function FilesPage({ filters, filesHref, recordHref, onNavigate }) { const query = buildQuery(filters); const { data, error, isPending, hasNextPage, fetchNextPage, isFetchingNextPage, isPlaceholderData, } = useInfiniteQuery({ queryKey: queryKeys.blobs(filters), queryFn: ({ pageParam }) => get( pageParam ? `${query}${query.includes('?') ? '&' : '?'}cursor=${encodeURIComponent(pageParam)}` : query, ), initialPageParam: null, getNextPageParam: (last) => last.cursor ?? undefined, // Keep the current list (and header) in place while a filter change loads. placeholderData: keepPreviousData, }); const pages = data?.pages ?? []; const blobs = pages.flatMap((page) => page.blobs); const blobBase = pages[0]?.blobBase || null; const facets = pages[0]?.facets || null; return (
{isPending && (
{['a', 'b', 'c'].map((key) => ( ))}
)} {!isPending && !error && facets && facets.total.count === 0 && ( } title="No files yet" description="When apps upload files, like the images in your posts, they will appear here." /> )} {facets && facets.total.count > 0 && ( )}
{!isPending && facets && facets.total.count > 0 && !blobs.length && ( } title="No matching files" description="Nothing matches these filters. Clear one to widen the view." /> )} {filters.kind === 'image' && blobBase ? ( ) : ( blobs.map((blob) => ( )) )}
{hasNextPage && ( fetchNextPage()} disabled={isFetchingNextPage} > {isFetchingNextPage ? 'Loading…' : 'Load more'} )}
); }