diff --git a/src/api/generated/api.schemas.ts b/src/api/generated/api.schemas.ts index 92ad298..0a5607b 100644 --- a/src/api/generated/api.schemas.ts +++ b/src/api/generated/api.schemas.ts @@ -32,6 +32,12 @@ export interface ImportMangaResponseDTO { id: number; } +export interface FileImportRequestDTO { + malId?: string; + aniListId?: string; + files?: Blob[]; +} + export interface AuthenticationRequestDTO { email: string; password: string; @@ -154,30 +160,30 @@ export interface MangaListDTO { export interface PageMangaListDTO { totalPages?: number; totalElements?: number; - pageable?: PageableObject; - first?: boolean; - last?: boolean; size?: number; content?: MangaListDTO[]; number?: number; - sort?: SortObject; + pageable?: PageableObject; numberOfElements?: number; + first?: boolean; + last?: boolean; + sort?: SortObject; empty?: boolean; } export interface PageableObject { + offset?: number; pageNumber?: number; pageSize?: number; paged?: boolean; unpaged?: boolean; - offset?: number; sort?: SortObject; } export interface SortObject { + empty?: boolean; sorted?: boolean; unsorted?: boolean; - empty?: boolean; } export interface DefaultResponseDTOMangaDTO { @@ -258,26 +264,19 @@ export interface GenreDTO { name: string; } -export type DownloadChapterArchiveParams = { -archiveFileType: DownloadChapterArchiveArchiveFileType; +export type DownloadContentArchiveParams = { +contentArchiveFileType: DownloadContentArchiveContentArchiveFileType; }; -export type DownloadChapterArchiveArchiveFileType = typeof DownloadChapterArchiveArchiveFileType[keyof typeof DownloadChapterArchiveArchiveFileType]; +export type DownloadContentArchiveContentArchiveFileType = typeof DownloadContentArchiveContentArchiveFileType[keyof typeof DownloadContentArchiveContentArchiveFileType]; // eslint-disable-next-line @typescript-eslint/no-redeclare -export const DownloadChapterArchiveArchiveFileType = { +export const DownloadContentArchiveContentArchiveFileType = { CBZ: 'CBZ', CBR: 'CBR', } as const; -export type ImportMultipleFilesBody = { - /** @minLength 1 */ - malId: string; - /** List of files to upload */ - files: Blob[]; -}; - export type ResolveMangaIngestReviewParams = { id: number; malId: string; diff --git a/src/api/generated/catalog/catalog.ts b/src/api/generated/catalog/catalog.ts index 138e88f..3f19fc2 100644 --- a/src/api/generated/catalog/catalog.ts +++ b/src/api/generated/catalog/catalog.ts @@ -5,16 +5,20 @@ * OpenAPI spec version: v0 */ import { + useMutation, useQuery } from '@tanstack/react-query'; import type { DataTag, DefinedInitialDataOptions, DefinedUseQueryResult, + MutationFunction, QueryClient, QueryFunction, QueryKey, UndefinedInitialDataOptions, + UseMutationOptions, + UseMutationResult, UseQueryOptions, UseQueryResult } from '@tanstack/react-query'; @@ -23,6 +27,7 @@ import type { DefaultResponseDTOListGenreDTO, DefaultResponseDTOMangaDTO, DefaultResponseDTOPageMangaListDTO, + DefaultResponseDTOVoid, GetMangasParams } from '../api.schemas'; @@ -34,6 +39,132 @@ type SecondParameter unknown> = Parameters[1]; /** + * Update a manga's metadata and cover + * @summary Update manga data + */ +export const updateMangas = ( + mangaId: number, + options?: SecondParameter,signal?: AbortSignal +) => { + + + return customInstance( + {url: `/catalog/mangas/${encodeURIComponent(String(mangaId))}/update`, method: 'POST', signal + }, + options); + } + + + +export const getUpdateMangasMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,{mangaId: number}, TContext> => { + +const mutationKey = ['updateMangas']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, {mangaId: number}> = (props) => { + const {mangaId} = props ?? {}; + + return updateMangas(mangaId,requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type UpdateMangasMutationResult = NonNullable>> + + export type UpdateMangasMutationError = unknown + + /** + * @summary Update manga data + */ +export const useUpdateMangas = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + {mangaId: number}, + TContext + > => { + + const mutationOptions = getUpdateMangasMutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + /** + * Update all manga's metadata and cover + * @summary Update all manga data + */ +export const updateMangas1 = ( + + options?: SecondParameter,signal?: AbortSignal +) => { + + + return customInstance( + {url: `/catalog/mangas/update`, method: 'POST', signal + }, + options); + } + + + +export const getUpdateMangas1MutationOptions = (options?: { mutation?:UseMutationOptions>, TError,void, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,void, TContext> => { + +const mutationKey = ['updateMangas1']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, void> = () => { + + + return updateMangas1(requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type UpdateMangas1MutationResult = NonNullable>> + + export type UpdateMangas1MutationError = unknown + + /** + * @summary Update all manga data + */ +export const useUpdateMangas1 = (options?: { mutation?:UseMutationOptions>, TError,void, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + void, + TContext + > => { + + const mutationOptions = getUpdateMangas1MutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + /** * Retrieve a list of mangas with their details. * @summary Get a list of mangas */ diff --git a/src/api/generated/content/content.ts b/src/api/generated/content/content.ts index 74a3470..ff5e554 100644 --- a/src/api/generated/content/content.ts +++ b/src/api/generated/content/content.ts @@ -5,23 +5,30 @@ * OpenAPI spec version: v0 */ import { + useMutation, useQuery } from '@tanstack/react-query'; import type { DataTag, DefinedInitialDataOptions, DefinedUseQueryResult, + MutationFunction, QueryClient, QueryFunction, QueryKey, UndefinedInitialDataOptions, + UseMutationOptions, + UseMutationResult, UseQueryOptions, UseQueryResult } from '@tanstack/react-query'; import type { DefaultResponseDTOListMangaContentDTO, - DefaultResponseDTOMangaContentImagesDTO + DefaultResponseDTOMangaContentImagesDTO, + DefaultResponseDTOVoid, + DownloadContentArchiveParams, + FileImportRequestDTO } from '../api.schemas'; import { customInstance } from '../../api'; @@ -32,6 +39,147 @@ type SecondParameter unknown> = Parameters[1]; /** + * Download content as a compressed file by its ID. + * @summary Download content archive + */ +export const downloadContentArchive = ( + mangaContentId: number, + params: DownloadContentArchiveParams, + options?: SecondParameter,signal?: AbortSignal +) => { + + + return customInstance( + {url: `/content/${encodeURIComponent(String(mangaContentId))}/download`, method: 'POST', + params, + responseType: 'blob', signal + }, + options); + } + + + +export const getDownloadContentArchiveMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{mangaContentId: number;params: DownloadContentArchiveParams}, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,{mangaContentId: number;params: DownloadContentArchiveParams}, TContext> => { + +const mutationKey = ['downloadContentArchive']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, {mangaContentId: number;params: DownloadContentArchiveParams}> = (props) => { + const {mangaContentId,params} = props ?? {}; + + return downloadContentArchive(mangaContentId,params,requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type DownloadContentArchiveMutationResult = NonNullable>> + + export type DownloadContentArchiveMutationError = unknown + + /** + * @summary Download content archive + */ +export const useDownloadContentArchive = (options?: { mutation?:UseMutationOptions>, TError,{mangaContentId: number;params: DownloadContentArchiveParams}, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + {mangaContentId: number;params: DownloadContentArchiveParams}, + TContext + > => { + + const mutationOptions = getDownloadContentArchiveMutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + /** + * Accepts multiple content files via multipart/form-data and processes them. + * @summary Import multiple files + */ +export const importContentFiles = ( + fileImportRequestDTO: FileImportRequestDTO, + options?: SecondParameter,signal?: AbortSignal +) => { + + const formData = new FormData(); +if(fileImportRequestDTO.malId !== undefined) { + formData.append(`malId`, fileImportRequestDTO.malId) + } +if(fileImportRequestDTO.aniListId !== undefined) { + formData.append(`aniListId`, fileImportRequestDTO.aniListId) + } +if(fileImportRequestDTO.files !== undefined) { + fileImportRequestDTO.files.forEach(value => formData.append(`files`, value)); + } + + return customInstance( + {url: `/content/import`, method: 'POST', + headers: {'Content-Type': 'multipart/form-data', }, + data: formData, signal + }, + options); + } + + + +export const getImportContentFilesMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: FileImportRequestDTO}, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,{data: FileImportRequestDTO}, TContext> => { + +const mutationKey = ['importContentFiles']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, {data: FileImportRequestDTO}> = (props) => { + const {data} = props ?? {}; + + return importContentFiles(data,requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type ImportContentFilesMutationResult = NonNullable>> + export type ImportContentFilesMutationBody = FileImportRequestDTO + export type ImportContentFilesMutationError = unknown + + /** + * @summary Import multiple files + */ +export const useImportContentFiles = (options?: { mutation?:UseMutationOptions>, TError,{data: FileImportRequestDTO}, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + {data: FileImportRequestDTO}, + TContext + > => { + + const mutationOptions = getImportContentFilesMutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + /** * Retrieve the content for a specific manga/content provider combination. * @summary Get the content for a specific manga/content provider combination */ diff --git a/src/api/generated/favorite-mangas/favorite-mangas.ts b/src/api/generated/favorite-mangas/favorite-mangas.ts deleted file mode 100644 index 668e002..0000000 --- a/src/api/generated/favorite-mangas/favorite-mangas.ts +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Generated by orval v7.17.0 🍺 - * Do not edit manually. - * OpenAPI definition - * OpenAPI spec version: v0 - */ -import { - useMutation -} from '@tanstack/react-query'; -import type { - MutationFunction, - QueryClient, - UseMutationOptions, - UseMutationResult -} from '@tanstack/react-query'; - -import type { - DefaultResponseDTOVoid -} from '../api.schemas'; - -import { customInstance } from '../../api'; - - -type SecondParameter unknown> = Parameters[1]; - - - -/** - * Remove a manga from favorites for the logged user. - * @summary Unfavorite a manga - */ -export const setUnfavorite = ( - id: number, - options?: SecondParameter,signal?: AbortSignal -) => { - - - return customInstance( - {url: `/mangas/${encodeURIComponent(String(id))}/unfavorite`, method: 'POST', signal - }, - options); - } - - - -export const getSetUnfavoriteMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{id: number}, TContext>, request?: SecondParameter} -): UseMutationOptions>, TError,{id: number}, TContext> => { - -const mutationKey = ['setUnfavorite']; -const {mutation: mutationOptions, request: requestOptions} = options ? - options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? - options - : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, request: undefined}; - - - - - const mutationFn: MutationFunction>, {id: number}> = (props) => { - const {id} = props ?? {}; - - return setUnfavorite(id,requestOptions) - } - - - - - return { mutationFn, ...mutationOptions }} - - export type SetUnfavoriteMutationResult = NonNullable>> - - export type SetUnfavoriteMutationError = unknown - - /** - * @summary Unfavorite a manga - */ -export const useSetUnfavorite = (options?: { mutation?:UseMutationOptions>, TError,{id: number}, TContext>, request?: SecondParameter} - , queryClient?: QueryClient): UseMutationResult< - Awaited>, - TError, - {id: number}, - TContext - > => { - - const mutationOptions = getSetUnfavoriteMutationOptions(options); - - return useMutation(mutationOptions, queryClient); - } - /** - * Set a manga as favorite for the logged user. - * @summary Favorite a manga - */ -export const setFavorite = ( - id: number, - options?: SecondParameter,signal?: AbortSignal -) => { - - - return customInstance( - {url: `/mangas/${encodeURIComponent(String(id))}/favorite`, method: 'POST', signal - }, - options); - } - - - -export const getSetFavoriteMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{id: number}, TContext>, request?: SecondParameter} -): UseMutationOptions>, TError,{id: number}, TContext> => { - -const mutationKey = ['setFavorite']; -const {mutation: mutationOptions, request: requestOptions} = options ? - options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? - options - : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, request: undefined}; - - - - - const mutationFn: MutationFunction>, {id: number}> = (props) => { - const {id} = props ?? {}; - - return setFavorite(id,requestOptions) - } - - - - - return { mutationFn, ...mutationOptions }} - - export type SetFavoriteMutationResult = NonNullable>> - - export type SetFavoriteMutationError = unknown - - /** - * @summary Favorite a manga - */ -export const useSetFavorite = (options?: { mutation?:UseMutationOptions>, TError,{id: number}, TContext>, request?: SecondParameter} - , queryClient?: QueryClient): UseMutationResult< - Awaited>, - TError, - {id: number}, - TContext - > => { - - const mutationOptions = getSetFavoriteMutationOptions(options); - - return useMutation(mutationOptions, queryClient); - } - \ No newline at end of file diff --git a/src/api/generated/manga-chapter/manga-chapter.ts b/src/api/generated/manga-chapter/manga-chapter.ts index cb3fb90..17caf5d 100644 --- a/src/api/generated/manga-chapter/manga-chapter.ts +++ b/src/api/generated/manga-chapter/manga-chapter.ts @@ -15,8 +15,7 @@ import type { } from '@tanstack/react-query'; import type { - DefaultResponseDTOVoid, - DownloadChapterArchiveParams + DefaultResponseDTOVoid } from '../api.schemas'; import { customInstance } from '../../api'; @@ -89,133 +88,4 @@ export const useFetchAllChapters = ,signal?: AbortSignal -) => { - - - return customInstance( - {url: `/mangas/chapters/${encodeURIComponent(String(chapterId))}/mark-as-read`, method: 'POST', signal - }, - options); - } - - - -export const getMarkAsReadMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{chapterId: number}, TContext>, request?: SecondParameter} -): UseMutationOptions>, TError,{chapterId: number}, TContext> => { - -const mutationKey = ['markAsRead']; -const {mutation: mutationOptions, request: requestOptions} = options ? - options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? - options - : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, request: undefined}; - - - - - const mutationFn: MutationFunction>, {chapterId: number}> = (props) => { - const {chapterId} = props ?? {}; - - return markAsRead(chapterId,requestOptions) - } - - - - - return { mutationFn, ...mutationOptions }} - - export type MarkAsReadMutationResult = NonNullable>> - - export type MarkAsReadMutationError = unknown - - /** - * @summary Mark a chapter as read - */ -export const useMarkAsRead = (options?: { mutation?:UseMutationOptions>, TError,{chapterId: number}, TContext>, request?: SecondParameter} - , queryClient?: QueryClient): UseMutationResult< - Awaited>, - TError, - {chapterId: number}, - TContext - > => { - - const mutationOptions = getMarkAsReadMutationOptions(options); - - return useMutation(mutationOptions, queryClient); - } - /** - * Download a chapter as a compressed file by its ID. - * @summary Download chapter archive - */ -export const downloadChapterArchive = ( - chapterId: number, - params: DownloadChapterArchiveParams, - options?: SecondParameter,signal?: AbortSignal -) => { - - - return customInstance( - {url: `/mangas/chapters/${encodeURIComponent(String(chapterId))}/download`, method: 'POST', - params, - responseType: 'blob', signal - }, - options); - } - - - -export const getDownloadChapterArchiveMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{chapterId: number;params: DownloadChapterArchiveParams}, TContext>, request?: SecondParameter} -): UseMutationOptions>, TError,{chapterId: number;params: DownloadChapterArchiveParams}, TContext> => { - -const mutationKey = ['downloadChapterArchive']; -const {mutation: mutationOptions, request: requestOptions} = options ? - options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? - options - : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, request: undefined}; - - - - - const mutationFn: MutationFunction>, {chapterId: number;params: DownloadChapterArchiveParams}> = (props) => { - const {chapterId,params} = props ?? {}; - - return downloadChapterArchive(chapterId,params,requestOptions) - } - - - - - return { mutationFn, ...mutationOptions }} - - export type DownloadChapterArchiveMutationResult = NonNullable>> - - export type DownloadChapterArchiveMutationError = unknown - - /** - * @summary Download chapter archive - */ -export const useDownloadChapterArchive = (options?: { mutation?:UseMutationOptions>, TError,{chapterId: number;params: DownloadChapterArchiveParams}, TContext>, request?: SecondParameter} - , queryClient?: QueryClient): UseMutationResult< - Awaited>, - TError, - {chapterId: number;params: DownloadChapterArchiveParams}, - TContext - > => { - - const mutationOptions = getDownloadChapterArchiveMutationOptions(options); - - return useMutation(mutationOptions, queryClient); - } \ No newline at end of file diff --git a/src/api/generated/manga-import/manga-import.ts b/src/api/generated/manga-import/manga-import.ts index 6591619..d931e6c 100644 --- a/src/api/generated/manga-import/manga-import.ts +++ b/src/api/generated/manga-import/manga-import.ts @@ -16,8 +16,6 @@ import type { import type { DefaultResponseDTOImportMangaResponseDTO, - DefaultResponseDTOVoid, - ImportMultipleFilesBody, ImportRequestDTO } from '../api.schemas'; @@ -29,74 +27,6 @@ type SecondParameter unknown> = Parameters[1]; /** - * Accepts multiple files via multipart/form-data and processes them. - * @summary Upload multiple files - */ -export const importMultipleFiles = ( - importMultipleFilesBody: ImportMultipleFilesBody, - options?: SecondParameter,signal?: AbortSignal -) => { - - const formData = new FormData(); -formData.append(`malId`, importMultipleFilesBody.malId) -importMultipleFilesBody.files.forEach(value => formData.append(`files`, value)); - - return customInstance( - {url: `/manga/import/upload`, method: 'POST', - headers: {'Content-Type': 'multipart/form-data', }, - data: formData, signal - }, - options); - } - - - -export const getImportMultipleFilesMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{data: ImportMultipleFilesBody}, TContext>, request?: SecondParameter} -): UseMutationOptions>, TError,{data: ImportMultipleFilesBody}, TContext> => { - -const mutationKey = ['importMultipleFiles']; -const {mutation: mutationOptions, request: requestOptions} = options ? - options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? - options - : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, request: undefined}; - - - - - const mutationFn: MutationFunction>, {data: ImportMultipleFilesBody}> = (props) => { - const {data} = props ?? {}; - - return importMultipleFiles(data,requestOptions) - } - - - - - return { mutationFn, ...mutationOptions }} - - export type ImportMultipleFilesMutationResult = NonNullable>> - export type ImportMultipleFilesMutationBody = ImportMultipleFilesBody - export type ImportMultipleFilesMutationError = unknown - - /** - * @summary Upload multiple files - */ -export const useImportMultipleFiles = (options?: { mutation?:UseMutationOptions>, TError,{data: ImportMultipleFilesBody}, TContext>, request?: SecondParameter} - , queryClient?: QueryClient): UseMutationResult< - Awaited>, - TError, - {data: ImportMultipleFilesBody}, - TContext - > => { - - const mutationOptions = getImportMultipleFilesMutationOptions(options); - - return useMutation(mutationOptions, queryClient); - } - /** * Imports manga data from content provider into the local database. * @summary Import manga from content provider */ diff --git a/src/api/generated/manga/manga.ts b/src/api/generated/manga/manga.ts deleted file mode 100644 index fc5caf9..0000000 --- a/src/api/generated/manga/manga.ts +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Generated by orval v7.17.0 🍺 - * Do not edit manually. - * OpenAPI definition - * OpenAPI spec version: v0 - */ -import { - useMutation -} from '@tanstack/react-query'; -import type { - MutationFunction, - QueryClient, - UseMutationOptions, - UseMutationResult -} from '@tanstack/react-query'; - -import type { - DefaultResponseDTOVoid -} from '../api.schemas'; - -import { customInstance } from '../../api'; - - -type SecondParameter unknown> = Parameters[1]; - - - -/** - * Unfollow the manga specified by its ID. - * @summary Unfollow the manga specified by its ID - */ -export const unfollowManga = ( - mangaId: number, - options?: SecondParameter,signal?: AbortSignal -) => { - - - return customInstance( - {url: `/mangas/${encodeURIComponent(String(mangaId))}/unfollowManga`, method: 'POST', signal - }, - options); - } - - - -export const getUnfollowMangaMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} -): UseMutationOptions>, TError,{mangaId: number}, TContext> => { - -const mutationKey = ['unfollowManga']; -const {mutation: mutationOptions, request: requestOptions} = options ? - options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? - options - : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, request: undefined}; - - - - - const mutationFn: MutationFunction>, {mangaId: number}> = (props) => { - const {mangaId} = props ?? {}; - - return unfollowManga(mangaId,requestOptions) - } - - - - - return { mutationFn, ...mutationOptions }} - - export type UnfollowMangaMutationResult = NonNullable>> - - export type UnfollowMangaMutationError = unknown - - /** - * @summary Unfollow the manga specified by its ID - */ -export const useUnfollowManga = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} - , queryClient?: QueryClient): UseMutationResult< - Awaited>, - TError, - {mangaId: number}, - TContext - > => { - - const mutationOptions = getUnfollowMangaMutationOptions(options); - - return useMutation(mutationOptions, queryClient); - } - /** - * Follow the manga specified by its ID. - * @summary Follow the manga specified by its ID - */ -export const followManga = ( - mangaId: number, - options?: SecondParameter,signal?: AbortSignal -) => { - - - return customInstance( - {url: `/mangas/${encodeURIComponent(String(mangaId))}/followManga`, method: 'POST', signal - }, - options); - } - - - -export const getFollowMangaMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} -): UseMutationOptions>, TError,{mangaId: number}, TContext> => { - -const mutationKey = ['followManga']; -const {mutation: mutationOptions, request: requestOptions} = options ? - options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? - options - : {...options, mutation: {...options.mutation, mutationKey}} - : {mutation: { mutationKey, }, request: undefined}; - - - - - const mutationFn: MutationFunction>, {mangaId: number}> = (props) => { - const {mangaId} = props ?? {}; - - return followManga(mangaId,requestOptions) - } - - - - - return { mutationFn, ...mutationOptions }} - - export type FollowMangaMutationResult = NonNullable>> - - export type FollowMangaMutationError = unknown - - /** - * @summary Follow the manga specified by its ID - */ -export const useFollowManga = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} - , queryClient?: QueryClient): UseMutationResult< - Awaited>, - TError, - {mangaId: number}, - TContext - > => { - - const mutationOptions = getFollowMangaMutationOptions(options); - - return useMutation(mutationOptions, queryClient); - } - \ No newline at end of file diff --git a/src/api/generated/user-interaction/user-interaction.ts b/src/api/generated/user-interaction/user-interaction.ts new file mode 100644 index 0000000..74ca77c --- /dev/null +++ b/src/api/generated/user-interaction/user-interaction.ts @@ -0,0 +1,343 @@ +/** + * Generated by orval v7.17.0 🍺 + * Do not edit manually. + * OpenAPI definition + * OpenAPI spec version: v0 + */ +import { + useMutation +} from '@tanstack/react-query'; +import type { + MutationFunction, + QueryClient, + UseMutationOptions, + UseMutationResult +} from '@tanstack/react-query'; + +import type { + DefaultResponseDTOVoid +} from '../api.schemas'; + +import { customInstance } from '../../api'; + + +type SecondParameter unknown> = Parameters[1]; + + + +/** + * Unfollow the manga specified by its ID. + * @summary Unfollow the manga specified by its ID + */ +export const unfollowManga = ( + mangaId: number, + options?: SecondParameter,signal?: AbortSignal +) => { + + + return customInstance( + {url: `/user-interaction/manga/${encodeURIComponent(String(mangaId))}/unfollow`, method: 'POST', signal + }, + options); + } + + + +export const getUnfollowMangaMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,{mangaId: number}, TContext> => { + +const mutationKey = ['unfollowManga']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, {mangaId: number}> = (props) => { + const {mangaId} = props ?? {}; + + return unfollowManga(mangaId,requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type UnfollowMangaMutationResult = NonNullable>> + + export type UnfollowMangaMutationError = unknown + + /** + * @summary Unfollow the manga specified by its ID + */ +export const useUnfollowManga = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + {mangaId: number}, + TContext + > => { + + const mutationOptions = getUnfollowMangaMutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + /** + * Remove a manga from favorites for the logged user. + * @summary Unfavorite a manga + */ +export const setUnfavorite = ( + mangaId: number, + options?: SecondParameter,signal?: AbortSignal +) => { + + + return customInstance( + {url: `/user-interaction/manga/${encodeURIComponent(String(mangaId))}/unfavorite`, method: 'POST', signal + }, + options); + } + + + +export const getSetUnfavoriteMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,{mangaId: number}, TContext> => { + +const mutationKey = ['setUnfavorite']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, {mangaId: number}> = (props) => { + const {mangaId} = props ?? {}; + + return setUnfavorite(mangaId,requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type SetUnfavoriteMutationResult = NonNullable>> + + export type SetUnfavoriteMutationError = unknown + + /** + * @summary Unfavorite a manga + */ +export const useSetUnfavorite = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + {mangaId: number}, + TContext + > => { + + const mutationOptions = getSetUnfavoriteMutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + /** + * Follow the manga specified by its ID. + * @summary Follow the manga specified by its ID + */ +export const followManga = ( + mangaId: number, + options?: SecondParameter,signal?: AbortSignal +) => { + + + return customInstance( + {url: `/user-interaction/manga/${encodeURIComponent(String(mangaId))}/follow`, method: 'POST', signal + }, + options); + } + + + +export const getFollowMangaMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,{mangaId: number}, TContext> => { + +const mutationKey = ['followManga']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, {mangaId: number}> = (props) => { + const {mangaId} = props ?? {}; + + return followManga(mangaId,requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type FollowMangaMutationResult = NonNullable>> + + export type FollowMangaMutationError = unknown + + /** + * @summary Follow the manga specified by its ID + */ +export const useFollowManga = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + {mangaId: number}, + TContext + > => { + + const mutationOptions = getFollowMangaMutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + /** + * Set a manga as favorite for the logged user. + * @summary Favorite a manga + */ +export const setFavorite = ( + mangaId: number, + options?: SecondParameter,signal?: AbortSignal +) => { + + + return customInstance( + {url: `/user-interaction/manga/${encodeURIComponent(String(mangaId))}/favorite`, method: 'POST', signal + }, + options); + } + + + +export const getSetFavoriteMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,{mangaId: number}, TContext> => { + +const mutationKey = ['setFavorite']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, {mangaId: number}> = (props) => { + const {mangaId} = props ?? {}; + + return setFavorite(mangaId,requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type SetFavoriteMutationResult = NonNullable>> + + export type SetFavoriteMutationError = unknown + + /** + * @summary Favorite a manga + */ +export const useSetFavorite = (options?: { mutation?:UseMutationOptions>, TError,{mangaId: number}, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + {mangaId: number}, + TContext + > => { + + const mutationOptions = getSetFavoriteMutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + /** + * Mark content as read by its ID. + * @summary Mark content as read + */ +export const markContentAsRead = ( + mangaContentId: number, + options?: SecondParameter,signal?: AbortSignal +) => { + + + return customInstance( + {url: `/user-interaction/content/${encodeURIComponent(String(mangaContentId))}/read`, method: 'POST', signal + }, + options); + } + + + +export const getMarkContentAsReadMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{mangaContentId: number}, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,{mangaContentId: number}, TContext> => { + +const mutationKey = ['markContentAsRead']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, {mangaContentId: number}> = (props) => { + const {mangaContentId} = props ?? {}; + + return markContentAsRead(mangaContentId,requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type MarkContentAsReadMutationResult = NonNullable>> + + export type MarkContentAsReadMutationError = unknown + + /** + * @summary Mark content as read + */ +export const useMarkContentAsRead = (options?: { mutation?:UseMutationOptions>, TError,{mangaContentId: number}, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + {mangaContentId: number}, + TContext + > => { + + const mutationOptions = getMarkContentAsReadMutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + \ No newline at end of file diff --git a/src/features/home/components/MangaCard.tsx b/src/features/home/components/MangaCard.tsx index a8a7320..bb4ecd8 100644 --- a/src/features/home/components/MangaCard.tsx +++ b/src/features/home/components/MangaCard.tsx @@ -6,15 +6,12 @@ import type { MangaListDTO, PageMangaListDTO, } from "@/api/generated/api.schemas.ts"; -import { - useSetFavorite, - useSetUnfavorite, -} from "@/api/generated/favorite-mangas/favorite-mangas.ts"; import { Badge } from "@/components/ui/badge.tsx"; import { Button } from "@/components/ui/button.tsx"; import { Card, CardContent } from "@/components/ui/card.tsx"; import { useAuth } from "@/contexts/AuthContext.tsx"; import { formatToTwoDigitsDateRange } from "@/utils/dateFormatter.ts"; +import {useSetFavorite, useSetUnfavorite} from "@/api/generated/user-interaction/user-interaction.ts"; interface MangaCardProps { manga: MangaListDTO; @@ -63,18 +60,18 @@ export const MangaCard = ({ manga, queryKey }: MangaCardProps) => { const isPendingFavoriteChange = isPendingFavorite || isPendingUnfavorite; const handleFavoriteClick = useCallback( - (isFavorite: boolean) => { + (isFavorite: boolean) => isFavorite - ? mutateUnfavorite({ id: manga.id }) - : mutateFavorite({ id: manga.id }); - }, + ? mutateUnfavorite({ mangaId: manga.id }) + : mutateFavorite({ mangaId: manga.id }) + , [mutateUnfavorite, manga.id, mutateFavorite], ); return ( -
+
{ const [malId, setMalId] = useState(""); + const [aniListId, setAniListId] = useState(""); const [dragActive, setDragActive] = useState(false); const [files, setFiles] = useState(null); - const { mutate, isPending } = useImportMultipleFiles({ + const { mutate, isPending } = useImportContentFiles({ mutation: { onSuccess: () => { setFiles(null); @@ -45,27 +46,27 @@ export const MangaManualImportDialog = ({ return; } - if (!malId.trim()) { - alert("Please enter a MyAnimeList manga ID"); + if (!malId.trim() && !aniListId.trim()) { + alert("Please enter either a AniList or a MyAnimeList ID"); return; } - let id = malId; + // let id = malId; + // + // if (!/^\d+$/.test(malId)) { + // const regex = + // /https?:\/\/(?:www\.)?myanimelist\.net\/(manga)\/(\d+)(?:\/|$)/i; + // const match = malId.match(regex); + // + // if (match) { + // id = match[2]; + // } else { + // alert("Invalid MyAnimeList URL or ID"); + // return; + // } + // } - if (!/^\d+$/.test(malId)) { - const regex = - /https?:\/\/(?:www\.)?myanimelist\.net\/(manga)\/(\d+)(?:\/|$)/i; - const match = malId.match(regex); - - if (match) { - id = match[2]; - } else { - alert("Invalid MyAnimeList URL or ID"); - return; - } - } - - mutate({ data: { malId: id, files } }); + mutate({ data: { malId: malId, aniListId: aniListId, files: files } }); }; const handleDrag = (e: React.DragEvent) => { @@ -110,10 +111,21 @@ export const MangaManualImportDialog = ({
setAniListId(e.target.value)} + className="mt-2" + /> +
+
+ + setMalId(e.target.value)} className="mt-2" diff --git a/src/features/manga/MangaChapter.tsx b/src/features/manga/MangaChapter.tsx index 3e6e105..11893d1 100644 --- a/src/features/manga/MangaChapter.tsx +++ b/src/features/manga/MangaChapter.tsx @@ -2,12 +2,9 @@ import { useQueryClient } from "@tanstack/react-query"; import { Check, Database, Download, Eye, Loader2 } from "lucide-react"; import { useCallback, useState } from "react"; import { useNavigate } from "react-router"; -import { - useDownloadChapterArchive, -} from "@/api/generated/manga-chapter/manga-chapter.ts"; import { Button } from "@/components/ui/button"; import ReactCountryFlag from "react-country-flag"; -import {useGetMangaProviderContent} from "@/api/generated/content/content.ts"; +import {useDownloadContentArchive, useGetMangaProviderContent} from "@/api/generated/content/content.ts"; import {useFetchContentProviderContent} from "@/api/generated/ingestion/ingestion.ts"; interface MangaChapterProps { @@ -25,13 +22,13 @@ export const MangaChapter = ({ const queryClient = useQueryClient(); - const { mutate: mutateDownloadChapterArchive } = useDownloadChapterArchive({ + const { mutate: mutateDownloadChapterArchive } = useDownloadContentArchive({ mutation: { - onSuccess: (data, { chapterId }) => { + onSuccess: (data, { mangaContentId }) => { const url = window.URL.createObjectURL(data); const link = document.createElement("a"); link.href = url; - link.setAttribute("download", chapterId + ".cbz"); + link.setAttribute("download", mangaContentId + ".cbz"); document.body.appendChild(link); link.click(); link.remove(); @@ -129,8 +126,8 @@ export const MangaChapter = ({ variant="outline" onClick={() => mutateDownloadChapterArchive({ - chapterId: chapter.id, - params: { archiveFileType: "CBZ" }, + mangaContentId: chapter.id, + params: { contentArchiveFileType: "CBZ" }, }) } className="gap-2" diff --git a/src/pages/Chapter.tsx b/src/pages/Chapter.tsx index 0a24c8a..ec9e285 100644 --- a/src/pages/Chapter.tsx +++ b/src/pages/Chapter.tsx @@ -1,13 +1,11 @@ import { ArrowLeft, ChevronLeft, ChevronRight, Home } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { useNavigate, useParams } from "react-router"; -import { - useMarkAsRead, -} from "@/api/generated/manga-chapter/manga-chapter.ts"; import { ThemeToggle } from "@/components/ThemeToggle.tsx"; import { Button } from "@/components/ui/button"; import { useReadingTracker } from "@/features/chapter/hooks/useReadingTracker.ts"; import {useGetMangaContentImages} from "@/api/generated/content/content.ts"; +import {useMarkContentAsRead} from "@/api/generated/user-interaction/user-interaction.ts"; const Chapter = () => { const { setCurrentChapterPage, getCurrentChapterPage } = useReadingTracker(); @@ -24,7 +22,7 @@ const Chapter = () => { const [infiniteScroll, setInfiniteScroll] = useState(true); const { data, isLoading } = useGetMangaContentImages(chapterNumber); - const { mutate } = useMarkAsRead(); + const { mutate } = useMarkContentAsRead(); // For infinite scroll mode const [visibleCount, setVisibleCount] = useState(1); @@ -35,7 +33,7 @@ const Chapter = () => { if (!data || isLoading) return; if (currentPage === data.data?.contentImageKeys.length) { - mutate({ chapterId: chapterNumber }); + mutate({ mangaContentId: chapterNumber }); } }, [data, mutate, currentPage]); diff --git a/src/pages/Manga.tsx b/src/pages/Manga.tsx index f53e5c6..4a56077 100644 --- a/src/pages/Manga.tsx +++ b/src/pages/Manga.tsx @@ -13,15 +13,6 @@ import { import { useCallback } from "react"; import { useNavigate, useParams } from "react-router"; import { toast } from "sonner"; -import { - useSetFavorite, - useSetUnfavorite, -} from "@/api/generated/favorite-mangas/favorite-mangas.ts"; -import { - useFollowManga, - useUnfollowManga, -} from "@/api/generated/manga/manga.ts"; -// import { useFetchAllChapters } from "@/api/generated/manga-chapter/manga-chapter.ts"; import { ThemeToggle } from "@/components/ThemeToggle.tsx"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; @@ -38,6 +29,12 @@ import { MangaChapter } from "@/features/manga/MangaChapter.tsx"; import { formatToTwoDigitsDateRange } from "@/utils/dateFormatter.ts"; import {useGetManga} from "@/api/generated/catalog/catalog.ts"; import {useFetchContentProviderContentList} from "@/api/generated/ingestion/ingestion.ts"; +import { + useFollowManga, + useSetFavorite, + useSetUnfavorite, + useUnfollowManga +} from "@/api/generated/user-interaction/user-interaction.ts"; const Manga = () => { const { isAuthenticated } = useAuth(); @@ -86,8 +83,8 @@ const Manga = () => { const handleFavoriteClick = useCallback( (isFavorite: boolean) => isFavorite - ? mutateUnfavorite({ id: mangaData?.data?.id ?? -1 }) - : mutateFavorite({ id: mangaData?.data?.id ?? -1 }), + ? mutateUnfavorite({ mangaId: mangaData?.data?.id ?? -1 }) + : mutateFavorite({ mangaId: mangaData?.data?.id ?? -1 }), [mutateUnfavorite, mutateFavorite, mangaData?.data?.id], ); @@ -146,7 +143,7 @@ const Manga = () => { return (
{/* Header */} -
+
@@ -171,7 +168,7 @@ const Manga = () => { {/* Manga Info Section */}
{/* Cover */} -
+