refactor #18
@ -32,6 +32,12 @@ export interface ImportMangaResponseDTO {
|
|||||||
id: number;
|
id: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FileImportRequestDTO {
|
||||||
|
malId?: string;
|
||||||
|
aniListId?: string;
|
||||||
|
files?: Blob[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface AuthenticationRequestDTO {
|
export interface AuthenticationRequestDTO {
|
||||||
email: string;
|
email: string;
|
||||||
password: string;
|
password: string;
|
||||||
@ -154,30 +160,30 @@ export interface MangaListDTO {
|
|||||||
export interface PageMangaListDTO {
|
export interface PageMangaListDTO {
|
||||||
totalPages?: number;
|
totalPages?: number;
|
||||||
totalElements?: number;
|
totalElements?: number;
|
||||||
pageable?: PageableObject;
|
|
||||||
first?: boolean;
|
|
||||||
last?: boolean;
|
|
||||||
size?: number;
|
size?: number;
|
||||||
content?: MangaListDTO[];
|
content?: MangaListDTO[];
|
||||||
number?: number;
|
number?: number;
|
||||||
sort?: SortObject;
|
pageable?: PageableObject;
|
||||||
numberOfElements?: number;
|
numberOfElements?: number;
|
||||||
|
first?: boolean;
|
||||||
|
last?: boolean;
|
||||||
|
sort?: SortObject;
|
||||||
empty?: boolean;
|
empty?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PageableObject {
|
export interface PageableObject {
|
||||||
|
offset?: number;
|
||||||
pageNumber?: number;
|
pageNumber?: number;
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
paged?: boolean;
|
paged?: boolean;
|
||||||
unpaged?: boolean;
|
unpaged?: boolean;
|
||||||
offset?: number;
|
|
||||||
sort?: SortObject;
|
sort?: SortObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SortObject {
|
export interface SortObject {
|
||||||
|
empty?: boolean;
|
||||||
sorted?: boolean;
|
sorted?: boolean;
|
||||||
unsorted?: boolean;
|
unsorted?: boolean;
|
||||||
empty?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DefaultResponseDTOMangaDTO {
|
export interface DefaultResponseDTOMangaDTO {
|
||||||
@ -258,26 +264,19 @@ export interface GenreDTO {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DownloadChapterArchiveParams = {
|
export type DownloadContentArchiveParams = {
|
||||||
archiveFileType: DownloadChapterArchiveArchiveFileType;
|
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
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
||||||
export const DownloadChapterArchiveArchiveFileType = {
|
export const DownloadContentArchiveContentArchiveFileType = {
|
||||||
CBZ: 'CBZ',
|
CBZ: 'CBZ',
|
||||||
CBR: 'CBR',
|
CBR: 'CBR',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type ImportMultipleFilesBody = {
|
|
||||||
/** @minLength 1 */
|
|
||||||
malId: string;
|
|
||||||
/** List of files to upload */
|
|
||||||
files: Blob[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ResolveMangaIngestReviewParams = {
|
export type ResolveMangaIngestReviewParams = {
|
||||||
id: number;
|
id: number;
|
||||||
malId: string;
|
malId: string;
|
||||||
|
|||||||
@ -5,16 +5,20 @@
|
|||||||
* OpenAPI spec version: v0
|
* OpenAPI spec version: v0
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
|
useMutation,
|
||||||
useQuery
|
useQuery
|
||||||
} from '@tanstack/react-query';
|
} from '@tanstack/react-query';
|
||||||
import type {
|
import type {
|
||||||
DataTag,
|
DataTag,
|
||||||
DefinedInitialDataOptions,
|
DefinedInitialDataOptions,
|
||||||
DefinedUseQueryResult,
|
DefinedUseQueryResult,
|
||||||
|
MutationFunction,
|
||||||
QueryClient,
|
QueryClient,
|
||||||
QueryFunction,
|
QueryFunction,
|
||||||
QueryKey,
|
QueryKey,
|
||||||
UndefinedInitialDataOptions,
|
UndefinedInitialDataOptions,
|
||||||
|
UseMutationOptions,
|
||||||
|
UseMutationResult,
|
||||||
UseQueryOptions,
|
UseQueryOptions,
|
||||||
UseQueryResult
|
UseQueryResult
|
||||||
} from '@tanstack/react-query';
|
} from '@tanstack/react-query';
|
||||||
@ -23,6 +27,7 @@ import type {
|
|||||||
DefaultResponseDTOListGenreDTO,
|
DefaultResponseDTOListGenreDTO,
|
||||||
DefaultResponseDTOMangaDTO,
|
DefaultResponseDTOMangaDTO,
|
||||||
DefaultResponseDTOPageMangaListDTO,
|
DefaultResponseDTOPageMangaListDTO,
|
||||||
|
DefaultResponseDTOVoid,
|
||||||
GetMangasParams
|
GetMangasParams
|
||||||
} from '../api.schemas';
|
} from '../api.schemas';
|
||||||
|
|
||||||
@ -33,6 +38,132 @@ type SecondParameter<T extends (...args: never) => unknown> = Parameters<T>[1];
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a manga's metadata and cover
|
||||||
|
* @summary Update manga data
|
||||||
|
*/
|
||||||
|
export const updateMangas = (
|
||||||
|
mangaId: number,
|
||||||
|
options?: SecondParameter<typeof customInstance>,signal?: AbortSignal
|
||||||
|
) => {
|
||||||
|
|
||||||
|
|
||||||
|
return customInstance<DefaultResponseDTOVoid>(
|
||||||
|
{url: `/catalog/mangas/${encodeURIComponent(String(mangaId))}/update`, method: 'POST', signal
|
||||||
|
},
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const getUpdateMangasMutationOptions = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof updateMangas>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
): UseMutationOptions<Awaited<ReturnType<typeof updateMangas>>, 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<Awaited<ReturnType<typeof updateMangas>>, {mangaId: number}> = (props) => {
|
||||||
|
const {mangaId} = props ?? {};
|
||||||
|
|
||||||
|
return updateMangas(mangaId,requestOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { mutationFn, ...mutationOptions }}
|
||||||
|
|
||||||
|
export type UpdateMangasMutationResult = NonNullable<Awaited<ReturnType<typeof updateMangas>>>
|
||||||
|
|
||||||
|
export type UpdateMangasMutationError = unknown
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Update manga data
|
||||||
|
*/
|
||||||
|
export const useUpdateMangas = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof updateMangas>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
, queryClient?: QueryClient): UseMutationResult<
|
||||||
|
Awaited<ReturnType<typeof updateMangas>>,
|
||||||
|
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<typeof customInstance>,signal?: AbortSignal
|
||||||
|
) => {
|
||||||
|
|
||||||
|
|
||||||
|
return customInstance<DefaultResponseDTOVoid>(
|
||||||
|
{url: `/catalog/mangas/update`, method: 'POST', signal
|
||||||
|
},
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const getUpdateMangas1MutationOptions = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof updateMangas1>>, TError,void, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
): UseMutationOptions<Awaited<ReturnType<typeof updateMangas1>>, 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<Awaited<ReturnType<typeof updateMangas1>>, void> = () => {
|
||||||
|
|
||||||
|
|
||||||
|
return updateMangas1(requestOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { mutationFn, ...mutationOptions }}
|
||||||
|
|
||||||
|
export type UpdateMangas1MutationResult = NonNullable<Awaited<ReturnType<typeof updateMangas1>>>
|
||||||
|
|
||||||
|
export type UpdateMangas1MutationError = unknown
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Update all manga data
|
||||||
|
*/
|
||||||
|
export const useUpdateMangas1 = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof updateMangas1>>, TError,void, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
, queryClient?: QueryClient): UseMutationResult<
|
||||||
|
Awaited<ReturnType<typeof updateMangas1>>,
|
||||||
|
TError,
|
||||||
|
void,
|
||||||
|
TContext
|
||||||
|
> => {
|
||||||
|
|
||||||
|
const mutationOptions = getUpdateMangas1MutationOptions(options);
|
||||||
|
|
||||||
|
return useMutation(mutationOptions, queryClient);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Retrieve a list of mangas with their details.
|
* Retrieve a list of mangas with their details.
|
||||||
* @summary Get a list of mangas
|
* @summary Get a list of mangas
|
||||||
|
|||||||
@ -5,23 +5,30 @@
|
|||||||
* OpenAPI spec version: v0
|
* OpenAPI spec version: v0
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
|
useMutation,
|
||||||
useQuery
|
useQuery
|
||||||
} from '@tanstack/react-query';
|
} from '@tanstack/react-query';
|
||||||
import type {
|
import type {
|
||||||
DataTag,
|
DataTag,
|
||||||
DefinedInitialDataOptions,
|
DefinedInitialDataOptions,
|
||||||
DefinedUseQueryResult,
|
DefinedUseQueryResult,
|
||||||
|
MutationFunction,
|
||||||
QueryClient,
|
QueryClient,
|
||||||
QueryFunction,
|
QueryFunction,
|
||||||
QueryKey,
|
QueryKey,
|
||||||
UndefinedInitialDataOptions,
|
UndefinedInitialDataOptions,
|
||||||
|
UseMutationOptions,
|
||||||
|
UseMutationResult,
|
||||||
UseQueryOptions,
|
UseQueryOptions,
|
||||||
UseQueryResult
|
UseQueryResult
|
||||||
} from '@tanstack/react-query';
|
} from '@tanstack/react-query';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
DefaultResponseDTOListMangaContentDTO,
|
DefaultResponseDTOListMangaContentDTO,
|
||||||
DefaultResponseDTOMangaContentImagesDTO
|
DefaultResponseDTOMangaContentImagesDTO,
|
||||||
|
DefaultResponseDTOVoid,
|
||||||
|
DownloadContentArchiveParams,
|
||||||
|
FileImportRequestDTO
|
||||||
} from '../api.schemas';
|
} from '../api.schemas';
|
||||||
|
|
||||||
import { customInstance } from '../../api';
|
import { customInstance } from '../../api';
|
||||||
@ -31,6 +38,147 @@ type SecondParameter<T extends (...args: never) => unknown> = Parameters<T>[1];
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download content as a compressed file by its ID.
|
||||||
|
* @summary Download content archive
|
||||||
|
*/
|
||||||
|
export const downloadContentArchive = (
|
||||||
|
mangaContentId: number,
|
||||||
|
params: DownloadContentArchiveParams,
|
||||||
|
options?: SecondParameter<typeof customInstance>,signal?: AbortSignal
|
||||||
|
) => {
|
||||||
|
|
||||||
|
|
||||||
|
return customInstance<Blob>(
|
||||||
|
{url: `/content/${encodeURIComponent(String(mangaContentId))}/download`, method: 'POST',
|
||||||
|
params,
|
||||||
|
responseType: 'blob', signal
|
||||||
|
},
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const getDownloadContentArchiveMutationOptions = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof downloadContentArchive>>, TError,{mangaContentId: number;params: DownloadContentArchiveParams}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
): UseMutationOptions<Awaited<ReturnType<typeof downloadContentArchive>>, 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<Awaited<ReturnType<typeof downloadContentArchive>>, {mangaContentId: number;params: DownloadContentArchiveParams}> = (props) => {
|
||||||
|
const {mangaContentId,params} = props ?? {};
|
||||||
|
|
||||||
|
return downloadContentArchive(mangaContentId,params,requestOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { mutationFn, ...mutationOptions }}
|
||||||
|
|
||||||
|
export type DownloadContentArchiveMutationResult = NonNullable<Awaited<ReturnType<typeof downloadContentArchive>>>
|
||||||
|
|
||||||
|
export type DownloadContentArchiveMutationError = unknown
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Download content archive
|
||||||
|
*/
|
||||||
|
export const useDownloadContentArchive = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof downloadContentArchive>>, TError,{mangaContentId: number;params: DownloadContentArchiveParams}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
, queryClient?: QueryClient): UseMutationResult<
|
||||||
|
Awaited<ReturnType<typeof downloadContentArchive>>,
|
||||||
|
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<typeof customInstance>,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<DefaultResponseDTOVoid>(
|
||||||
|
{url: `/content/import`, method: 'POST',
|
||||||
|
headers: {'Content-Type': 'multipart/form-data', },
|
||||||
|
data: formData, signal
|
||||||
|
},
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const getImportContentFilesMutationOptions = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof importContentFiles>>, TError,{data: FileImportRequestDTO}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
): UseMutationOptions<Awaited<ReturnType<typeof importContentFiles>>, 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<Awaited<ReturnType<typeof importContentFiles>>, {data: FileImportRequestDTO}> = (props) => {
|
||||||
|
const {data} = props ?? {};
|
||||||
|
|
||||||
|
return importContentFiles(data,requestOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { mutationFn, ...mutationOptions }}
|
||||||
|
|
||||||
|
export type ImportContentFilesMutationResult = NonNullable<Awaited<ReturnType<typeof importContentFiles>>>
|
||||||
|
export type ImportContentFilesMutationBody = FileImportRequestDTO
|
||||||
|
export type ImportContentFilesMutationError = unknown
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Import multiple files
|
||||||
|
*/
|
||||||
|
export const useImportContentFiles = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof importContentFiles>>, TError,{data: FileImportRequestDTO}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
, queryClient?: QueryClient): UseMutationResult<
|
||||||
|
Awaited<ReturnType<typeof importContentFiles>>,
|
||||||
|
TError,
|
||||||
|
{data: FileImportRequestDTO},
|
||||||
|
TContext
|
||||||
|
> => {
|
||||||
|
|
||||||
|
const mutationOptions = getImportContentFilesMutationOptions(options);
|
||||||
|
|
||||||
|
return useMutation(mutationOptions, queryClient);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Retrieve the content for a specific manga/content provider combination.
|
* Retrieve the content for a specific manga/content provider combination.
|
||||||
* @summary Get the content for a specific manga/content provider combination
|
* @summary Get the content for a specific manga/content provider combination
|
||||||
|
|||||||
@ -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<T extends (...args: never) => unknown> = Parameters<T>[1];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a manga from favorites for the logged user.
|
|
||||||
* @summary Unfavorite a manga
|
|
||||||
*/
|
|
||||||
export const setUnfavorite = (
|
|
||||||
id: number,
|
|
||||||
options?: SecondParameter<typeof customInstance>,signal?: AbortSignal
|
|
||||||
) => {
|
|
||||||
|
|
||||||
|
|
||||||
return customInstance<DefaultResponseDTOVoid>(
|
|
||||||
{url: `/mangas/${encodeURIComponent(String(id))}/unfavorite`, method: 'POST', signal
|
|
||||||
},
|
|
||||||
options);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const getSetUnfavoriteMutationOptions = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof setUnfavorite>>, TError,{id: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
): UseMutationOptions<Awaited<ReturnType<typeof setUnfavorite>>, 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<Awaited<ReturnType<typeof setUnfavorite>>, {id: number}> = (props) => {
|
|
||||||
const {id} = props ?? {};
|
|
||||||
|
|
||||||
return setUnfavorite(id,requestOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return { mutationFn, ...mutationOptions }}
|
|
||||||
|
|
||||||
export type SetUnfavoriteMutationResult = NonNullable<Awaited<ReturnType<typeof setUnfavorite>>>
|
|
||||||
|
|
||||||
export type SetUnfavoriteMutationError = unknown
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Unfavorite a manga
|
|
||||||
*/
|
|
||||||
export const useSetUnfavorite = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof setUnfavorite>>, TError,{id: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
, queryClient?: QueryClient): UseMutationResult<
|
|
||||||
Awaited<ReturnType<typeof setUnfavorite>>,
|
|
||||||
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<typeof customInstance>,signal?: AbortSignal
|
|
||||||
) => {
|
|
||||||
|
|
||||||
|
|
||||||
return customInstance<DefaultResponseDTOVoid>(
|
|
||||||
{url: `/mangas/${encodeURIComponent(String(id))}/favorite`, method: 'POST', signal
|
|
||||||
},
|
|
||||||
options);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const getSetFavoriteMutationOptions = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof setFavorite>>, TError,{id: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
): UseMutationOptions<Awaited<ReturnType<typeof setFavorite>>, 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<Awaited<ReturnType<typeof setFavorite>>, {id: number}> = (props) => {
|
|
||||||
const {id} = props ?? {};
|
|
||||||
|
|
||||||
return setFavorite(id,requestOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return { mutationFn, ...mutationOptions }}
|
|
||||||
|
|
||||||
export type SetFavoriteMutationResult = NonNullable<Awaited<ReturnType<typeof setFavorite>>>
|
|
||||||
|
|
||||||
export type SetFavoriteMutationError = unknown
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Favorite a manga
|
|
||||||
*/
|
|
||||||
export const useSetFavorite = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof setFavorite>>, TError,{id: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
, queryClient?: QueryClient): UseMutationResult<
|
|
||||||
Awaited<ReturnType<typeof setFavorite>>,
|
|
||||||
TError,
|
|
||||||
{id: number},
|
|
||||||
TContext
|
|
||||||
> => {
|
|
||||||
|
|
||||||
const mutationOptions = getSetFavoriteMutationOptions(options);
|
|
||||||
|
|
||||||
return useMutation(mutationOptions, queryClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -15,8 +15,7 @@ import type {
|
|||||||
} from '@tanstack/react-query';
|
} from '@tanstack/react-query';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
DefaultResponseDTOVoid,
|
DefaultResponseDTOVoid
|
||||||
DownloadChapterArchiveParams
|
|
||||||
} from '../api.schemas';
|
} from '../api.schemas';
|
||||||
|
|
||||||
import { customInstance } from '../../api';
|
import { customInstance } from '../../api';
|
||||||
@ -89,133 +88,4 @@ export const useFetchAllChapters = <TError = unknown,
|
|||||||
|
|
||||||
return useMutation(mutationOptions, queryClient);
|
return useMutation(mutationOptions, queryClient);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Mark a chapter as read by its ID.
|
|
||||||
* @summary Mark a chapter as read
|
|
||||||
*/
|
|
||||||
export const markAsRead = (
|
|
||||||
chapterId: number,
|
|
||||||
options?: SecondParameter<typeof customInstance>,signal?: AbortSignal
|
|
||||||
) => {
|
|
||||||
|
|
||||||
|
|
||||||
return customInstance<DefaultResponseDTOVoid>(
|
|
||||||
{url: `/mangas/chapters/${encodeURIComponent(String(chapterId))}/mark-as-read`, method: 'POST', signal
|
|
||||||
},
|
|
||||||
options);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const getMarkAsReadMutationOptions = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof markAsRead>>, TError,{chapterId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
): UseMutationOptions<Awaited<ReturnType<typeof markAsRead>>, 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<Awaited<ReturnType<typeof markAsRead>>, {chapterId: number}> = (props) => {
|
|
||||||
const {chapterId} = props ?? {};
|
|
||||||
|
|
||||||
return markAsRead(chapterId,requestOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return { mutationFn, ...mutationOptions }}
|
|
||||||
|
|
||||||
export type MarkAsReadMutationResult = NonNullable<Awaited<ReturnType<typeof markAsRead>>>
|
|
||||||
|
|
||||||
export type MarkAsReadMutationError = unknown
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Mark a chapter as read
|
|
||||||
*/
|
|
||||||
export const useMarkAsRead = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof markAsRead>>, TError,{chapterId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
, queryClient?: QueryClient): UseMutationResult<
|
|
||||||
Awaited<ReturnType<typeof markAsRead>>,
|
|
||||||
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<typeof customInstance>,signal?: AbortSignal
|
|
||||||
) => {
|
|
||||||
|
|
||||||
|
|
||||||
return customInstance<Blob>(
|
|
||||||
{url: `/mangas/chapters/${encodeURIComponent(String(chapterId))}/download`, method: 'POST',
|
|
||||||
params,
|
|
||||||
responseType: 'blob', signal
|
|
||||||
},
|
|
||||||
options);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const getDownloadChapterArchiveMutationOptions = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof downloadChapterArchive>>, TError,{chapterId: number;params: DownloadChapterArchiveParams}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
): UseMutationOptions<Awaited<ReturnType<typeof downloadChapterArchive>>, 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<Awaited<ReturnType<typeof downloadChapterArchive>>, {chapterId: number;params: DownloadChapterArchiveParams}> = (props) => {
|
|
||||||
const {chapterId,params} = props ?? {};
|
|
||||||
|
|
||||||
return downloadChapterArchive(chapterId,params,requestOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return { mutationFn, ...mutationOptions }}
|
|
||||||
|
|
||||||
export type DownloadChapterArchiveMutationResult = NonNullable<Awaited<ReturnType<typeof downloadChapterArchive>>>
|
|
||||||
|
|
||||||
export type DownloadChapterArchiveMutationError = unknown
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Download chapter archive
|
|
||||||
*/
|
|
||||||
export const useDownloadChapterArchive = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof downloadChapterArchive>>, TError,{chapterId: number;params: DownloadChapterArchiveParams}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
, queryClient?: QueryClient): UseMutationResult<
|
|
||||||
Awaited<ReturnType<typeof downloadChapterArchive>>,
|
|
||||||
TError,
|
|
||||||
{chapterId: number;params: DownloadChapterArchiveParams},
|
|
||||||
TContext
|
|
||||||
> => {
|
|
||||||
|
|
||||||
const mutationOptions = getDownloadChapterArchiveMutationOptions(options);
|
|
||||||
|
|
||||||
return useMutation(mutationOptions, queryClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -16,8 +16,6 @@ import type {
|
|||||||
|
|
||||||
import type {
|
import type {
|
||||||
DefaultResponseDTOImportMangaResponseDTO,
|
DefaultResponseDTOImportMangaResponseDTO,
|
||||||
DefaultResponseDTOVoid,
|
|
||||||
ImportMultipleFilesBody,
|
|
||||||
ImportRequestDTO
|
ImportRequestDTO
|
||||||
} from '../api.schemas';
|
} from '../api.schemas';
|
||||||
|
|
||||||
@ -28,74 +26,6 @@ type SecondParameter<T extends (...args: never) => unknown> = Parameters<T>[1];
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accepts multiple files via multipart/form-data and processes them.
|
|
||||||
* @summary Upload multiple files
|
|
||||||
*/
|
|
||||||
export const importMultipleFiles = (
|
|
||||||
importMultipleFilesBody: ImportMultipleFilesBody,
|
|
||||||
options?: SecondParameter<typeof customInstance>,signal?: AbortSignal
|
|
||||||
) => {
|
|
||||||
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(`malId`, importMultipleFilesBody.malId)
|
|
||||||
importMultipleFilesBody.files.forEach(value => formData.append(`files`, value));
|
|
||||||
|
|
||||||
return customInstance<DefaultResponseDTOVoid>(
|
|
||||||
{url: `/manga/import/upload`, method: 'POST',
|
|
||||||
headers: {'Content-Type': 'multipart/form-data', },
|
|
||||||
data: formData, signal
|
|
||||||
},
|
|
||||||
options);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const getImportMultipleFilesMutationOptions = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof importMultipleFiles>>, TError,{data: ImportMultipleFilesBody}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
): UseMutationOptions<Awaited<ReturnType<typeof importMultipleFiles>>, 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<Awaited<ReturnType<typeof importMultipleFiles>>, {data: ImportMultipleFilesBody}> = (props) => {
|
|
||||||
const {data} = props ?? {};
|
|
||||||
|
|
||||||
return importMultipleFiles(data,requestOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return { mutationFn, ...mutationOptions }}
|
|
||||||
|
|
||||||
export type ImportMultipleFilesMutationResult = NonNullable<Awaited<ReturnType<typeof importMultipleFiles>>>
|
|
||||||
export type ImportMultipleFilesMutationBody = ImportMultipleFilesBody
|
|
||||||
export type ImportMultipleFilesMutationError = unknown
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Upload multiple files
|
|
||||||
*/
|
|
||||||
export const useImportMultipleFiles = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof importMultipleFiles>>, TError,{data: ImportMultipleFilesBody}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
, queryClient?: QueryClient): UseMutationResult<
|
|
||||||
Awaited<ReturnType<typeof importMultipleFiles>>,
|
|
||||||
TError,
|
|
||||||
{data: ImportMultipleFilesBody},
|
|
||||||
TContext
|
|
||||||
> => {
|
|
||||||
|
|
||||||
const mutationOptions = getImportMultipleFilesMutationOptions(options);
|
|
||||||
|
|
||||||
return useMutation(mutationOptions, queryClient);
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Imports manga data from content provider into the local database.
|
* Imports manga data from content provider into the local database.
|
||||||
* @summary Import manga from content provider
|
* @summary Import manga from content provider
|
||||||
|
|||||||
@ -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<T extends (...args: never) => unknown> = Parameters<T>[1];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unfollow the manga specified by its ID.
|
|
||||||
* @summary Unfollow the manga specified by its ID
|
|
||||||
*/
|
|
||||||
export const unfollowManga = (
|
|
||||||
mangaId: number,
|
|
||||||
options?: SecondParameter<typeof customInstance>,signal?: AbortSignal
|
|
||||||
) => {
|
|
||||||
|
|
||||||
|
|
||||||
return customInstance<DefaultResponseDTOVoid>(
|
|
||||||
{url: `/mangas/${encodeURIComponent(String(mangaId))}/unfollowManga`, method: 'POST', signal
|
|
||||||
},
|
|
||||||
options);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const getUnfollowMangaMutationOptions = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof unfollowManga>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
): UseMutationOptions<Awaited<ReturnType<typeof unfollowManga>>, 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<Awaited<ReturnType<typeof unfollowManga>>, {mangaId: number}> = (props) => {
|
|
||||||
const {mangaId} = props ?? {};
|
|
||||||
|
|
||||||
return unfollowManga(mangaId,requestOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return { mutationFn, ...mutationOptions }}
|
|
||||||
|
|
||||||
export type UnfollowMangaMutationResult = NonNullable<Awaited<ReturnType<typeof unfollowManga>>>
|
|
||||||
|
|
||||||
export type UnfollowMangaMutationError = unknown
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Unfollow the manga specified by its ID
|
|
||||||
*/
|
|
||||||
export const useUnfollowManga = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof unfollowManga>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
, queryClient?: QueryClient): UseMutationResult<
|
|
||||||
Awaited<ReturnType<typeof unfollowManga>>,
|
|
||||||
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<typeof customInstance>,signal?: AbortSignal
|
|
||||||
) => {
|
|
||||||
|
|
||||||
|
|
||||||
return customInstance<DefaultResponseDTOVoid>(
|
|
||||||
{url: `/mangas/${encodeURIComponent(String(mangaId))}/followManga`, method: 'POST', signal
|
|
||||||
},
|
|
||||||
options);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const getFollowMangaMutationOptions = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof followManga>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
): UseMutationOptions<Awaited<ReturnType<typeof followManga>>, 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<Awaited<ReturnType<typeof followManga>>, {mangaId: number}> = (props) => {
|
|
||||||
const {mangaId} = props ?? {};
|
|
||||||
|
|
||||||
return followManga(mangaId,requestOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return { mutationFn, ...mutationOptions }}
|
|
||||||
|
|
||||||
export type FollowMangaMutationResult = NonNullable<Awaited<ReturnType<typeof followManga>>>
|
|
||||||
|
|
||||||
export type FollowMangaMutationError = unknown
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Follow the manga specified by its ID
|
|
||||||
*/
|
|
||||||
export const useFollowManga = <TError = unknown,
|
|
||||||
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof followManga>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
|
||||||
, queryClient?: QueryClient): UseMutationResult<
|
|
||||||
Awaited<ReturnType<typeof followManga>>,
|
|
||||||
TError,
|
|
||||||
{mangaId: number},
|
|
||||||
TContext
|
|
||||||
> => {
|
|
||||||
|
|
||||||
const mutationOptions = getFollowMangaMutationOptions(options);
|
|
||||||
|
|
||||||
return useMutation(mutationOptions, queryClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
343
src/api/generated/user-interaction/user-interaction.ts
Normal file
343
src/api/generated/user-interaction/user-interaction.ts
Normal file
@ -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<T extends (...args: never) => unknown> = Parameters<T>[1];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unfollow the manga specified by its ID.
|
||||||
|
* @summary Unfollow the manga specified by its ID
|
||||||
|
*/
|
||||||
|
export const unfollowManga = (
|
||||||
|
mangaId: number,
|
||||||
|
options?: SecondParameter<typeof customInstance>,signal?: AbortSignal
|
||||||
|
) => {
|
||||||
|
|
||||||
|
|
||||||
|
return customInstance<DefaultResponseDTOVoid>(
|
||||||
|
{url: `/user-interaction/manga/${encodeURIComponent(String(mangaId))}/unfollow`, method: 'POST', signal
|
||||||
|
},
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const getUnfollowMangaMutationOptions = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof unfollowManga>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
): UseMutationOptions<Awaited<ReturnType<typeof unfollowManga>>, 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<Awaited<ReturnType<typeof unfollowManga>>, {mangaId: number}> = (props) => {
|
||||||
|
const {mangaId} = props ?? {};
|
||||||
|
|
||||||
|
return unfollowManga(mangaId,requestOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { mutationFn, ...mutationOptions }}
|
||||||
|
|
||||||
|
export type UnfollowMangaMutationResult = NonNullable<Awaited<ReturnType<typeof unfollowManga>>>
|
||||||
|
|
||||||
|
export type UnfollowMangaMutationError = unknown
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Unfollow the manga specified by its ID
|
||||||
|
*/
|
||||||
|
export const useUnfollowManga = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof unfollowManga>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
, queryClient?: QueryClient): UseMutationResult<
|
||||||
|
Awaited<ReturnType<typeof unfollowManga>>,
|
||||||
|
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<typeof customInstance>,signal?: AbortSignal
|
||||||
|
) => {
|
||||||
|
|
||||||
|
|
||||||
|
return customInstance<DefaultResponseDTOVoid>(
|
||||||
|
{url: `/user-interaction/manga/${encodeURIComponent(String(mangaId))}/unfavorite`, method: 'POST', signal
|
||||||
|
},
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const getSetUnfavoriteMutationOptions = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof setUnfavorite>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
): UseMutationOptions<Awaited<ReturnType<typeof setUnfavorite>>, 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<Awaited<ReturnType<typeof setUnfavorite>>, {mangaId: number}> = (props) => {
|
||||||
|
const {mangaId} = props ?? {};
|
||||||
|
|
||||||
|
return setUnfavorite(mangaId,requestOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { mutationFn, ...mutationOptions }}
|
||||||
|
|
||||||
|
export type SetUnfavoriteMutationResult = NonNullable<Awaited<ReturnType<typeof setUnfavorite>>>
|
||||||
|
|
||||||
|
export type SetUnfavoriteMutationError = unknown
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Unfavorite a manga
|
||||||
|
*/
|
||||||
|
export const useSetUnfavorite = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof setUnfavorite>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
, queryClient?: QueryClient): UseMutationResult<
|
||||||
|
Awaited<ReturnType<typeof setUnfavorite>>,
|
||||||
|
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<typeof customInstance>,signal?: AbortSignal
|
||||||
|
) => {
|
||||||
|
|
||||||
|
|
||||||
|
return customInstance<DefaultResponseDTOVoid>(
|
||||||
|
{url: `/user-interaction/manga/${encodeURIComponent(String(mangaId))}/follow`, method: 'POST', signal
|
||||||
|
},
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const getFollowMangaMutationOptions = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof followManga>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
): UseMutationOptions<Awaited<ReturnType<typeof followManga>>, 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<Awaited<ReturnType<typeof followManga>>, {mangaId: number}> = (props) => {
|
||||||
|
const {mangaId} = props ?? {};
|
||||||
|
|
||||||
|
return followManga(mangaId,requestOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { mutationFn, ...mutationOptions }}
|
||||||
|
|
||||||
|
export type FollowMangaMutationResult = NonNullable<Awaited<ReturnType<typeof followManga>>>
|
||||||
|
|
||||||
|
export type FollowMangaMutationError = unknown
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Follow the manga specified by its ID
|
||||||
|
*/
|
||||||
|
export const useFollowManga = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof followManga>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
, queryClient?: QueryClient): UseMutationResult<
|
||||||
|
Awaited<ReturnType<typeof followManga>>,
|
||||||
|
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<typeof customInstance>,signal?: AbortSignal
|
||||||
|
) => {
|
||||||
|
|
||||||
|
|
||||||
|
return customInstance<DefaultResponseDTOVoid>(
|
||||||
|
{url: `/user-interaction/manga/${encodeURIComponent(String(mangaId))}/favorite`, method: 'POST', signal
|
||||||
|
},
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const getSetFavoriteMutationOptions = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof setFavorite>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
): UseMutationOptions<Awaited<ReturnType<typeof setFavorite>>, 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<Awaited<ReturnType<typeof setFavorite>>, {mangaId: number}> = (props) => {
|
||||||
|
const {mangaId} = props ?? {};
|
||||||
|
|
||||||
|
return setFavorite(mangaId,requestOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { mutationFn, ...mutationOptions }}
|
||||||
|
|
||||||
|
export type SetFavoriteMutationResult = NonNullable<Awaited<ReturnType<typeof setFavorite>>>
|
||||||
|
|
||||||
|
export type SetFavoriteMutationError = unknown
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Favorite a manga
|
||||||
|
*/
|
||||||
|
export const useSetFavorite = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof setFavorite>>, TError,{mangaId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
, queryClient?: QueryClient): UseMutationResult<
|
||||||
|
Awaited<ReturnType<typeof setFavorite>>,
|
||||||
|
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<typeof customInstance>,signal?: AbortSignal
|
||||||
|
) => {
|
||||||
|
|
||||||
|
|
||||||
|
return customInstance<DefaultResponseDTOVoid>(
|
||||||
|
{url: `/user-interaction/content/${encodeURIComponent(String(mangaContentId))}/read`, method: 'POST', signal
|
||||||
|
},
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const getMarkContentAsReadMutationOptions = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof markContentAsRead>>, TError,{mangaContentId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
): UseMutationOptions<Awaited<ReturnType<typeof markContentAsRead>>, 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<Awaited<ReturnType<typeof markContentAsRead>>, {mangaContentId: number}> = (props) => {
|
||||||
|
const {mangaContentId} = props ?? {};
|
||||||
|
|
||||||
|
return markContentAsRead(mangaContentId,requestOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return { mutationFn, ...mutationOptions }}
|
||||||
|
|
||||||
|
export type MarkContentAsReadMutationResult = NonNullable<Awaited<ReturnType<typeof markContentAsRead>>>
|
||||||
|
|
||||||
|
export type MarkContentAsReadMutationError = unknown
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Mark content as read
|
||||||
|
*/
|
||||||
|
export const useMarkContentAsRead = <TError = unknown,
|
||||||
|
TContext = unknown>(options?: { mutation?:UseMutationOptions<Awaited<ReturnType<typeof markContentAsRead>>, TError,{mangaContentId: number}, TContext>, request?: SecondParameter<typeof customInstance>}
|
||||||
|
, queryClient?: QueryClient): UseMutationResult<
|
||||||
|
Awaited<ReturnType<typeof markContentAsRead>>,
|
||||||
|
TError,
|
||||||
|
{mangaContentId: number},
|
||||||
|
TContext
|
||||||
|
> => {
|
||||||
|
|
||||||
|
const mutationOptions = getMarkContentAsReadMutationOptions(options);
|
||||||
|
|
||||||
|
return useMutation(mutationOptions, queryClient);
|
||||||
|
}
|
||||||
|
|
||||||
@ -6,15 +6,12 @@ import type {
|
|||||||
MangaListDTO,
|
MangaListDTO,
|
||||||
PageMangaListDTO,
|
PageMangaListDTO,
|
||||||
} from "@/api/generated/api.schemas.ts";
|
} 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 { Badge } from "@/components/ui/badge.tsx";
|
||||||
import { Button } from "@/components/ui/button.tsx";
|
import { Button } from "@/components/ui/button.tsx";
|
||||||
import { Card, CardContent } from "@/components/ui/card.tsx";
|
import { Card, CardContent } from "@/components/ui/card.tsx";
|
||||||
import { useAuth } from "@/contexts/AuthContext.tsx";
|
import { useAuth } from "@/contexts/AuthContext.tsx";
|
||||||
import { formatToTwoDigitsDateRange } from "@/utils/dateFormatter.ts";
|
import { formatToTwoDigitsDateRange } from "@/utils/dateFormatter.ts";
|
||||||
|
import {useSetFavorite, useSetUnfavorite} from "@/api/generated/user-interaction/user-interaction.ts";
|
||||||
|
|
||||||
interface MangaCardProps {
|
interface MangaCardProps {
|
||||||
manga: MangaListDTO;
|
manga: MangaListDTO;
|
||||||
@ -63,18 +60,18 @@ export const MangaCard = ({ manga, queryKey }: MangaCardProps) => {
|
|||||||
const isPendingFavoriteChange = isPendingFavorite || isPendingUnfavorite;
|
const isPendingFavoriteChange = isPendingFavorite || isPendingUnfavorite;
|
||||||
|
|
||||||
const handleFavoriteClick = useCallback(
|
const handleFavoriteClick = useCallback(
|
||||||
(isFavorite: boolean) => {
|
(isFavorite: boolean) =>
|
||||||
isFavorite
|
isFavorite
|
||||||
? mutateUnfavorite({ id: manga.id })
|
? mutateUnfavorite({ mangaId: manga.id })
|
||||||
: mutateFavorite({ id: manga.id });
|
: mutateFavorite({ mangaId: manga.id })
|
||||||
},
|
,
|
||||||
[mutateUnfavorite, manga.id, mutateFavorite],
|
[mutateUnfavorite, manga.id, mutateFavorite],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="h-full group overflow-hidden border-border bg-card py-0 gap-0 transition-all hover:border-primary/50 hover:shadow-lg hover:shadow-primary/10 cursor-pointer relative">
|
<Card className="h-full group overflow-hidden border-border bg-card py-0 gap-0 transition-all hover:border-primary/50 hover:shadow-lg hover:shadow-primary/10 cursor-pointer relative">
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
<div className="relative aspect-[2/3] overflow-hidden bg-muted">
|
<div className="relative aspect-2/3 overflow-hidden bg-muted">
|
||||||
<Link to={`/manga/${manga.id}`}>
|
<Link to={`/manga/${manga.id}`}>
|
||||||
<img
|
<img
|
||||||
src={
|
src={
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { FileUp } from "lucide-react";
|
|||||||
import type React from "react";
|
import type React from "react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { useImportMultipleFiles } from "@/api/generated/manga-import/manga-import.ts";
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
@ -13,6 +12,7 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
|
import {useImportContentFiles} from "@/api/generated/content/content.ts";
|
||||||
|
|
||||||
interface MangaManualImportDialogProps {
|
interface MangaManualImportDialogProps {
|
||||||
fileImportDialogOpen: boolean;
|
fileImportDialogOpen: boolean;
|
||||||
@ -24,10 +24,11 @@ export const MangaManualImportDialog = ({
|
|||||||
onFileImportDialogOpenChange,
|
onFileImportDialogOpenChange,
|
||||||
}: MangaManualImportDialogProps) => {
|
}: MangaManualImportDialogProps) => {
|
||||||
const [malId, setMalId] = useState("");
|
const [malId, setMalId] = useState("");
|
||||||
|
const [aniListId, setAniListId] = useState("");
|
||||||
const [dragActive, setDragActive] = useState(false);
|
const [dragActive, setDragActive] = useState(false);
|
||||||
const [files, setFiles] = useState<File[] | null>(null);
|
const [files, setFiles] = useState<File[] | null>(null);
|
||||||
|
|
||||||
const { mutate, isPending } = useImportMultipleFiles({
|
const { mutate, isPending } = useImportContentFiles({
|
||||||
mutation: {
|
mutation: {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setFiles(null);
|
setFiles(null);
|
||||||
@ -45,27 +46,27 @@ export const MangaManualImportDialog = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!malId.trim()) {
|
if (!malId.trim() && !aniListId.trim()) {
|
||||||
alert("Please enter a MyAnimeList manga ID");
|
alert("Please enter either a AniList or a MyAnimeList ID");
|
||||||
return;
|
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)) {
|
mutate({ data: { malId: malId, aniListId: aniListId, files: files } });
|
||||||
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 } });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDrag = (e: React.DragEvent) => {
|
const handleDrag = (e: React.DragEvent) => {
|
||||||
@ -110,10 +111,21 @@ export const MangaManualImportDialog = ({
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="text-sm font-medium">
|
<label className="text-sm font-medium">
|
||||||
MyAnimeList Manga URL (or ID)
|
AniList ID
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
placeholder="e.g., https://myanimelist.net/manga/..."
|
placeholder="17"
|
||||||
|
value={aniListId}
|
||||||
|
onChange={(e) => setAniListId(e.target.value)}
|
||||||
|
className="mt-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="text-sm font-medium">
|
||||||
|
MyAnimeList ID
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
placeholder="20"
|
||||||
value={malId}
|
value={malId}
|
||||||
onChange={(e) => setMalId(e.target.value)}
|
onChange={(e) => setMalId(e.target.value)}
|
||||||
className="mt-2"
|
className="mt-2"
|
||||||
|
|||||||
@ -2,12 +2,9 @@ import { useQueryClient } from "@tanstack/react-query";
|
|||||||
import { Check, Database, Download, Eye, Loader2 } from "lucide-react";
|
import { Check, Database, Download, Eye, Loader2 } from "lucide-react";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { useNavigate } from "react-router";
|
import { useNavigate } from "react-router";
|
||||||
import {
|
|
||||||
useDownloadChapterArchive,
|
|
||||||
} from "@/api/generated/manga-chapter/manga-chapter.ts";
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import ReactCountryFlag from "react-country-flag";
|
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";
|
import {useFetchContentProviderContent} from "@/api/generated/ingestion/ingestion.ts";
|
||||||
|
|
||||||
interface MangaChapterProps {
|
interface MangaChapterProps {
|
||||||
@ -25,13 +22,13 @@ export const MangaChapter = ({
|
|||||||
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const { mutate: mutateDownloadChapterArchive } = useDownloadChapterArchive({
|
const { mutate: mutateDownloadChapterArchive } = useDownloadContentArchive({
|
||||||
mutation: {
|
mutation: {
|
||||||
onSuccess: (data, { chapterId }) => {
|
onSuccess: (data, { mangaContentId }) => {
|
||||||
const url = window.URL.createObjectURL(data);
|
const url = window.URL.createObjectURL(data);
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
link.href = url;
|
link.href = url;
|
||||||
link.setAttribute("download", chapterId + ".cbz");
|
link.setAttribute("download", mangaContentId + ".cbz");
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
link.remove();
|
link.remove();
|
||||||
@ -129,8 +126,8 @@ export const MangaChapter = ({
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
mutateDownloadChapterArchive({
|
mutateDownloadChapterArchive({
|
||||||
chapterId: chapter.id,
|
mangaContentId: chapter.id,
|
||||||
params: { archiveFileType: "CBZ" },
|
params: { contentArchiveFileType: "CBZ" },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="gap-2"
|
className="gap-2"
|
||||||
|
|||||||
@ -1,13 +1,11 @@
|
|||||||
import { ArrowLeft, ChevronLeft, ChevronRight, Home } from "lucide-react";
|
import { ArrowLeft, ChevronLeft, ChevronRight, Home } from "lucide-react";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useNavigate, useParams } from "react-router";
|
import { useNavigate, useParams } from "react-router";
|
||||||
import {
|
|
||||||
useMarkAsRead,
|
|
||||||
} from "@/api/generated/manga-chapter/manga-chapter.ts";
|
|
||||||
import { ThemeToggle } from "@/components/ThemeToggle.tsx";
|
import { ThemeToggle } from "@/components/ThemeToggle.tsx";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { useReadingTracker } from "@/features/chapter/hooks/useReadingTracker.ts";
|
import { useReadingTracker } from "@/features/chapter/hooks/useReadingTracker.ts";
|
||||||
import {useGetMangaContentImages} from "@/api/generated/content/content.ts";
|
import {useGetMangaContentImages} from "@/api/generated/content/content.ts";
|
||||||
|
import {useMarkContentAsRead} from "@/api/generated/user-interaction/user-interaction.ts";
|
||||||
|
|
||||||
const Chapter = () => {
|
const Chapter = () => {
|
||||||
const { setCurrentChapterPage, getCurrentChapterPage } = useReadingTracker();
|
const { setCurrentChapterPage, getCurrentChapterPage } = useReadingTracker();
|
||||||
@ -24,7 +22,7 @@ const Chapter = () => {
|
|||||||
const [infiniteScroll, setInfiniteScroll] = useState(true);
|
const [infiniteScroll, setInfiniteScroll] = useState(true);
|
||||||
|
|
||||||
const { data, isLoading } = useGetMangaContentImages(chapterNumber);
|
const { data, isLoading } = useGetMangaContentImages(chapterNumber);
|
||||||
const { mutate } = useMarkAsRead();
|
const { mutate } = useMarkContentAsRead();
|
||||||
|
|
||||||
// For infinite scroll mode
|
// For infinite scroll mode
|
||||||
const [visibleCount, setVisibleCount] = useState(1);
|
const [visibleCount, setVisibleCount] = useState(1);
|
||||||
@ -35,7 +33,7 @@ const Chapter = () => {
|
|||||||
if (!data || isLoading) return;
|
if (!data || isLoading) return;
|
||||||
|
|
||||||
if (currentPage === data.data?.contentImageKeys.length) {
|
if (currentPage === data.data?.contentImageKeys.length) {
|
||||||
mutate({ chapterId: chapterNumber });
|
mutate({ mangaContentId: chapterNumber });
|
||||||
}
|
}
|
||||||
}, [data, mutate, currentPage]);
|
}, [data, mutate, currentPage]);
|
||||||
|
|
||||||
|
|||||||
@ -13,15 +13,6 @@ import {
|
|||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
import { useNavigate, useParams } from "react-router";
|
import { useNavigate, useParams } from "react-router";
|
||||||
import { toast } from "sonner";
|
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 { ThemeToggle } from "@/components/ThemeToggle.tsx";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@ -38,6 +29,12 @@ import { MangaChapter } from "@/features/manga/MangaChapter.tsx";
|
|||||||
import { formatToTwoDigitsDateRange } from "@/utils/dateFormatter.ts";
|
import { formatToTwoDigitsDateRange } from "@/utils/dateFormatter.ts";
|
||||||
import {useGetManga} from "@/api/generated/catalog/catalog.ts";
|
import {useGetManga} from "@/api/generated/catalog/catalog.ts";
|
||||||
import {useFetchContentProviderContentList} from "@/api/generated/ingestion/ingestion.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 Manga = () => {
|
||||||
const { isAuthenticated } = useAuth();
|
const { isAuthenticated } = useAuth();
|
||||||
@ -86,8 +83,8 @@ const Manga = () => {
|
|||||||
const handleFavoriteClick = useCallback(
|
const handleFavoriteClick = useCallback(
|
||||||
(isFavorite: boolean) =>
|
(isFavorite: boolean) =>
|
||||||
isFavorite
|
isFavorite
|
||||||
? mutateUnfavorite({ id: mangaData?.data?.id ?? -1 })
|
? mutateUnfavorite({ mangaId: mangaData?.data?.id ?? -1 })
|
||||||
: mutateFavorite({ id: mangaData?.data?.id ?? -1 }),
|
: mutateFavorite({ mangaId: mangaData?.data?.id ?? -1 }),
|
||||||
[mutateUnfavorite, mutateFavorite, mangaData?.data?.id],
|
[mutateUnfavorite, mutateFavorite, mangaData?.data?.id],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -146,7 +143,7 @@ const Manga = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<header className="border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
<header className="border-b border-border bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60">
|
||||||
<div className="px-8 py-6">
|
<div className="px-8 py-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-6">
|
<div className="flex items-center gap-6">
|
||||||
@ -171,7 +168,7 @@ const Manga = () => {
|
|||||||
{/* Manga Info Section */}
|
{/* Manga Info Section */}
|
||||||
<div className="grid gap-8 lg:grid-cols-[300px_1fr]">
|
<div className="grid gap-8 lg:grid-cols-[300px_1fr]">
|
||||||
{/* Cover */}
|
{/* Cover */}
|
||||||
<div className="relative aspect-[2/3] overflow-hidden rounded-lg border border-border bg-muted lg:sticky lg:top-8 lg:h-fit">
|
<div className="relative aspect-2/3 overflow-hidden rounded-lg border border-border bg-muted lg:sticky lg:top-8 lg:h-fit">
|
||||||
<img
|
<img
|
||||||
src={
|
src={
|
||||||
(mangaData.data?.coverImageKey &&
|
(mangaData.data?.coverImageKey &&
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user