From b664b4cbeaf2e312a747f14137842e12b30efb67 Mon Sep 17 00:00:00 2001 From: Gauthier Roebroeck Date: Mon, 4 May 2026 14:38:06 +0800 Subject: [PATCH] centralize infinite queries --- next-ui/src/colada/books.ts | 32 +++- next-ui/src/colada/collections.ts | 32 +++- next-ui/src/colada/readlists.ts | 34 +++- next-ui/src/colada/referential.ts | 158 +++++++++++++++++- next-ui/src/colada/series.ts | 32 +++- next-ui/src/components/filter/by/Author.vue | 23 +-- next-ui/src/components/filter/by/Genre.vue | 21 +-- .../src/components/filter/by/Publisher.vue | 23 +-- .../src/components/filter/by/SharingLabel.vue | 23 +-- next-ui/src/components/filter/by/Tag.vue | 21 +-- next-ui/src/pages/collection/[id].vue | 29 +--- next-ui/src/pages/libraries/[id]/books.vue | 29 +--- .../src/pages/libraries/[id]/collections.vue | 26 +-- .../src/pages/libraries/[id]/readlists.vue | 26 +-- next-ui/src/pages/libraries/[id]/series.vue | 29 +--- 15 files changed, 322 insertions(+), 216 deletions(-) diff --git a/next-ui/src/colada/books.ts b/next-ui/src/colada/books.ts index 36e529ce..40255dc2 100644 --- a/next-ui/src/colada/books.ts +++ b/next-ui/src/colada/books.ts @@ -1,7 +1,12 @@ -import { defineMutation, defineQueryOptions, useMutation } from '@pinia/colada' +import { + defineInfiniteQueryOptions, + defineMutation, + defineQueryOptions, + useMutation, +} from '@pinia/colada' import { komgaClient } from '@/api/komga-client' import type { components } from '@/generated/openapi/komga' -import type { PageRequest } from '@/types/PageRequest' +import { PageRequest, type Sort, sortToString } from '@/types/PageRequest' export const QUERY_KEYS_BOOKS = { root: ['books'] as const, @@ -34,6 +39,29 @@ export const bookListQuery = defineQueryOptions( }), ) +export const bookListQueryInfinite = defineInfiniteQueryOptions( + ({ search, sort }: { search: components['schemas']['BookSearch']; sort?: Sort[] }) => ({ + key: QUERY_KEYS_BOOKS.bySearch({ search: search, sort: sort, infinite: true }), + initialPageParam: new PageRequest(0, 50, sort), + query: ({ pageParam }) => + komgaClient + .POST('/api/v1/books/list', { + body: search, + params: { + query: { + page: pageParam.page, + size: pageParam.size, + sort: sort?.map((it) => sortToString(it)), + }, + }, + }) + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + getNextPageParam: (lastPage, _, lastPageParam) => + !lastPage?.last ? lastPageParam.next() : null, + }), +) + export const bookDetailQuery = defineQueryOptions(({ bookId }: { bookId: string }) => ({ key: QUERY_KEYS_BOOKS.byId(bookId), query: () => diff --git a/next-ui/src/colada/collections.ts b/next-ui/src/colada/collections.ts index 122b58c1..b9d2d279 100644 --- a/next-ui/src/colada/collections.ts +++ b/next-ui/src/colada/collections.ts @@ -1,6 +1,12 @@ -import { defineMutation, defineQueryOptions, useMutation, useQueryCache } from '@pinia/colada' +import { + defineInfiniteQueryOptions, + defineMutation, + defineQueryOptions, + useMutation, + useQueryCache, +} from '@pinia/colada' import { komgaClient } from '@/api/komga-client' -import type { PageRequest } from '@/types/PageRequest' +import { PageRequest } from '@/types/PageRequest' import type { components } from '@/generated/openapi/komga' export const QUERY_KEYS_COLLECTIONS = { @@ -37,6 +43,28 @@ export const collectionsListQuery = defineQueryOptions( }), ) +export const collectionsListQueryInfinite = defineInfiniteQueryOptions( + ({ libraryIds }: { libraryIds?: string[] }) => ({ + key: QUERY_KEYS_COLLECTIONS.bySearch({ libraryIds, infinite: true }), + initialPageParam: new PageRequest(0, 50), + query: ({ pageParam }) => + komgaClient + .GET('/api/v1/collections', { + params: { + query: { + library_id: libraryIds, + page: pageParam.page, + size: pageParam.size, + }, + }, + }) + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + getNextPageParam: (lastPage, _, lastPageParam) => + !lastPage?.last ? lastPageParam.next() : null, + }), +) + export const collectionDetailQuery = defineQueryOptions( ({ collectionId }: { collectionId: string }) => ({ key: QUERY_KEYS_COLLECTIONS.byId(collectionId), diff --git a/next-ui/src/colada/readlists.ts b/next-ui/src/colada/readlists.ts index 4b08d7c0..2969112d 100644 --- a/next-ui/src/colada/readlists.ts +++ b/next-ui/src/colada/readlists.ts @@ -1,7 +1,12 @@ -import { defineMutation, defineQueryOptions, useMutation } from '@pinia/colada' +import { + defineInfiniteQueryOptions, + defineMutation, + defineQueryOptions, + useMutation, +} from '@pinia/colada' import { komgaClient } from '@/api/komga-client' import type { components } from '@/generated/openapi/komga' -import type { PageRequest } from '@/types/PageRequest' +import { PageRequest } from '@/types/PageRequest' export const QUERY_KEYS_READLIST = { root: ['readlists'] as const, @@ -40,6 +45,31 @@ export const readListsListQuery = defineQueryOptions( }), ) +export const readListsListQueryInfinite = defineInfiniteQueryOptions( + ({ libraryIds }: { libraryIds?: string[] }) => ({ + key: QUERY_KEYS_READLIST.bySearch({ + libraryIds: libraryIds, + infinite: true, + }), + initialPageParam: new PageRequest(0, 50), + query: ({ pageParam }) => + komgaClient + .GET('/api/v1/readlists', { + params: { + query: { + page: pageParam.page, + size: pageParam.size, + libraryIds: libraryIds, + }, + }, + }) + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + getNextPageParam: (lastPage, _, lastPageParam) => + !lastPage?.last ? lastPageParam.next() : null, + }), +) + export const useCreateReadList = defineMutation(() => { return useMutation({ mutation: (readList: components['schemas']['ReadListCreationDto']) => diff --git a/next-ui/src/colada/referential.ts b/next-ui/src/colada/referential.ts index 7422bb71..861b74d8 100644 --- a/next-ui/src/colada/referential.ts +++ b/next-ui/src/colada/referential.ts @@ -1,6 +1,6 @@ -import { defineQueryOptions } from '@pinia/colada' +import { defineInfiniteQueryOptions, defineQueryOptions } from '@pinia/colada' import { komgaClient } from '@/api/komga-client' -import type { PageRequest } from '@/types/PageRequest' +import { PageRequest } from '@/types/PageRequest' export const authorsQuery = defineQueryOptions( ({ @@ -44,6 +44,45 @@ export const authorsQuery = defineQueryOptions( }, ) +export const authorsNamesQueryInfinite = defineInfiniteQueryOptions( + ({ + role, + library_id, + collection_id, + series_id, + readlist_id, + }: { + role?: string + library_id?: string[] + collection_id?: string[] + series_id?: string[] + readlist_id?: string[] + }) => { + const queryParams = { + role: role, + library_id: library_id, + collection_id: collection_id, + series_id: series_id, + readlist_id: readlist_id, + } + return { + key: ['authors', queryParams, { infinite: true }], + initialPageParam: new PageRequest(0, 50), + query: ({ pageParam }) => + komgaClient + .GET('/api/v2/authors/names', { + params: { + query: { ...queryParams, ...pageParam }, + }, + }) + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + getNextPageParam: (lastPage, _, lastPageParam) => + !lastPage?.last ? lastPageParam.next() : null, + } + }, +) + export const genresQuery = defineQueryOptions( ({ search, @@ -77,6 +116,30 @@ export const genresQuery = defineQueryOptions( }, ) +export const genresQueryInfinite = defineInfiniteQueryOptions( + ({ library_id, collection_id }: { library_id?: string[]; collection_id?: string[] }) => { + const queryParams = { + library_id: library_id, + collection_id: collection_id, + } + return { + key: ['genres', queryParams, { infinite: true }], + initialPageParam: new PageRequest(0, 50), + query: ({ pageParam }) => + komgaClient + .GET('/api/v2/genres', { + params: { + query: { ...queryParams, ...pageParam }, + }, + }) + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + getNextPageParam: (lastPage, _, lastPageParam) => + !lastPage?.last ? lastPageParam.next() : null, + } + }, +) + export const tagsQuery = defineQueryOptions( ({ search, @@ -119,6 +182,45 @@ export const tagsQuery = defineQueryOptions( }, ) +export const tagsQueryInfinite = defineInfiniteQueryOptions( + ({ + library_id, + collection_id, + series_id, + readlist_id, + include, + }: { + library_id?: string[] + collection_id?: string[] + series_id?: string[] + readlist_id?: string[] + include?: 'SERIES' | 'BOOK' | 'BOTH' + }) => { + const queryParams = { + library_id: library_id, + collection_id: collection_id, + series_id: series_id, + readlist_id: readlist_id, + include: include, + } + return { + key: ['tags', queryParams, { infinite: true }], + initialPageParam: new PageRequest(0, 50), + query: ({ pageParam }) => + komgaClient + .GET('/api/v2/tags', { + params: { + query: { ...queryParams, ...pageParam }, + }, + }) + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + getNextPageParam: (lastPage, _, lastPageParam) => + !lastPage?.last ? lastPageParam.next() : null, + } + }, +) + export const publishersQuery = defineQueryOptions( ({ search, @@ -152,6 +254,33 @@ export const publishersQuery = defineQueryOptions( }, ) +export const publishersQueryInfinite = defineInfiniteQueryOptions( + ({ library_id, collection_id }: { library_id?: string[]; collection_id?: string[] }) => { + const queryParams = { + library_id: library_id, + collection_id: collection_id, + } + return { + key: ['publishers', queryParams, { infinite: true }], + initialPageParam: new PageRequest(0, 50), + query: ({ pageParam }) => + komgaClient + .GET('/api/v2/publishers', { + params: { + query: { + ...queryParams, + ...pageParam, + }, + }, + }) + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + getNextPageParam: (lastPage, _, lastPageParam) => + !lastPage?.last ? lastPageParam.next() : null, + } + }, +) + export const sharingLabelsQuery = defineQueryOptions( ({ search, @@ -185,6 +314,30 @@ export const sharingLabelsQuery = defineQueryOptions( }, ) +export const sharingLabelsQueryInfinite = defineInfiniteQueryOptions( + ({ library_id, collection_id }: { library_id?: string[]; collection_id?: string[] }) => { + const queryParams = { + library_id: library_id, + collection_id: collection_id, + } + return { + key: ['sharing-labels', queryParams, { infinite: true }], + initialPageParam: new PageRequest(0, 50), + query: ({ pageParam }) => + komgaClient + .GET('/api/v2/sharing-labels', { + params: { + query: { ...queryParams, ...pageParam }, + }, + }) + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + getNextPageParam: (lastPage, _, lastPageParam) => + !lastPage?.last ? lastPageParam.next() : null, + } + }, +) + export const languagesQuery = defineQueryOptions( ({ search, @@ -277,3 +430,4 @@ export const ageRatingsQuery = defineQueryOptions( } }, ) +export class authorsQueryInfinite {} diff --git a/next-ui/src/colada/series.ts b/next-ui/src/colada/series.ts index ab6d7ea6..8fffb3c9 100644 --- a/next-ui/src/colada/series.ts +++ b/next-ui/src/colada/series.ts @@ -1,7 +1,12 @@ -import { defineMutation, defineQueryOptions, useMutation } from '@pinia/colada' +import { + defineInfiniteQueryOptions, + defineMutation, + defineQueryOptions, + useMutation, +} from '@pinia/colada' import { komgaClient } from '@/api/komga-client' import type { components } from '@/generated/openapi/komga' -import type { PageRequest } from '@/types/PageRequest' +import { PageRequest, type Sort, sortToString } from '@/types/PageRequest' import { seriesMetadataToDto } from '@/functions/series' export const QUERY_KEYS_SERIES = { @@ -35,6 +40,29 @@ export const seriesListQuery = defineQueryOptions( }), ) +export const seriesListQueryInfinite = defineInfiniteQueryOptions( + ({ search, sort }: { search: components['schemas']['SeriesSearch']; sort?: Sort[] }) => ({ + key: QUERY_KEYS_SERIES.bySearch({ search: search, sort: sort, infinite: true }), + initialPageParam: new PageRequest(0, 50, sort), + query: ({ pageParam }) => + komgaClient + .POST('/api/v1/series/list', { + body: search, + params: { + query: { + page: pageParam.page, + size: pageParam.size, + sort: sort?.map((it) => sortToString(it)), + }, + }, + }) + // unwrap the openapi-fetch structure on success + .then((res) => res.data), + getNextPageParam: (lastPage, _, lastPageParam) => + !lastPage?.last ? lastPageParam.next() : null, + }), +) + export const seriesDetailQuery = defineQueryOptions(({ seriesId }: { seriesId: string }) => ({ key: QUERY_KEYS_SERIES.byId(seriesId), query: () => diff --git a/next-ui/src/components/filter/by/Author.vue b/next-ui/src/components/filter/by/Author.vue index d2380615..02b6e271 100644 --- a/next-ui/src/components/filter/by/Author.vue +++ b/next-ui/src/components/filter/by/Author.vue @@ -15,9 +15,8 @@