From 91deb9b7c184920b044fc8d5e1520c98fba91e5d Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sun, 28 Sep 2025 20:58:07 -0700 Subject: [PATCH] add paginated list loader hook --- .../helpers/item-list-paginated-loader.ts | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/renderer/components/item-list/helpers/item-list-paginated-loader.ts diff --git a/src/renderer/components/item-list/helpers/item-list-paginated-loader.ts b/src/renderer/components/item-list/helpers/item-list-paginated-loader.ts new file mode 100644 index 000000000..2ce5b00fa --- /dev/null +++ b/src/renderer/components/item-list/helpers/item-list-paginated-loader.ts @@ -0,0 +1,68 @@ +import { useQuery, useSuspenseQuery, UseSuspenseQueryOptions } from '@tanstack/react-query'; + +import { queryKeys } from '/@/renderer/api/query-keys'; +import { getServerById } from '/@/renderer/store'; + +export interface PaginatedListProps { + query: Omit; + serverId: string; +} + +interface UseItemListPaginatedLoaderProps { + itemsPerPage: number; + listCountQuery: UseSuspenseQueryOptions; + listQueryFn: (args: { apiClientProps: any; query: any }) => Promise<{ items: unknown[] }>; + pageIndex: number; + query: Record; + serverId: string; +} + +function getInitialData(itemCount: number) { + return Array.from({ length: itemCount }, () => undefined); +} + +export const useItemListPaginatedLoader = ({ + itemsPerPage = 100, + listCountQuery, + listQueryFn, + pageIndex, + query = {}, + serverId, +}: UseItemListPaginatedLoaderProps) => { + const { data: totalItemCount } = useSuspenseQuery(listCountQuery); + + const { data } = useQuery({ + gcTime: 1000 * 15, + initialData: getInitialData(totalItemCount), + queryFn: async ({ signal }) => { + const fetchRange = getFetchRange(pageIndex, itemsPerPage); + const startIndex = fetchRange.startIndex; + + const queryParams = { + limit: itemsPerPage, + startIndex: startIndex, + ...query, + }; + + const result = await listQueryFn({ + apiClientProps: { server: getServerById(serverId), signal }, + query: queryParams, + }); + + return result.items; + }, + queryKey: queryKeys.albums.list(serverId, query), + staleTime: 1000 * 15, + }); + + return { data }; +}; + +const getFetchRange = (pageIndex: number, itemsPerPage: number) => { + const startIndex = pageIndex * itemsPerPage; + + return { + limit: itemsPerPage, + startIndex, + }; +};