add media detail dialog and infinite loading

This commit is contained in:
dswbx
2025-03-27 09:23:14 +01:00
parent 0424c08a9e
commit f6a511d998
17 changed files with 419 additions and 50 deletions

View File

@@ -1,7 +1,9 @@
import type { Api } from "Api";
import type { FetchPromise, ModuleApi, ResponseObject } from "modules/ModuleApi";
import { FetchPromise, type ModuleApi, type ResponseObject } from "modules/ModuleApi";
import useSWR, { type SWRConfiguration, useSWRConfig } from "swr";
import useSWRInfinite from "swr/infinite";
import { useApi } from "ui/client";
import { useState } from "react";
export const useApiQuery = <
Data,
@@ -27,6 +29,50 @@ export const useApiQuery = <
};
};
/** @attention: highly experimental, use with caution! */
export const useApiInfiniteQuery = <
Data,
RefineFn extends (data: ResponseObject<Data>) => unknown = (data: ResponseObject<Data>) => Data,
>(
fn: (api: Api, page: number) => FetchPromise<Data>,
options?: SWRConfiguration & { refine?: RefineFn },
) => {
const [endReached, setEndReached] = useState(false);
const api = useApi();
const promise = (page: number) => fn(api, page);
const refine = options?.refine ?? ((data: any) => data);
type RefinedData = RefineFn extends (data: ResponseObject<Data>) => infer R ? R : Data;
// @ts-ignore
const swr = useSWRInfinite<RefinedData>(
(index, previousPageData: any) => {
if (previousPageData && !previousPageData.length) {
setEndReached(true);
return null; // reached the end
}
return promise(index).request.url;
},
(url: string) => {
return new FetchPromise(new Request(url), { fetcher: api.fetcher }, refine).execute();
},
{
revalidateFirstPage: false,
},
);
// @ts-ignore
const data = swr.data ? [].concat(...swr.data) : [];
return {
...swr,
_data: swr.data,
data,
endReached,
promise: promise(swr.size),
key: promise(swr.size).key(),
api,
};
};
export const useInvalidate = (options?: { exact?: boolean }) => {
const mutate = useSWRConfig().mutate;
const api = useApi();