From 0cd5720f54d06d70e15a57afa1ee1f28d52ae5da Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Sat, 20 May 2023 13:12:23 +0200 Subject: [PATCH] Fix/request manager infinite swr requests (#306) * Fix RequestManager initial infinite swr requests Functions always returned "null" as the url, which causes SWR to not send the request - useGetSourceLatestMangas - useSourceSearch - useSourceQuickSearch * Use "skipRequest" for infinite SWR requests Is easier to use then overwriting "getEndpoint" only for specific cases * Request correct first page for infinite SWR requests The following endpoints start at page 1 - popular source mangas - latest source mangas - source search - source quick search * Remove wrong parameter from source manga browse requests No idea why I've added this in the first place * Correctly request "latest" and "popular" source mangas The "page" wasn't a param of the query but part of the endpoint --- src/lib/RequestManager.ts | 41 ++++++++++++++++++++------------------- src/typings.ts | 5 +++++ 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/lib/RequestManager.ts b/src/lib/RequestManager.ts index 9fe21f1d..85487f2f 100644 --- a/src/lib/RequestManager.ts +++ b/src/lib/RequestManager.ts @@ -24,6 +24,7 @@ import { IUpdateStatus, Metadata, PaginatedList, + PaginatedMangaList, SourcePreferences, SourceSearchResult, UpdateCheck, @@ -125,23 +126,26 @@ export class RequestManager { }); } - public useSwrInfinite( + public useSwrInfinite< + Data = any, + ErrorResponse = any, + OptionsSWR extends SWRInfiniteOptions = SWRInfiniteOptions, + >( getEndpoint: Required>['getEndpoint'], - { - axiosOptions, - swrOptions, - }: { axiosOptions?: AxiosRequestConfig; swrOptions?: SWRInfiniteConfiguration } = {}, + { axiosOptions, swrOptions }: { axiosOptions?: AxiosRequestConfig; swrOptions?: OptionsSWR } = {}, ): SWRInfiniteResponse { + const { skipRequest, ...swrConfig } = swrOptions ?? {}; + // useSWRInfinite will (by default) revalidate the first page, to check if the other pages have to be revalidated as well const result = useSWRInfinite( (index, previousData) => { const pageEndpoint = getEndpoint(index, previousData); - return pageEndpoint !== null ? this.getValidUrlFor(pageEndpoint) : null; + return pageEndpoint !== null && !skipRequest ? this.getValidUrlFor(pageEndpoint) : null; }, { fetcher: (path: string) => this.restClient.fetcher(path, { httpMethod: HttpMethod.GET, config: axiosOptions }), - ...swrOptions, + ...swrConfig, }, ); @@ -163,7 +167,6 @@ export class RequestManager { * In that case "getEndpoint" has to be passed, which gets used over "endpoint" * * Pass "skipRequest" to make SWR skip sending the request to the server. - * Only works for none "infinite" requests, for "infinite" requests the "getEndpoint" function can return "null". * In case "formData" is passed, "data" gets ignored. */ private doRequest< @@ -265,14 +268,13 @@ export class RequestManager { public useGetSourcePopularMangas( sourceId: string, - extension: string, initialPages?: number, - swrOptions?: SWRInfiniteOptions>, - ): SWRInfiniteResponse> { + swrOptions?: SWRInfiniteOptions, + ): SWRInfiniteResponse { return this.doRequest(SWRHttpMethod.SWR_GET_INFINITE, '', { swrOptions: { getEndpoint: (page, previousData) => - previousData?.hasNextPage ? `source/${sourceId}/popular/${extension}?pageNum=${page}` : null, + previousData?.hasNextPage ?? true ? `source/${sourceId}/popular/${page + 1}` : null, initialSize: initialPages, ...swrOptions, } as typeof swrOptions, @@ -281,14 +283,13 @@ export class RequestManager { public useGetSourceLatestMangas( sourceId: string, - extension: string, initialPages?: number, - swrOptions?: SWRInfiniteOptions>, - ): SWRInfiniteResponse> { + swrOptions?: SWRInfiniteOptions, + ): SWRInfiniteResponse { return this.doRequest(SWRHttpMethod.SWR_GET_INFINITE, '', { swrOptions: { getEndpoint: (page, previousData) => - previousData?.hasNextPage ? `source/${sourceId}/latest/${extension}?pageNum=${page}` : null, + previousData?.hasNextPage ?? true ? `source/${sourceId}/latest/${page + 1}` : null, initialSize: initialPages, ...swrOptions, } as typeof swrOptions, @@ -331,8 +332,8 @@ export class RequestManager { return this.doRequest(HttpMethod.SWR_GET_INFINITE, '', { swrOptions: { getEndpoint: (page, previousData) => - previousData?.hasNextPage - ? `source/${sourceId}/search?searchTerm=${searchTerm}&pageNum=${page}` + previousData?.hasNextPage ?? true + ? `source/${sourceId}/search?searchTerm=${searchTerm}&pageNum=${page + 1}` : null, initialSize: initialPages, ...swrOptions, @@ -351,8 +352,8 @@ export class RequestManager { data: filters, swrOptions: { getEndpoint: (page, previousData) => - previousData?.hasNextPage - ? `source/${sourceId}/quick-search?searchTerm=${searchTerm}&pageNum=${page}` + previousData?.hasNextPage ?? true + ? `source/${sourceId}/quick-search?searchTerm=${searchTerm}&pageNum=${page + 1}` : null, initialSize: initialPages, ...swrOptions, diff --git a/src/typings.ts b/src/typings.ts index 1d15f695..136efe33 100644 --- a/src/typings.ts +++ b/src/typings.ts @@ -330,6 +330,11 @@ export interface PaginatedList { hasNextPage: boolean; } +export type PaginatedMangaList = { + mangaList: IManga[]; + hasNextPage: boolean; +}; + export type NullAndUndefined = T | null | undefined; export type ChapterSortMode = 'fetchedAt' | 'source';