import DotsLoading from '@/mainview/components/backgrounds/dots';
import LoadMoreButton from '@/mainview/components/LoadMoreButton';
import { SideDownloadFilters } from '@/mainview/components/SideFilters';
import { downloadLookupFiltersQuery, downloadsLookupQuery } from '@/mainview/scripts/queries/romm';
import { scrollIntoViewHandler } from '@/mainview/scripts/utils';
import { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation';
import { DownloadLookupEntry, DownloadsLookupFilter } from '@simeonradivoev/gameflow-sdk/shared';
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { DownloadIcon, Eye, MessageCircle, Save, Star } from 'lucide-react';
import prettyBytes from 'pretty-bytes';
import { useSessionStorage } from 'usehooks-ts';
export const Route = createFileRoute('/store/tab/download')({
component: RouteComponent,
});
function Download (data: { focusKey: string, match: DownloadLookupEntry; })
{
const navigate = useNavigate();
const handleAction = () => navigate({
to: '/store/details/download/$source/$id', params: {
source: encodeURIComponent(data.match.source),
id: encodeURIComponent(data.match.id)
}
});
const { ref, focusKey } = useFocusable({
focusKey: data.focusKey,
onFocus: (l, p, d) => scrollIntoViewHandler({ behavior: "smooth", block: "center", inline: "center" })(focusKey, ref.current, d),
onEnterPress: handleAction
});
return
{!!data.match.cover_url &&
}
{data.match.name}
{data.match.date?.toDateString()}
{!!data.match.size && - {prettyBytes(data.match.size)}
}
{!!data.match.download_count && - {data.match.download_count}
}
{!!data.match.view_count && - {data.match.view_count}
}
{!!data.match.comment_count && - {data.match.comment_count}
}
{!!data.match.rating && - {data.match.rating}
}
;
}
function Downloads (data: {
pages: {
data: DownloadLookupEntry[];
totalCount: number;
nextPage: number;
}[];
hasNextPage: boolean,
isFetchingNextPage: boolean,
isFetching: boolean,
fetchNextPage: () => void,
error: string | undefined;
})
{
const { ref, focusKey } = useFocusable({ focusKey: 'downloads-list' });
return
{data.pages.flatMap((page, p) => page.data.map((match, i) => ))}
{data.hasNextPage &&
{
if (data.isFetchingNextPage || data.isFetching)
return;
data.fetchNextPage();
}} />}
{!!data.error}
;
}
function RouteComponent ()
{
const [search] = useSessionStorage(`${Route.to}-search`, undefined);
const [filter, setFilter] = useSessionStorage('store-download-lookup-filters', {});
const { data, error, isPending, isFetching, isFetchingNextPage, fetchNextPage, hasNextPage } = useInfiniteQuery({
...downloadsLookupQuery({ ...filter, search }),
maxPages: 10,
refetchOnMount: false
});
const { ref, focusKey } = useFocusable({
focusKey: "main-area",
preferredChildFocusKey: "downloads-list"
});
const { data: lookupFilters } = useQuery(downloadLookupFiltersQuery);
return
{isFetching && }
Results
{isPending ? : {data?.pages[0].totalCount}}
{isPending && }
{data && }
;
}